Glossary

Clipboard API

Clipboard API is the set of browser interfaces that let a web page copy text and other data to the system clipboard, and paste it back, asynchronously through navigator.clipboard. It is defined by the W3C Clipboard API and Events specification and works only in secure contexts. The call most people search for is navigator.clipboard.writeText, which returns a Promise.

How it works

navigator.clipboard is a Clipboard object with four methods. writeText and readText handle plain strings. write and read handle ClipboardItem objects, which map a MIME type to a Blob, so one item can carry text/plain, text/html or image/png at once. Browsers commonly support those three formats.

The page also receives copy, cut and paste events. Their clipboardData property is the older, synchronous route and lets you replace what the browser would copy. The asynchronous methods are preferred over the deprecated document.execCommand.

Permission rules differ between reading and writing:

  • Writing needs the clipboard-write permission or a transient user activation, such as a click. Chromium browsers keep a granted permission, while Firefox and Safari require the activation each time.
  • Reading is stricter. The specification requires recent user activation plus a browser paste action. In practice Chromium shows a clipboard-read permission prompt, while Firefox and Safari show a small Paste menu.
  • Inside an iframe, the Permissions-Policy values clipboard-read and clipboard-write must allow access.
  • A failed call rejects with a NotAllowedError. The API is not available in web workers.
async function copyText(text) {
  if (!navigator.clipboard || !globalThis.isSecureContext) return 'unavailable';
  try { await navigator.clipboard.writeText(text); return 'copied'; }
  catch (e) { return e.name; }
}
console.log(typeof navigator.clipboard, typeof ClipboardItem);
copyText('x').then(console.log);

This was run in Node.js 22.22.0, which has no clipboard, so it shows the guard path. In a browser click handler on an HTTPS page the same function resolves to copied.

undefined undefined
unavailable

Why is navigator.clipboard undefined?

It is undefined when the page is not a secure context, which means a plain http: page that is not localhost, and in some embedded or older environments. Serve the page over HTTPS. Check globalThis.isSecureContext, and keep a fallback for the rest.

Why does writeText fail with NotAllowedError?

It fails because the call did not happen during a user action, the document lacks focus, or a policy blocked it. Call writeText directly from a click handler, before any await that waits on slow work. If the text must be fetched first, pass a ClipboardItem containing a Promise of the Blob to write, so the copy is requested inside the gesture.

Common pitfalls

  • Copying on page load or from a timer: there is no user activation, so the browser rejects the call. Tie it to a button.
  • Reading the clipboard silently: readText can trigger a prompt, and the result may be empty if the clipboard holds an image. Treat the value as untrusted input.
  • Pasting clipboard HTML straight into the DOM: inserted markup can carry scripts or handlers. Prefer plain text, or sanitize it. See XSS.
  • No error handling: the Promise can reject for permission, focus or policy reasons. Always catch it and show a manual copy fallback.
  • Cross-origin iframes: the embedded page needs the Permissions-Policy allow attribute from its parent.
  • Assuming it works in a worker: it does not, so call it from the main thread.

Related terms

  • Promise — the type every async clipboard method returns
  • Async/await — the usual syntax for awaiting writeText and readText
  • HTTPS — the secure transport the API requires
  • DOM — where copy and paste events fire
  • XSS — the risk of inserting pasted HTML without sanitizing
  • Fetch API — another promise-based browser API for moving data

See also

  • Term: Promise — explains the rejected state a denied clipboard call produces