Intercepting Clipboard Events with JavaScript

The JavaScript copy event allows us to react to clipboard events within our web applications. Although still in a working draft state, support is pretty good across modern browsers.
Handling this event we are able to modify clipboard contents, but cannot read from the clipboard data (as this would otherwise be a security concern). What can do ‑ however ‑ is use window.getSelection() to identify the highlighted items.
Implementing this is as simple as tying an event listener to document:
document.addEventListener('copy', handleClipboard);From there, we can modify what happens. If we really just wanted to stop people from being able to copy at all, we can just use event.preventDefault():
const handleClipboard = e => e.preventDefault();My use for this is a little involved: I want to make sure that people can copy off my website, but I also want to make sure that they are aware that they are copying copyrighted work.
const handleClipboard = (e) => { const selection = window.getSelection().toString(); const thisURL = `https://johnkavanagh.co.uk${window.location.pathname}`; const copyright = `Copyright (c) ${getCurrentYear()} John Kavanagh. All rights reserved.`; const source = `Original source: https://johnkavanagh.co.uk${window.location.pathname}`; const newClipboard = `${selection}\n\n${copyright}\n${source}`; e.clipboardData.setData('text/plain', newClipboard); e.preventDefault();};What this is doing is:
- Getting the selected text from the
windowobject, as a string; - Building a copyright notice (over two lines);
- Combining the selection and copyright notice together with line breaks;
- Placing this within the clipboard (in place of the original copy) via
setData.
When you paste back off your clipboard you will get:
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum fringilla arcu.Copyright (c) 2021 John Kavanagh. All rights reserved. Original source: https://johnkavanagh.co.uk/page-visited/You can easily extend this yet further to avoid the copyright notice from being injected where the user is ‑ for example ‑ only copying out of a <code> or <pre> block:
const { path } = e;const { tagName } = path[0];const isCode = tagName === 'PRE' || tagName === 'CODE';if (isCode) { return;}I also modify this a little further so that I can avoid intercepting very short copies (e.g., where somebody is copying my email address), and to generate a store of what has been copied off the site to try and head off potential duplicate content issues. You can probably work those bits out for yourself, though!
Permissions and User Expectation
Clipboard behaviour is more sensitive than ordinary click handling because it touches something the user is deliberately taking away from the page. If you intercept a copy event, keep the change predictable and visible. Quietly adding tracking text, changing the copied content or blocking copy altogether usually creates more distrust than value.
The modern Clipboard API also has permission and security constraints, especially for reading from the clipboard. Writing during an explicit copy action is one thing; reading clipboard contents without a clear user action is treated much more carefully by browsers.
Prefer Explicit Controls
For code snippets, share text or generated references, a visible "copy" button is often better than intercepting every copy event on the page. It gives the user a clear target and keeps the behaviour scoped to the content that actually needs it.