How to Copy to Clipboard in JavaScript with the Clipboard API

Introduction

The copy/paste feature is without a doubt one of the most commonly used features in modern computing, and it refers to the process of copying/transferring text or images from one part of a computer-based application to another. Most recently, it's become common practice to programmatically copy some contents to the clipboard of a user, so that they don't have to.

For instance, activation and verification codes that pop up on a page or email. You can either copy them automatically or have a button that allows someone to copy the contents to the clipboard, so they don't have to copy it themselves. Additionally, code snippets are a great example of content you might want copied to a clipboard!

In this guide, we’ll take a look at how to programmatically copy content to the clipboard using JavaScript's new Clipboard API.

Note: Unless you're on localhost, the new Clipboard API will only work if your website is hosted over a secure domain (HTTPS).

Copy to Clipboard in JavaScript

The whole process can be simplified down to a button (or other element) that triggers the code! You could also do this on the page load, but it's generally advisable to be conservative when it comes to interfacing automatically with the user and performing actions that affect their local machine (like adding something to the clipboard):

<textarea id="content"></textarea>
<button onclick="copyToClipboard()">Copy</button>

<script>
  function copyToClipboard() {
    var copyText = document.getElementById("content").value;
    navigator.clipboard.writeText(copyText).then(() => {
        // Alert the user that the action took place.
        // Nobody likes hidden stuff being done under the hood!
        alert("Copied to clipboard");
    });
  }
</script>

However, there's more to be said here - how it works, the limitations, how to copy images, etc. In the rest of the guide, we'll be covering exactly these.

Previously, JavaScript developers relied on document.execCommand(). However, a relatively new Clipboard API was recently released to make data transfer via copy/paste seamless!

Reading the Browser's Permission

Depending on the action you’re performing (reading or writing) with the Clipboard API, it's always advisable to check for browser's permission, before attempting any operations. To check whether you have write access, you'll use the navigator.permissions and query for the clipboard-write permission:

navigator.permissions.query({ name: "clipboard-write" }).then((result) => {
  if (result.state == "granted" || result.state == "prompt") {
    alert("Write access ranted!");
  }
});

Note: The "clipboard-write" permission of the Permissions API is granted automatically to pages when they are in the active tab.

Similarly enough, you can check whether you have clipboard-read access as well:

navigator.permissions.query({ name: "clipboard-read" }).then((result) => {
  if (result.state == "granted" || result.state == "prompt") {
    alert("Read access ranted!");
  }
});

Copying Text to Clipboard

Let's start out with copying the text onto the clipboard. We've briefly seen this in the first example, and it doesn't really get much more complex than that. To copy text with the new Clipboard API, we use an asynchronous writeText() method and this method accepts only one parameter - the text to copy to clipboard.

Being asynchronous, it returns a promise, which is resolved if the clipboard has been updated successfully, and rejected otherwise:

navigator.clipboard.writeText("TEXT_TO_COPY_TO").then(() => {
  /* Resolved - text copied to clipboard */
},() => {
  /* Rejected - clipboard failed */
});

Read Clipboard Contents

Similar to writing, you can also read the contents of a clipboard. This does raise privacy concerns, and you should by all means be transparent and careful about using the feature. You may want to chain writing and reading together, to ensure that whatever you read is only what you already wrote.

For instance - a user may open a verification code on one page, that's automatically copied to the clipboard. If you're ensured that they'll then go to another page with that entry in the clipboard - you may read the entry and paste it into another field, to yet again, save them a bit of time and effort!

We use the readText() method to read the latest entry in the clipboard. This method also returns a promise which is resolved if browser can access the clipboard content, and rejected otherwise:

navigator.clipboard
  .readText()
  .then((copiedText) => {
        // Do something with copied text
   });

Unlike writing to the clipboard, asking to read the browser clipboard content additionally displays a one-time prompt asking the user to consent, as shown in the image below:

Copy Image and Rich Text to Clipboard

Rich text refers to textual contents that allow styling such as - bold, italics, and underlining, as well as different font families and font sizes. When copying textual content, it might be in rich text format, which means that there's more metadata regarding the contents than just the text itself.

Free eBook: Git Essentials

Check out our hands-on, practical guide to learning Git, with best-practices, industry-accepted standards, and included cheat sheet. Stop Googling Git commands and actually learn it!

We can also use the Clipboard API's write() method to copy arbitrary data such as rich text and images, and this function accepts only one parameter, which is an array containing the data to be written to the clipboard. The writeText() method is specialized for plain text, while write() can write any arbitrary data.

For instance, you could fetch an image from a remote URL and copy it to the clipboard:

const copyImage = async () => {
    const response = await fetch("/path/to/image.png");
    const blob = await response.blob();
    await navigator.clipboard.write([
      new ClipboardItem({ "image/png": blob }),
    ]);
  };

The example above also works for copying rich texts, when you change the type of the item to "text/html":

const copyRichText = async () => {
    const content = document.getElementById("richTextInputId").innerHTML;
    const blob = new Blob([content], { type: "text/html" });
    const richTextInput = new ClipboardItem({ "text/html": blob });
    await navigator.clipboard.write([richTextInput]);
};

This does assume that the richTextInputId element supports rich text itself.

Read Image and Rich Text from Clipboard

The Clipboard API also provides a distinct read() method, which is used to read arbitrary data rather than plain text, and it works similarly to the previous readText() function, but can read arbitrary data. For example to read an image data that was previously copied to the clipboard:

<img src="" alt="" id="sample-img" />
<script>
const img = document.getElementById("sample-img");
  navigator.clipboard.read().then((data) => {
  for (let i = 0; i < data.length; i++) {
    if (!data[i].types.includes("image/png")) {
      // Clipboard does not contain image data
    } else {
      data[i].getType("image/png").then((blob) => {
          img.src = URL.createObjectURL(blob);
      });
    }
  }
});
</script>

Conclusion

In this short guide, we've been able to cover the process of copying text and other data such as images to the clipboard using the new Clipboard API. Whenever you're writing to or reading from a user's local machine - be careful to be transparent and safe about the process!

Last Updated: September 11th, 2023
Was this article helpful?

Improve your dev skills!

Get tutorials, guides, and dev jobs in your inbox.

No spam ever. Unsubscribe at any time. Read our Privacy Policy.

Project

React State Management with Redux and Redux-Toolkit

# javascript# React

Coordinating state and keeping components in sync can be tricky. If components rely on the same data but do not communicate with each other when...

David Landup
Uchechukwu Azubuko
Details

Getting Started with AWS in Node.js

Build the foundation you'll need to provision, deploy, and run Node.js applications in the AWS cloud. Learn Lambda, EC2, S3, SQS, and more!

© 2013-2024 Stack Abuse. All rights reserved.

AboutDisclosurePrivacyTerms