"Copy to Clipboard" functionality in plain JavaScript

"Copy to Clipboard" functionality in plain JavaScript

In modern browsers, you can use Clipboard API to read and write to the system clipboard.

Clipboard API consists of four asynchronous methods:

  • navigator.clipboard.read() - reading arbitrary data
  • navigator.clipboard.readText() - reading text
  • navigator.clipboard.write() - writing arbitrary data
  • navigator.clipboard.writeText() - writing text

It's very easy to use the writeText() method to implement a simple "Copy to Clipboard" functionality.

HTML:

<input type="text" id="copy-text">
<button id="copy-btn">Copy to Clipboard</button>

JavaScript:

document.getElementById("copy-btn").addEventListener("click", function(e) {
  if (!navigator.clipboard) {
    console.error('Clipboard API is not available');
    return;
  }

  let text = document.getElementById("copy-text").value;
  navigator.clipboard.writeText(text).then(function() {
    console.log("Copied to clipboard");
  }, function(err) {
    console.error(err);
  })  
})

If you try to run this code, you should see "Copied to clipboard" text in the console after clicking the copy button.

Explanation

document.getElementById("copy-btn").addEventListener("click", function(e) {
  if (!navigator.clipboard) {
    console.error('Clipboard API is not available');
    return;
  }

First, we're attaching onclick event handler to our "#copy-btn" button, and checking navigator.clipboard is available. We don't want our code to break if it's not, so we will just log an error and return.

  let text = document.getElementById("copy-text").value;

  navigator.clipboard.writeText(text).then(function() {
    console.log("Copied to clipboard");
  }, function(err) {
    console.error(err);
  })

Then we're getting the text value from our "copy-text" input element, and using navigator.clipboard.writeText method to write it to the system clipboard. Keep in mind that writeText is an async method that returns a promise, and you need to use the promise API directly (like the above), or use async/await.

Common mistake I've seen often is to do something like this:

navigator.clipboard.writeText(text)
console.log("Copied to clipboard")

Which will log "Copied to clipboard" immediately after calling writeText (regardless if the operation was successful or not).

Permissions API

"clipboard-write" permission is automatically granted to pages when they are in the active tab, but if you need to explicitly check for the permission, you can use something like this:

navigator.permissions.query({ name: "clipboard-write" }).then(p => console.log(p.state))


Note: This is a snapshot of the wiki page from the BetterWays.dev wiki, you can find the latest (better formatted) version here: betterways.dev/copy-to-clipboard-in-plain-javascript.