Clipboard: read() method

Baseline 2024 *
Newly available

Since June 2024, this feature works across the latest devices and browser versions. This feature might not work in older devices or browsers.

* Some parts of this feature may have varying levels of support.

Secure context: This feature is available only in secure contexts (HTTPS), in some or all supporting browsers.

The read() method of the Clipboard interface requests a copy of the clipboard's contents, fulfilling the returned Promise with the data.

The method can in theory return arbitrary data (unlike readText(), which can only return text). Browsers commonly support reading text, HTML, and PNG image data.

Syntax

js
read()
read(formats)

Parameters

formats Optional

An optional object with the following properties:

unsanitized Optional

An Array of strings containing MIME types of data formats that should not be sanitized when reading from the clipboard.

Certain browsers may sanitize the clipboard data when it is read, to prevent malicious content from being pasted into the document. For example, Chrome (and other Chromium-based browsers) sanitizes HTML data by stripping <script> tags and other potentially dangerous content. Use the unsanitized array to specify a list of MIME types that should not be sanitized.

Return value

A Promise that resolves with an array of ClipboardItem objects containing the clipboard's contents.

Exceptions

NotAllowedError DOMException

Thrown if the reading from the clipboard is not allowed.

Security considerations

Reading from the clipboard can only be done in a secure context.

Additional security requirements are covered in the Security consideration section of the API overview topic.

Examples

Reading image data from clipboard

This example uses the read() method to read image data from the clipboard and paste it into an <img> element.

HTML

html
<img id="source" src="butterfly.jpg" alt="A butterfly" />
<img id="destination" src="" alt="Pasted image" />
<button id="reload" type="button">Reload</button>
<p id="log"></p>

CSS

css
img {
  height: 100px;
  width: 100px;
  margin: 0 1rem;
  border: 1px solid black;
}
#reload {
  display: block;
  margin: 0 1rem;
}

JavaScript

This code provides a mechanism to log any errors to the element with id log.

js
const logElement = document.querySelector("#log");
function log(text) {
  logElement.innerText = `Error: ${text}`;
}

We also add code to reload and clear the example when the "Reload" button is pressed.

js
const reload = document.querySelector("#reload");

reload.addEventListener("click", () => {
  window.location.reload(true);
});

The remaining code reads the clipboard when the destination element is clicked and copies the image data into the destinationImage element. It logs an error if it is unable to use the read() method, or if the clipboard does not contain data in PNG format.

js
const destinationImage = document.querySelector("#destination");
destinationImage.addEventListener("click", pasteImage);

async function pasteImage() {
  try {
    const clipboardContents = await navigator.clipboard.read();
    for (const item of clipboardContents) {
      if (!item.types.includes("image/png")) {
        throw new Error("Clipboard does not contain PNG image data.");
      }
      const blob = await item.getType("image/png");
      destinationImage.src = URL.createObjectURL(blob);
    }
  } catch (error) {
    log(error.message);
  }
}

Result

Copy the butterfly image on the left by right-clicking the image and selecting "Copy image" from the context menu. Then click on the empty frame on the right. The example will fetch the image data from the clipboard and display the image in the empty frame.

Note: If prompted, grant permission in order to paste the image.

Reading data from the clipboard

This example uses the read() method to read data from the clipboard and log whatever data is stored in the clipboard.

This differs from the previous version in that it will display text, HTML, and image ClipboardItem objects (rather than just images).

HTML

html
<img id="source_jpg" src="butterfly.jpg" alt="JPG butterfly image" />
<div id="destination">Click here to copy clipboard data.</div>
<button id="reload" type="button">Reload</button>
<p id="log"></p>

CSS

css
img {
  height: 100px;
  width: 100px;
  margin: 0 1rem;
  border: 1px solid black;
}

#destination {
  min-height: 300px;
  min-width: 90%;
  margin: 0 1rem;
  border: 1px solid black;
}

#reload {
  display: block;
  margin: 0 1rem;
}

JavaScript

This code provides a mechanism to log any errors to the element with id log.

js
const logElement = document.querySelector("#log");
function log(text) {
  logElement.innerText = `Error: ${text}`;
}

We also add code to reload and clear the example when the "Reload" button is pressed.

js
const reload = document.querySelector("#reload");

reload.addEventListener("click", () => {
  window.location.reload(true);
});

The remaining code reads the clipboard when the destination element is clicked and displays each ClipboardItem element along with its MIME type. It logs an error it is unable to use the read() method, or if the clipboard contains any other MIME type.

js
const destinationDiv = document.querySelector("#destination");
destinationDiv.addEventListener("click", pasteData);

async function pasteData() {
  destinationDiv.innerText = ""; // Clear inner text
  try {
    const clipboardContents = await navigator.clipboard.read();
    for (const item of clipboardContents) {
      for (const mimeType of item.types) {
        const mimeTypeElement = document.createElement("p");
        mimeTypeElement.innerText = `MIME type: ${mimeType}`;
        destinationDiv.appendChild(mimeTypeElement);
        if (mimeType === "image/png") {
          const pngImage = new Image();
          pngImage.alt = "PNG image from clipboard";
          const blob = await item.getType("image/png");
          pngImage.src = URL.createObjectURL(blob);
          destinationDiv.appendChild(pngImage);
        } else if (mimeType === "text/html") {
          const blob = await item.getType("text/html");
          const blobText = await blob.text();
          const clipHTML = document.createElement("pre");
          clipHTML.innerText = blobText;
          destinationDiv.appendChild(clipHTML);
        } else if (mimeType === "text/plain") {
          const blob = await item.getType("text/plain");
          const blobText = await blob.text();
          const clipPlain = document.createElement("pre");
          clipPlain.innerText = blobText;
          destinationDiv.appendChild(clipPlain);
        } else {
          throw new Error(`${mimeType} not supported.`);
        }
      }
    }
  } catch (error) {
    log(error.message);
  }
}

Result

Copy some text or the butterfly (JPG) image below (to copy images right-click on them and then select "Copy image" from the context menu). Select the indicated frame below to paste this information from the clipboard into the frame.

Notes:

  • Even though the butterfly image is a JPG file, when read from the clipboard it is a PNG.
  • If prompted, you will need to grant permission in order to paste the image.
  • This may not work on chromium browsers as the sample frame is not granted the Permissions-Policy clipboard-read and clipboard-write permissions (required by Chromium browsers).

Reading unsanitized HTML from the clipboard

This example uses the formats parameter to read HTML data from the clipboard and get the code in its original form, without the browser sanitizing it first.

HTML

html
<textarea id="source" rows="5">
  <style>h1 {color: red;} p {color: blue;}</style>
  <h1>Hello world!</h1>
  <p>This is a test.</p>
  <script>alert('Hello world!');</script>
</textarea>
<button id="copy">Copy HTML</button>
<button id="paste_normal">Paste HTML</button>
<button id="paste_unsanitized">Paste unsanitized HTML</button>
<textarea id="destination" rows="5"></textarea>

CSS

css
body {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 5px;
}

textarea {
  grid-column: 1 / span 3;
}

JavaScript

js
const copyButton = document.getElementById("copy");
const pasteButton = document.getElementById("paste_normal");
const pasteUnsanitizedButton = document.getElementById("paste_unsanitized");
const sourceTextarea = document.getElementById("source");
const destinationTextarea = document.getElementById("destination");

copyButton.addEventListener("click", async () => {
  const text = sourceTextarea.value;
  const type = "text/html";
  const blob = new Blob([text], { type });
  const data = [new ClipboardItem({ [type]: blob })];

  try {
    await navigator.clipboard.write(data);
  } catch (error) {
    destinationTextarea.value = `Clipboard write failed: ${error}`;
  }
});

async function getHTMLFromClipboardContents(clipboardContents) {
  for (const item of clipboardContents) {
    if (item.types.includes("text/html")) {
      const blob = await item.getType("text/html");
      const blobText = await blob.text();
      return blobText;
    }
  }

  return null;
}

pasteButton.addEventListener("click", async () => {
  try {
    const clipboardContents = await navigator.clipboard.read();
    const html = await getHTMLFromClipboardContents(clipboardContents);
    destinationTextarea.value =
      html || "Could not find HTML data in the clipboard.";
  } catch (error) {
    destinationTextarea.value = `Clipboard read failed: ${error}`;
  }
});

pasteUnsanitizedButton.addEventListener("click", async () => {
  try {
    const clipboardContents = await navigator.clipboard.read({
      unsanitized: ["text/html"],
    });
    const html = await getHTMLFromClipboardContents(clipboardContents);
    destinationTextarea.value =
      html || "Could not find HTML data in the clipboard.";
  } catch (error) {
    destinationTextarea.value = `Clipboard read failed: ${error}`;
  }
});

Result

First click the "Copy HTML" button to write the HTML code from the first textarea to the clipboard. Then either click the "Paste HTML" button or the "Paste unsanitized HTML" button to paste the sanitized or unsanitized HTML code into the second textarea.

Specifications

Specification
Clipboard API and events
# dom-clipboard-read

Browser compatibility

desktop mobile
Chrome
Edge
Firefox
Opera
Safari
Chrome Android
Firefox for Android
Opera Android
Safari on iOS
Samsung Internet
WebView Android
WebView on iOS
read
Chrome – Full support
Chrome 76 (Release date: 2019-07-30)
footnote
footnote The user must grant the clipboard-read permission.
Edge – Full support
Edge 79 (Release date: 2020-01-15)
footnote
footnote The user must grant the clipboard-read permission.
Firefox – Full support
Firefox 127 (Release date: 2024-06-11)
footnote
footnote This method must be called within user gesture event handlers.
footnote A paste prompt is displayed when the clipboard is read. If the clipboard contains same-origin content, the prompt is suppressed.
footnote 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.
Opera – Full support
Opera 63 (Release date: 2019-08-20)
footnote
footnote The user must grant the clipboard-read permission.
Safari – Full support
Safari 13.1 (Release date: 2020-03-24)
footnote Full support
Chrome Android – Full support
Chrome Android 76 (Release date: 2019-07-30)
footnote
footnote The user must grant the clipboard-read permission.
Firefox for Android – Full support
Firefox for Android 127 (Release date: 2024-06-11)
footnote
footnote This method must be called within user gesture event handlers.
footnote A paste prompt is displayed when the clipboard is read. If the clipboard contains same-origin content, the prompt is suppressed.
footnote Web extensions with the clipboardRead permission in their manifest can read data without the paste prompt displaying. Prior to Firefox for Android 147, extensions without this permission were unable to read clipboard data.
Opera Android – Full support
Opera Android 54 (Release date: 2019-10-18)
footnote
footnote The user must grant the clipboard-read permission.
Safari on iOS – Full support
Safari on iOS 13.4 (Release date: 2020-03-24)
footnote Full support
Samsung Internet – Full support
Samsung Internet 12 (Release date: 2020-06-19)
footnote
footnote The user must grant the clipboard-read permission.
WebView Android – Full support
WebView Android 76 (Release date: 2019-07-30)
footnote
footnote The user must grant the clipboard-read permission.
WebView on iOS – Full support
WebView on iOS 13.4 (Release date: 2020-03-24)
footnote Full support
formats.unsanitized parameter
Experimental
Chrome – Full support
Chrome 122 (Release date: 2024-02-20)
footnote Full support
Edge – Full support
Edge 122 (Release date: 2024-02-23)
footnote Full support
Firefox – No support
Firefox
footnote No support
Opera – Full support
Opera 108 (Release date: 2024-03-05)
footnote Full support
Safari – No support
Safari
footnote No support
Chrome Android – Full support
Chrome Android 122 (Release date: 2024-02-20)
footnote Full support
Firefox for Android – No support
Firefox for Android
footnote No support
Opera Android – Full support
Opera Android 81 (Release date: 2024-03-14)
footnote Full support
Safari on iOS – No support
Safari on iOS
footnote No support
Samsung Internet – Full support
Samsung Internet 26 (Release date: 2024-06-07)
footnote Full support
WebView Android – Full support
WebView Android 122 (Release date: 2024-02-20)
footnote Full support
WebView on iOS – No support
WebView on iOS
footnote No support

Legend

Tip: you can click/tap on a cell for more information.

Full support
Full support
No support
No support
Experimental. Expect behavior to change in the future.
See implementation notes.

See also