Copy with the Clipboard API

async function copy(text) {
  await navigator.clipboard.writeText(text);
  console.log("Copied!");
}
copy("hello world");

Because it is promise-based, awaiting the call tells you exactly when the text has landed on the clipboard.

Wire it to a copy button

button.addEventListener("click", async () => {
  await navigator.clipboard.writeText(input.value);
  button.textContent = "Copied!";
});

This reads the value from an input and gives the user instant feedback by changing the button label.

Handle failures gracefully

try {
  await navigator.clipboard.writeText(text);
} catch (err) {
  console.error("Copy failed", err);
}

Copying can fail if the page is not served over HTTPS or the user denied permission, so always wrap it in try/catch.

Read text back from the clipboard

const text = await navigator.clipboard.readText();
console.log(text);

Common mistakes

  • Calling it outside a user gesture. The copy must run from a click or similar event.
  • Expecting it to work on plain HTTP. The Clipboard API needs a secure (HTTPS) context.
  • Ignoring the promise. Await it so you know it succeeded.

Frequently asked questions

Why does writeText do nothing?

The Clipboard API only works in a secure context and usually requires a user gesture like a click. On localhost and HTTPS it works; on plain HTTP it is blocked.

Is execCommand still needed?

Rarely. document.execCommand("copy") is deprecated. Use it only as a fallback for very old browsers, with the Clipboard API as the primary path.

Practice browser APIs in our free JavaScript course.