The async Clipboard API replaced the old, synchronous document.execCommand("copy") hack with a permission-aware, Promise-based interface for reading and writing clipboard content.
1The Clipboard API | JavaScript Tutorial - In-Depth Guide Part 1
navigator.clipboard.writeText() copies plain text to the system clipboard, returning a Promise that resolves once the copy succeeds.
async function copyText(text) {
await navigator.clipboard.writeText(text);
console.log('Copied!');
}Writing Text
2The Clipboard API | JavaScript Tutorial - In-Depth Guide Part 2
Clipboard access requires a secure context (HTTPS, or localhost) and, in most browsers, must be triggered by a direct user action like a click.
button.addEventListener('click', async () => {
await navigator.clipboard.writeText('Copied via user click');
});Secure Context + User Gesture
3The Clipboard API | JavaScript Tutorial - In-Depth Guide Part 3
navigator.clipboard.readText() reads plain text FROM the clipboard, but requires explicit permission and only works in a secure, user-initiated context too.
button.addEventListener('click', async () => {
const text = await navigator.clipboard.readText();
console.log('Clipboard contains:', text);
});Reading from the Clipboard
4The Clipboard API | JavaScript Tutorial - In-Depth Guide Part 4
writeText() can fail — due to permissions, an insecure context, or a browser that doesn't support it — so always wrap it in a try/catch with a fallback.
async function copyWithFallback(text) {
try {
await navigator.clipboard.writeText(text);
} catch {
// Fallback: legacy execCommand or manual selection
fallbackCopy(text);
}
}Handling Failures Gracefully
5The Clipboard API | JavaScript Tutorial - In-Depth Guide Part 5
The Clipboard API also supports writing rich content (like images) via navigator.clipboard.write() with ClipboardItem objects, not just plain text.
async function copyImage(blob) {
await navigator.clipboard.write([
new ClipboardItem({ [blob.type]: blob }),
]);
}Copying Rich Content
6Step-by-Step Breakdown
navigator.clipboard.writeText() copies plain text to the system clipboard, returning a Promise that resolves once the copy succeeds.
Clipboard access requires a secure context (HTTPS, or localhost) and, in most browsers, must be triggered by a direct user action like a click.
Checkpoint: Does the Clipboard API generally require the call to originate from a real user action like a click, rather than a background timer?
- →Yes, most browsers require a genuine user gesture
- →No, it can be called from anywhere at any time
navigator.clipboard.readText() reads plain text FROM the clipboard, but requires explicit permission and only works in a secure, user-initiated context too.
writeText() can fail — due to permissions, an insecure context, or a browser that doesn't support it — so always wrap it in a try/catch with a fallback.
Checkpoint: Should code calling navigator.clipboard.writeText() always include a try/catch?
- →Yes, since it can fail due to permissions or support
- →No, it always succeeds once called
The Clipboard API also supports writing rich content (like images) via navigator.clipboard.write() with ClipboardItem objects, not just plain text.
Next, we'll explore 'The URL API'.
Level Up 🚀
Advanced cheat sheets, SEO tricks, and interview prep for this topic.
Browser Support
Fully supported.
Fully supported.
Fully supported.
Fully supported.
Accessibility (A11y)
1Announce Copy Success/Failure to Screen Reader Users
A visual-only 'Copied!' tooltip is invisible to screen reader users; pair it with an ARIA live region announcement so the copy confirmation (or failure) is communicated non-visually too.
SEO Implications
- 1
No Direct SEO Effect
The Clipboard API is a client-side interaction feature with no bearing on search engine indexing or ranking.
Best Practices
Always Trigger Clipboard Access from a Direct User Gesture
Calling clipboard methods from a click handler (not a delayed callback or unrelated event) maximizes compatibility with browser permission models that require a recent, genuine user interaction.
Provide a Visible Fallback or Error State When Copy Fails
Since clipboard access can be denied or unsupported, always give the user visible feedback (a toast, an inline message) confirming success, and a clear alternative (like selectable text) if it fails.
Frequent Bugs
Calling navigator.clipboard.writeText() from inside an async operation's .then() callback that runs well after the triggering click, causing it to silently fail in browsers that require a fresh user gesture.
Call the clipboard write as early as possible within the synchronous part of the click handler, or ensure any awaited work happens before the clipboard call, not after.
Not handling a rejected writeText() promise, leaving users with no feedback when a copy silently fails.
Wrap the call in try/catch and show explicit success or failure feedback to the user either way.
Real-World Examples
A "Copy Code Snippet" Button
A documentation site needed a button next to each code block that copied its contents to the clipboard and showed brief visual confirmation.
copyButton.addEventListener('click', async () => {
try {
await navigator.clipboard.writeText(codeBlock.textContent);
showToast('Copied to clipboard!');
} catch {
showToast('Copy failed — please copy manually.');
}
});