How to copy an image to the clipboard with vanilla JavaScript

OpenJavaScript 0

Last updated: September 30, 2022.

You do not need to rely upon a third-party library to copy an image to the clipboard!

With vanilla JavaScript, you can achieve this by writing an image to a HTML canvas element, extacting the image from it and serving it up to the clipboard by writing a new ClipboardItem object to it.

Table of contents

Creating an image-to-clipboard copier

The first step is to create some new elements in Javascript:

const img = new Image();
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');

The next step is to create a function that sets img.src and then writes its contents to the canvas when it has finished loading. Finally, the canvas content is extracted to produce a Blob object of type image/png.

Because this process contains an asynchronous process (waiting for the image to load), it is wrapped in a promise so that the return value of the function is a promise containing the Blob image:

function writeToCanvas(src) {
  return new Promise((res, rej) => {
    img.src = src;
    img.onload = function() {
      canvas.width = img.naturalWidth;
      canvas.height = img.naturalHeight;
      ctx.drawImage(img,0,0)
      canvas.toBlob((blob) => {
        res(blob);
      }, 'image/png');
    }
  });
}

Now, we create a new function to handle the promise inside an asynchronous function.

The function first waits for the result of the promise to be returned and then attempts to write the Blob image to the clipboard as a new ClipboardItem.

ClipboardItem accepts an object containing the MIME type as the key and the image as the value.

Because writing the the clipboard is itself asynchronous and returns a promise, the success message awaits this process.

async function copyToClipboard(src) {
  const image = await writeToCanvas(src);
  try {
    await navigator.clipboard.write([
      new ClipboardItem({
        [image.type]: image,
      })
    ]);

    console.log("Success");
  } catch(e) {
    console.log("Copy failed: " + e);
  }
}

Result: Image-to-clipboard copying

And here is the final result:

<button id="btn">Copy image!</button>

<script>

const img = new Image();
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');

document.getElementById('btn').addEventListener('click', () => {
  copyToClipboard('your-image.jpg');
});

function writeToCanvas(src) {
  return new Promise((res, rej) => {
    img.src = src;
    img.onload = function() {
      canvas.width = img.naturalWidth;
      canvas.height = img.naturalHeight;
      ctx.drawImage(img,0,0)
      canvas.toBlob((blob) => {
        res(blob);
      }, 'image/png');
    }
  });
}

async function copyToClipboard(src) {
  const image = await writeToCanvas(src);
  try {
    await navigator.clipboard.write([
      new ClipboardItem({
        [image.type]: image,
      })
    ]);

    console.log("Success");
  } catch(e) {
    console.log("Copy failed: " + e);
  }
}

</script>

For a fetched image

If the image to copy requires an API call, you can include a Fetch request as a first step.

The result can be converted to a Blob object by calling the blob() method on it. The resulting blob can then be passed into the createObjectURL() method that will create a local URL to the file in memory.

Use this URL to set img.src and the process then continues unchanged:

<label for="url">Enter image URL: </label><input id="url" type="text"><br>
<button id="btn">Copy image!</button>

<script>

const img = new Image();
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');

function writeToCanvas(src) {
  return new Promise((res, rej) => {
    fetch(src)
    .then(res => res.blob())
    .then(imgBlob => {
        const imgURL = URL.createObjectURL(imgBlob);
        img.src = imgURL;
    })
    .then(() => {
      img.onload = function() {
        canvas.width = img.naturalWidth;
        canvas.height = img.naturalHeight;
        ctx.drawImage(img,0,0)
        canvas.toBlob((blob) => {
          res(blob);
        }, 'image/png');
      }
    })
  });
}

async function copyToClipboard(src) {
  const image = await writeToCanvas(src);
  try {
    await navigator.clipboard.write([
      new ClipboardItem({
        [image.type]: image,
      })
    ]);

    console.log("Success");
  } catch(e) {
    console.log("Copy failed: " + e);
  }
}

</script>

Related links