Cut, Copy and Paste in JavaScript with the Clipboard API – SitePoint

Accessing the OS clipboard using browser JavaScript has been possible for several years using document.execCommand().
Unfortunately, there are some problems:
clipboard access is synchronous, which has performance and security implications
support is patchy, especially on older versions of Safari on macOS and iOS
permissions access varies across browsers, and
the API could never be considered elegant
It’s finally been superseded by a new asynchronous Clipboard API. It’s new, and no browser supports all features, but it’s easier to use and more robust.
Why Would an App Need to Access the Clipboard?
As a developer, you’ll know how the clipboard works and regularly use the following keyboard shortcuts:
Ctrl | Cmd + C to copy
Ctrl | Cmd + X to cut
Ctrl | Cmd + V to paste
Those with less computing experience won’t necessarily have that knowledge. They may also be using a touch-screen device where keyboard shortcuts aren’t available. Offering easy-to-use cut and paste icons can be useful.
Additionally, you may want to modify content when a clipboard action is completed, such as adding or removing formatting.
Clipboard Access is Dangerous!
Accessing the clipboard programmatically raises several security concerns:
Users often copy passwords or private information so no page should be able to arbitrarily read clipboard data.
Pages should be restricted when adding data to the clipboard. A nefarious page could replace copied text with a dangerous command or even an executable file.
To avoid potential issues, the Clipboard API can only be used on pages served over HTTPS (localhost is also permitted). When running in an iframe, the parent page must also grant clipboard-read and/or clipboard-write permissions:

The API is only available to the active browser tab (not background tabs) and can only be triggered by a user interaction such as a click. When necessary, the user will be prompted for permission to read clipboard data:

This alert is shown when a page first requests clipboard access. It shouldn’t cause any issues, given that the API is asynchronous and returns a Promise. It’s also possible to examine and request the status using the Permissions API.
Clipboard API Feature Detection
The Clipboard API is available when navigator.clipboard returns a truthy result. For example:
if (navigator.clipboard) {

console.log(‘Clipboard API available’);

}

However, this doesn’t guarantee the browser supports all features, so it’s necessary to make further checks. For example, at the time of writing, Chrome supports the API’s readText() method, while Firefox doesn’t.
Copy and Paste Text
Copying and pasting text will be a useful option in most applications. The API is refreshingly simple:

await navigator.clipboard.writeText(‘This text is now in the clipboard’);

let text = await navigator.clipboard.readText();

You’ll require considerably more code to detect support and handle errors …
View the Clipboard API text demonstration
The code can be downloaded from GitHub. Refer to clipboardtext.js for the JavaScript.
This example implements text copying when a data-copy attribute is added any HTML element such as a button. You can set this value to either of these:
a hard-coded string — such as data-copy=”copy this to the clipboard”.
a CSS selector — such as data-copy=”#mysection”. The text content of the first matching element is then copied.
Optionally, you can set a custom success message in a data-done attribute:

The button is only shown when navigator.clipboard.writeText() is supported. When clicked, the JavaScript event handler locates the text, copies it to the clipboard, and shows an animated success message.
The text paste button is very similar except it defines a data-paste attribute which must point to a DOM node:

Copy and Paste Data
The Clipboard API’s readText() and writeText() are convenience options for the more generic read() and write() methods. These have less browser support but are able to copy and paste any type of data such as binary images.
Copying requires blob data typically returned by a fetch() or canvas.toBlob() method. This is passed to a ClipboardItem constructor so it can be written to the clipboard:
const
image = await fetch(‘myimage.png’),
blob = await image.blob();

await navigator.clipboard.write([
new ClipboardItem({ [blob.type]: blob })
]);

Pasting is more complex because multiple ClipboardItem objects can be returned with differing content types. It’s therefore necessary to iterate through each type until a useful format is found. For example:
const clipboardItems = await navigator.clipboard.read();

for (const clipboardItem of clipboardItems) {

for (const type of clipboardItem.types) {

if (type === ‘image/png’) {

return await clipboardItem.getType(type);

}

}

}

View the Clipboard API image demonstration (supported in Chromium-based browsers).
The code can be downloaded from GitHub. Refer to clipboardblob.js for the JavaScript.
This works in a similar way to the text demonstration, in that copy and paste buttons must point to DOM elements using a CSS selector in data-copyblob and data-pasteblob attributes. For example:

Try copying image data from a graphics application, then use the paste button.
Cut, Copy, and Paste Events
The cut, copy, and paste events fire whenever the user initiates a clipboard action in the browser — typically with right-click menus or the keyboard shortcuts mentioned above. This is supported in most browsers and handler functions can intercept the events to make changes using a clipboardData object passed as a parameter.
The following function forces all cut or copied text to be uppercase. Note that e.preventDefault() stops the default cut/copy action which would override it:
body.addEventListener(‘cut’, cutCopyHandler);
body.addEventListener(‘copy’, cutCopyHandler);

function cutCopyHandler(e) {

const selection = document.getSelection();

e.clipboardData.setData(
‘text/plain’,
selection.toString().toUpperCase()
);

if (e.type === ‘cut’) selection.deleteFromDocument();

e.preventDefault();

}

The following code attaches a paste handler to a specific