Skip to content

Capabilities · API

Async Clipboard API: reading and writing the clipboard

Published

Newly available since 2024-06W3C draft

In one line: The Async Clipboard API — navigator.clipboard — lets you read from and write to the system clipboard programmatically. Writing plain text requires no permission; reads are tightly gated: Chromium may use the clipboard-read permission, while Firefox and Safari require transient activation and the browser’s own paste prompt (no persistent grant is stored). All operations require a secure context (HTTPS or localhost).

try {
await navigator.clipboard.writeText('Hello, clipboard!');
} catch (err) {
console.error('Clipboard write failed:', err);
}

writeText requires:

  • A secure context (HTTPS or localhost).
  • Either a user activation or that the page has focus (the exact rule is browser-dependent, but calling from a click handler is always safe).
const blob = new Blob(['<b>hello</b>'], { type: 'text/html' });
const item = new ClipboardItem({ 'text/html': blob });
await navigator.clipboard.write([item]);

write() accepts an array of ClipboardItem objects. Each item can carry multiple MIME types so the paste target can pick the richest format it understands.

const text = await navigator.clipboard.readText();
const items = await navigator.clipboard.read();
for (const item of items) {
for (const type of item.types) {
const blob = await item.getType(type);
// process blob
}
}

Permission behavior differs significantly by browser family.

Chromium uses the clipboard-read and clipboard-write Permissions API names:

  • Writing (writeText / write): no permission prompt for writeText when called from a focused, user-activated context. write() with certain MIME types (e.g., images) may prompt for clipboard-write.
  • Reading (readText / read): requires the clipboard-read permission; a browser prompt is shown the first time. You can query the current state without triggering a prompt:
// Chromium only — clipboard-read is not a recognised name in Firefox or Safari
const { state } = await navigator.permissions.query({ name: 'clipboard-read' });
// state: 'granted' | 'denied' | 'prompt'

Firefox does not recognise clipboard-read or clipboard-write as Permissions API names — navigator.permissions.query({ name: 'clipboard-read' }) will reject or return a nonsense state. Instead:

  • Writing: requires transient activation (a user gesture such as a click).
  • Reading: requires transient activation and triggers a one-time browser paste confirmation dialog the user must accept; there is no persistent grant.

Safari also does not expose clipboard-read/clipboard-write to the Permissions API. Its model is similar to Firefox:

  • Writing: requires transient activation.
  • Reading: requires transient activation and a user-initiated paste prompt; no persistent permission is stored.

Both read and write operations should be called from within a user-gesture handler or while the document has focus. Browsers differ slightly, but calling from a click handler is always safe. Attempting to call outside a user-activated context typically results in a NotAllowedError.

The legacy document.execCommand('copy') and document.execCommand('paste') work in older browsers but are deprecated and do not support rich content. Use them only as a last resort:

function legacyCopy(text) {
const textarea = document.createElement('textarea');
textarea.value = text;
document.body.appendChild(textarea);
textarea.select();
document.execCommand('copy');
textarea.remove();
}
Decision question Recommended action Rationale
Copy plain text on button click? navigator.clipboard.writeText() inside a click handler. No permission prompt; works in all modern browsers with HTTPS.
Copy an image or HTML to clipboard? navigator.clipboard.write([new ClipboardItem(...)]). Allows multi-format payloads; the paste target picks the best type.
Read clipboard contents? Always call from a user-gesture handler. In Chromium you can query clipboard-read permission first; in Firefox and Safari rely on transient activation and the browser’s own paste prompt — do not use navigator.permissions.query for this. Permission model is browser-family-specific; transient activation is the portable baseline.
Need to support older browsers? Feature-detect navigator.clipboard; fall back to execCommand. execCommand is deprecated but still works in older engines.
Clipboard in a Service Worker or background context? Not possible — clipboard access requires a focused document. By spec and browser policy, clipboard is not available in background contexts.
  • Serve the page over HTTPS — navigator.clipboard is undefined on plain HTTP.
  • Call clipboard methods from user-gesture handlers or while the document has focus.
  • Use writeText for plain text; use write with ClipboardItem for rich content.
  • Always call read methods from a user-gesture handler. In Chromium, optionally query the clipboard-read permission state first; in Firefox and Safari, depend on transient activation and the browser’s paste prompt — navigator.permissions.query({ name: 'clipboard-read' }) is not portable across browser families.
  • Catch errors from all clipboard calls — permissions can be denied or revoked.
  • Provide a document.execCommand fallback for browsers that do not support the Async Clipboard API.

Specifications

SpecificationStatus
Async Clipboard APIW3C draft
  • Legend
  • Yes
  • Partial
  • Flag
  • No
  • Unknown
Browser / PlatformSupportVersionsConfidenceSourceNotes
Chrome (Desktop)Yes76highsource1
Chrome (Android)Yes76highsource23
Edge (Desktop)Yes79highsource45
Firefox (Desktop)Yes127highsource678
Firefox (Android)Yes127highsource9101112
Safari (macOS)Yes13.1highsource—
Safari (iOS)Yes13.4highsource13
Samsung InternetYes12.0highsource1415
WebView (Android)Yes76highsource1617
  1. The user must grant the `clipboard-read` permission.
  2. The user must grant the `clipboard-read` permission.
  3. Derived by browser-compat-data mirroring from Chrome.
  4. The user must grant the `clipboard-read` permission.
  5. Derived by browser-compat-data mirroring from Chrome.
  6. This method must be called within user gesture event handlers.
  7. A paste prompt is displayed when the clipboard is read. If the clipboard contains same-origin content, the prompt is suppressed.
  8. Web extensions with the `clipboardRead` permission in their manifest can read data without the paste prompt displaying. Prior to Firefox 147, extensions without this permission were unable to read clipboard data.
  9. This method must be called within user gesture event handlers.
  10. A paste prompt is displayed when the clipboard is read. If the clipboard contains same-origin content, the prompt is suppressed.
  11. Web extensions with the `clipboardRead` permission in their manifest can read data without the paste prompt displaying. Prior to Firefox 147, extensions without this permission were unable to read clipboard data.
  12. Derived by browser-compat-data mirroring from Firefox.
  13. Derived by browser-compat-data mirroring from Safari.
  14. The user must grant the `clipboard-read` permission.
  15. Derived by browser-compat-data mirroring from Chrome Android.
  16. The user must grant the `clipboard-read` permission.
  17. Derived by browser-compat-data mirroring from Chrome Android.

Source data: /compatibility/clipboard.json · Global usage: 93 % (StatCounter 2026-05)

Source: spec · MDN · Last verified 2026-10-03 · Confidence: high (computed from sources)