Interact with the clipboard

You work with the clipboard in extensions using the Web API navigator.clipboard method and "clipboardRead" or "clipboardWrite" extension permissions. navigator.clipboard enables your extension to read and write arbitrary data from and to the clipboard.

Note: The Web API document.execCommand method was used to provide clipboard functionality. However, document.execCommand("copy"), document.execCommand("cut"), and document.execCommand("paste") are deprecated and no longer guaranteed to work or be available on any browser. These features are documented in this article for historical reference.

The navigator.clipboard API provides methods for:

Note: The Clipboard API write and read methods are only available in secure contexts. Your extension can't use them from a content script running on http: pages; they can only use them from https: pages.

Writing to the clipboard

The Clipboard API methods navigator.clipboard.write() and navigator.clipboard.writeText() write arbitrary content to the clipboard. The methods are available from a secure context but only function after the extension's user performs transient activation. However, with the "clipboardWrite" permission, transient activation isn't required.

Note: In Firefox and Chrome, the "clipboardWrite" permission enables writing to the clipboard from all extension contexts and content scripts. In Safari, the "clipboardWrite" permission is only supported in extension contexts (not content scripts).

This function takes a string and writes it to the clipboard:

js
function updateClipboard(newClip) {
  navigator.clipboard.writeText(newClip).then(
    () => {
      /* clipboard successfully set */
    },
    () => {
      /* clipboard write failed */
    },
  );
}

Using execCommand()

Note: document.execCommand("copy") and document.execCommand("cut") are deprecated and no longer guaranteed to work or be available on any browser.

The "cut" and "copy" commands of the document.execCommand() method are used to replace the clipboard's content with the selected material. Extensions can use these commands without special permission in short-lived event handlers triggered by user actions (for example, a click handler).

For example, suppose you've got a popup that includes this HTML:

html
<input id="input" type="text" /> <button id="copy">Copy</button>

To make the "copy" button copy the contents of the <input> element, you can use code like this:

js
function copy() {
  let copyText = document.querySelector("#input");
  copyText.select();
  document.execCommand("copy");
}

document.querySelector("#copy").addEventListener("click", copy);

Because the execCommand() call is inside a click event handler, your extension doesn't need special permissions.

However, take the example of your extension triggering the copy from an alarm:

js
function copy() {
  let copyText = document.querySelector("#input");
  copyText.select();
  document.execCommand("copy");
}

browser.alarms.create({
  delayInMinutes: 0.1,
});

browser.alarms.onAlarm.addListener(copy);

Depending on the browser, this may not work. On Firefox, it doesn't work, and you see a message like this in the console:

document.execCommand('cut'/'copy') was denied because it was not called from inside a short running user-generated event handler.

To enable this use case, your extension must request the "clipboardWrite" permission: "clipboardWrite" enables your extension to write to the clipboard outside a short-lived event handler for a user action.

Note: document.execCommand() doesn't work on input fields of type="hidden", with the HTML5 attribute "hidden", or any matching CSS rule using "display: none;". To add a "copy to clipboard" button to a span, div, or p tag, you need to use a workaround, such as setting the input's position to absolute and moving it out of the viewport.

Reading from the clipboard

The Clipboard API methods navigator.clipboard.read() and navigator.clipboard.readText() read arbitrary text or binary data from the clipboard. These methods allow extensions to access data in the clipboard without pasting it into an editable element.

The methods are available from a secure context but only function after the extension's user performs transient activation and clicks a paste prompt in an ephemeral context menu. However, with the "clipboardRead" permission, your extension can read from the clipboard without user confirmation or transient activation.

Note: In Firefox and Chrome, the "clipboardRead" permission enables writing to the clipboard from all extension contexts and content scripts. Safari doesn't support the "clipboardRead" permission.

This snippet of code fetches the text from the clipboard and replaces the contents of the element with the ID "outbox" with that text.

js
navigator.clipboard
  .readText()
  .then((clipText) => (document.getElementById("outbox").innerText = clipText));

Using execCommand()

Note: document.execCommand("paste") is deprecated and no longer guaranteed to work or be available on any browser.

To use document.execCommand("paste"), your extension needs the "clipboardRead" permission. This requirement exists even if you're using the "paste" command from within a user-generated event handler, such as click or keypress.

Consider HTML that includes this:

html
<textarea id="output"></textarea> <button id="paste">Paste</button>

To set the content of the <textarea> element with the ID "output" from the clipboard when the user clicks the "paste" <button>, you can use code like this:

js
function paste() {
  let pasteText = document.querySelector("#output");
  pasteText.focus();
  document.execCommand("paste");
  console.log(pasteText.textContent);
}
document.querySelector("#paste").addEventListener("click", paste);

Browser-specific considerations

In Chrome:

  • Chrome doesn't expose navigator.clipboard to extension service workers, and offscreen documents can't access navigator.clipboard due to the API's document focus requirements. As a result, Chrome extensions have to use the deprecated document.execCommand() APIs in an offscreen document or use navigator.clipboard in a different context, such as a content script or extension page. For page scripts to write to the clipboard without user interaction, the "clipboard-write" permission needs to be requested using the Web API navigator.permissions. Your extension can check for that permission using navigator.permissions.query():

    js
    navigator.permissions.query({ name: "clipboard-write" }).then((result) => {
      if (result.state === "granted" || result.state === "prompt") {
        /* write to the clipboard now */
      }
    });
    

    Note: The clipboard-write permission is not supported in Firefox or Safari.

In Firefox:

  • The availability of the Clipboard API read methods on the user's response to a paste prompt was introduced for web pages in Firefox 127 and extensions in Firefox 147. Before that, the methods were only available when the "clipboardRead" permission was set.

In Safari:

  • The "clipboardWrite" permission is only supported in extension contexts (not content scripts).
  • The "clipboardRead" permission isn't support.

Browser compatibility

api.Clipboard

webextensions.api.clipboard

See also