Flash-Free Clipboard for the Web

As part of our effort to grow the Web platform and make it accessible to new devices, we are trying to reduce the Web’s dependence on Flash. As part of that effort, we are standardizing and exposing useful features which are currently only available to Flash to the entirety of the Web platform.

One of the reasons why many sites still use Flash is because of its copy and cut clipboard APIs. Flash exposes an API for programmatically copying text to the user’s clipboard on a button press. This has been used to implement handy features, such as GitHub’s “clone URL” button. It’s also useful for things such as editor UIs, which want to expose a button for copying to the clipboard, rather than requiring users to use keyboard shortcuts or the context menu.

Unfortunately, Web APIs haven’t provided the functionality to copy text to the clipboard through JavaScript, which is why visiting GitHub with Flash disabled shows an ugly grey box where the button is supposed to be. Fortunately, we have a solution. The editor APIs provide document.execCommand as an entry point for executing editor commands. The "copy" and cut" commands have previously been disabled for web pages, but with Firefox 41, which is currently in Beta, and slated to move to release in mid-September, it is becoming available to JavaScript within user-action initiated callbacks.

Using execCommand("cut"/"copy")

The execCommand("cut"/"copy") API is only available during a user-triggered callback, such as a click. If you try to call it at a different time, execCommand will return false, meaning that the command failed to execute. Running execCommand("cut") will copy the current selection to the clipboard, so let’s go about implementing a basic copy-to-clipboard button.

// button which we are attaching the event to
var button = ...;
// input containing the text we want to copy 
var input = ...;

button.addEventListener("click", function(event) {
  event.preventDefault();
  // Select the input node's contents
  input.select();
  // Copy it to the clipboard
  document.execCommand("copy");
});

That code will trigger a copy of the text in the input to the clipboard upon the click of the button in Firefox 41 and above. However, you probably want to also handle failure situations, potentially to fallback to another Flash-based approach such as ZeroClipboard, or even just to tell the user that their browser doesn’t support the functionality.

The execCommand method will return false if the action failed, for example, due to being called outside of a user-initiated callback, but on older versions of Firefox, we would also throw a security exception if you attempted to use the "cut" or "copy" APIs. Thus, if you want to be sure that you capture all failures, make sure to surround the call in a try-catch block, and also interpret an exception as a failure.

// button which we are attaching the event to
var button = ...;
// input containing the text we want to copy
var input = ...;

button.addEventListener("click", function(event) {
  event.preventDefault();
  input.select(); // Select the input node's contents
  var succeeded;
  try {
    // Copy it to the clipboard
    succeeded = document.execCommand("copy");
  } catch (e) {
    succeeded = false;
  }
  if (succeeded) {
    // The copy was successful!
  } else {
    // The copy failed :(
  }
});

The "cut" API is also exposed to web pages through the same mechanism, so just s/copy/cut/, and you’re all set to go!

Feature testing

The editor APIs provide a method document.queryCommandSupported("copy") intended to allow API consumers to determine whether a command is supported by the browser. Unfortunately, in versions of Firefox prior to 41, we returned true from document.queryCommandSupported("copy") even though the web page was unable to actually perform the copy operation. However, attempting to execute document.execCommand("copy") would throw a SecurityException. So, attempting to copy on load, and checking for this exception is probably the easiest way to feature-detect support for document.execCommand("copy") in Firefox.

var supported = document.queryCommandSupported("copy");
if (supported) {
  // Check that the browser isn't Firefox pre-41
  try {
    document.execCommand("copy");
  } catch (e) {
    supported = false;
  }
}
if (!supported) {
  // Fall back to an alternate approach like ZeroClipboard
}

Support in other browsers

Google Chrome and Internet Explorer both also support this API. Chrome uses the same restriction as Firefox (that it must be run in a user-initiated callback). Internet Explorer allows it to be called at any time, except it first prompts the user with a dialog, asking for permission to access the clipboard.

For more information about the API and browser support, see MDN documentation for document.execCommand().

About Michael Layzell

More articles by Michael Layzell…


24 comments

  1. mario

    Good information. Bookmarked!

    September 1st, 2015 at 08:22

  2. Serge

    Glad to hear it! I was so frustrated that every color picker website uses flash to just copy 6 letters of text, so I made my own one last week – http://0xrgb.com
    Chrome works now, but FF didn’t (as a fallback I just selected the color value, letting user to press Ctrl+C manually if a browser doesn’t support clipboard API).
    I’m so glad to hear that new FF will end up the era of zeroclipboard and other hacks!

    September 1st, 2015 at 08:48

  3. Josh Triplett

    Will sites have to request explicit permission to use the clipboard? Because if not, I fully expect many sites to start shoving unwanted data in the clipboard.

    September 1st, 2015 at 10:24

    1. Michael Layzell

      Flash has been available for a long time as a mechanism to copy text to the user’s clipboard on a user-initiated event. We haven’t seen it being abused to copy random text to users’ clipboards. Dialogs produce a poor user experience, and we made the judgement that maintaining the flash-style UX (allowing copy without prompt in a user-initiated callback) removed reasons for developers not to migrate.

      September 2nd, 2015 at 10:11

      1. voracity

        Isn’t it wonderful when we can make security decisions based on evidence?

        September 4th, 2015 at 21:52

  4. 4esn0k

    Thanks, that FF fires “copy” event, when the selection is empty.
    IE does not.

    September 1st, 2015 at 11:24

    1. cpeterson

      here. I just looked at the W3C draft spec and it wasn’t immediately clear to me which behavior is correct. I’ll have to test it.

      September 2nd, 2015 at 20:27

      1. cpeterson

        That should have said: “Thanks for pointing out the difference in behavior here.” :-)

        I just tested an empty selection and both IE and Safari (OS X) return false from document.execCommand(‘copy’) and don’t modify the OS clipboard. MS Edge, Chrome, and Firefox return true and don’t modify the OS clipboard. I did find an inconsistency between Chrome and Firefox I’ll need to investigate some more.

        September 2nd, 2015 at 21:06

  5. Dmitry Pashkevich

    So is there a white-list of “user-initiated events” that one can look up? For instance, I’m curious if the copy command will work on `mousemove` or `drag` too.

    September 1st, 2015 at 11:34

    1. cpeterson

      MDN says, “clipboard capability are enabled by default in any event handler that is able to pop-up a window (semi-trusted scripts).” But I don’t know which events those are.

      https://developer.mozilla.org/en-US/docs/Web/API/Document/execCommand#Browser_Compatibility

      September 2nd, 2015 at 20:36

  6. Brett Zamir

    Why is it thought that user-initiated events offer any added security whatsoever? A page can appear with a gray sheet and say “click to continue”, and I believe the requirement will be met… I’m in favor of providing powerful APIs to users, but it should be with their consent.

    September 1st, 2015 at 14:07

    1. Luke

      But unless I misunderstand, there is no “paste” execCommand – that certainly would be security problem!

      September 1st, 2015 at 20:29

      1. cpeterson

        There is an execCommand (“paste”) command, but it is only accessible to Firefox extensions, not web content.

        September 2nd, 2015 at 16:34

  7. _ck_

    What do I set in about:config to disable this api because now any website can wipe out my clipboard (or fill it) when I click on any link on the page?

    September 1st, 2015 at 14:51

    1. Michael Layzell

      I believe that the about:config preference “dom.allow_cut_copy” set to false will disable these APIs.

      September 2nd, 2015 at 10:15

    2. marsjaninzmarsa

      Now? Even before it was possible by Flash…

      September 6th, 2015 at 18:09

    3. Antoine

      You could have been tricked by Flash buttons anyway (unless you always disabled Flash)

      September 8th, 2015 at 05:12

  8. Matthew Douglass

    Won’t the copy on load example
    a) fail because it’s not during a user-initiated action
    b) if it succeeded, wipe the user’s clipboard on page load which would be pretty unexpected

    September 1st, 2015 at 16:20

    1. Michael Layzell

      It will fail (return false – not throw) because it’s not during a user-initiated action, however, even if it succeeded, it wouldn’t clear the user’s clipboard, as the user will have an empty selection. The default action specified for an empty selection is to leave the clipboard as is.

      September 2nd, 2015 at 10:02

  9. Dane MacMillan

    In my day we had to school users about Ctrl+C with fickle title text that never hung around. Next thing you know there will be a bookmark API.

    (╯°□°)╯ ┻━┻

    September 4th, 2015 at 07:39

  10. voracity

    There’s still no way to paste text, or for that matter copy text without the user clicking anything — which is as things should be for now.

    However! The only _real_ gap between web and native is this kind of permissive capability. (A lot of people talk about performance, but that’s increasingly irrelevant — at a total guess, it’d be relevant for roughly 10% of apps today, and that number is declining.)

    At some point, the web community is going to have to work out how to expose these capabilities to all web pages securely*, _discouraging_ frivolous uses of the capabilities** in a way that competes equally with native, while remaining decentralised. The last point is particularly important — it’s trivial to compete with native with centralised review, but that’s not at all what the web is about. (Otherwise, we may as well just revive interactive TV!)

    It’s a tall ask, but I hope the web community is up to it. We have things like Uber and Airbnb that manage to be partly decentralised, while still managing the security risk, so I’m hopeful.

    * ‘Secure’ _just_ means the user knows and understands what the site is doing and consents (or would consent to it if asked explicitly)
    ** By this, I also mean that the user doesn’t feel compelled to give the site a permission to get access to something unrelated; the user doesn’t get tricked into believing a permission is needed when it isn’t; and the user doesn’t grant a permission simply out of habit or because “everyone does it all the time”.

    September 4th, 2015 at 22:34

  11. zilch

    Allowing sites to destroy/replace the content of my clipboard? Seriously?

    September 7th, 2015 at 03:02

  12. Zeno Rocha

    If you’re interested on this, you might wanna check Clipboard.js too :)

    http://zenorocha.github.io/clipboard.js/

    September 27th, 2015 at 17:12

  13. Madis

    How to know if “click” event is triggered by user clicking something, or triggered via script. Can they be identified in javascript or is it done only on Firefox’s own engine in the background.

    Also, what if I use Selenium and would like copy pasteing to work (not sure how Selenium works exactly, perhaps it does not trigger click events via JS).

    October 1st, 2015 at 06:34

Comments are closed for this article.