The Clipboard API lets your page put text on the user’s clipboard (the classic “Copy” button) or read from it.
> The clipboard needs a real page, a secure context (HTTPS) and a user action, so the Try it sandbox blocks it. The code below is for your own pages.
Copying text
async function copyText(text) {
try {
await navigator.clipboard.writeText(text);
return true;
} catch (error) {
return false; // blocked, or not allowed
}
}
writeText returns a promise. It normally works when called from a user gesture, such as a click handler.
A Copy button
<code id="snippet">npm install my-package</code>
<button id="copy">Copy</button>
<span id="status" role="status"></span>
document.querySelector("#copy").addEventListener("click", async () => {
const text = document.querySelector("#snippet").textContent;
const status = document.querySelector("#status");
try {
await navigator.clipboard.writeText(text);
status.textContent = "Copied!";
} catch {
status.textContent = "Could not copy. Select the text and press Ctrl+C.";
}
setTimeout(() => { status.textContent = ""; }, 2000);
});
Using role="status" makes screen readers announce “Copied!”.
Reading from the clipboard
const text = await navigator.clipboard.readText();
Reading is more sensitive (the clipboard might contain passwords), so browsers ask for permission, and some only allow it on a user gesture or in a focused page. It may be denied. Always handle the failure.
Requirements
| Requirement | Why |
|---|---|
| Secure context (HTTPS or localhost) | the API is not available on plain HTTP |
| User gesture (click, key press) | prevents silent clipboard changes |
| Page has focus | for reads and often for writes |
| Permission (for reads) | privacy |
Feature detection and fallback
async function copy(text) {
if (navigator.clipboard?.writeText) {
await navigator.clipboard.writeText(text);
return;
}
// old fallback: select a hidden textarea and use the legacy command
const area = document.createElement("textarea");
area.value = text;
area.setAttribute("readonly", "");
area.style.position = "fixed";
area.style.opacity = "0";
document.body.append(area);
area.select();
document.execCommand("copy"); // deprecated, but still widely supported
area.remove();
}
document.execCommand("copy") is deprecated. Keep it only as a fallback for old browsers.
The copy and paste events
You can also react when the user copies or pastes:
document.addEventListener("copy", event => {
console.log("User copied text");
});
Copying more than text
navigator.clipboard.write() can copy images and rich content using ClipboardItem. Support is more limited, so check it.
Good practice
- Give visible feedback (“Copied!”).
- Never write to the clipboard without the user asking for it.
- Do not read the clipboard unless the user clearly triggers it (a “Paste” button).
- Offer a manual alternative, such as selected text.