A clipboard magic trick – how to use different MIME types with the Clipboard API (#note)

I discovered a web development magic trick from Cyrus Roshan today. It took me a good 20 minutes to figure out how the trick works, and I learned some things about JavaScript clipboard handling and MIME types. Sounds intriguing? Rea…


This content originally appeared on Stefan Judis Web Development and was authored by Stefan Judis

I discovered a web development magic trick from Cyrus Roshan today. It took me a good 20 minutes to figure out how the trick works, and I learned some things about JavaScript clipboard handling and MIME types. Sounds intriguing? Read on!

Try the magic tricks yourself; I'll wait. 😉

If you didn't try it, here's the flow:

  1. You're tasked to click an ASCII art play card. The card's characters are automatically copied to your clipboard using JavaScript.
  2. Then, a new screen tells you to paste the copied ASCII card into a textarea (which works as expected).
  3. Next, you're told to open a new Google Doc and paste your clipboard content into it (the ASCII art playing card).
  4. The just copied ASCII art now includes a new line telling you to paste the same content into the URL bar, and boom! 🪄 You just pasted Cyrus' Twitter profile URL.

Whoot? That's magic! 🤯

The Clipboard API

After creating fifteen different Google documents wondering if Cyros somehow injects JavaScript into Google Docs (which he doesn't), I figured out how this trick works.

Cyros' page leverages a nifty feature of the JavaScript Clipboard API (navigator.clipboard), and like every magic trick, once you know how it works, it's stupidly simple.

If you've been doing web development long enough, you might remember the document.execCommand('copy') command. This old way to interact with the clipboard is now deprecated and replaced by the Clipboard API. The newer API has the single purpose of interacting with the clipboard and works asynchronously. Yay!

But does the Clipboard API work everywhere today? At first look, navigator.clipboard seems to be cross-browser supported...

MDN Compat Data (source)
Browser support info for Clipboard
chrome chrome_android edge firefox firefox_android safari safari_ios samsunginternet_android webview_android
66 66 79 63 63 13.1 13.4 9.0 66

... but watch out! Looking deeper into it, you'll find out that just because navigator.clipboard is available, it doesn't mean all functionality is available.

How to place plain text in the clipboard

Putting text into the clipboard is straightforward using the API. Here's an example.

await navigator.clipboard.writeText(
  "That's some cool copied text, isn't it?"
);

Click the button below and paste the new clipboard content into the input fields to confirm it works.

[Interactive component: visit the article to see it...]

writeText covers many standard use cases, but it's not what the magic trick uses. Let's dig deeper!

How to write different MIME types to the clipboard

As seen, placing text on the clipboard is quickly done. But how would you handle images or other text formats such as richtext or HTML? Is it possible to put these into the clipboard with JavaScript, too?

There's another method available to put content in the clipboard – clipboard.write.

await navigator.clipboard.write([
  new ClipboardItem({
    'text/plain': new Blob(["That's some cool plain text, isn't it?"], {
      type: 'text/plain',
    }),
  }),
]);

clipboard.write doesn't accept strings but ClipboardItems. The main difference between the two methods is that if you want to put anything but plain text into the clipboard, you must define the matching MIME type using a ClipboardItem.

It's more code to write but still a decent experience in my opinion. Sweet!

Unfortunately, neither navigator.clipboard.write nor the global ClipboardItem property is defined in Firefox at the time of writing (both are behind the dom.events.asyncClipboard.clipboardItem flag).

MDN Compat Data (source)
Browser support info for ClipboardItem
chrome chrome_android edge firefox firefox_android safari safari_ios samsunginternet_android webview_android
66 66 79 87* Non 13.1 13.4 9.0 66

I didn't do the research but if you're looking for a cross-browser solution to place things other than text in the clipboard, I'm sure some libraries have you covered.

And here's annother example to play with. It looks the same as the previous one, but now it uses navigator.clipboard.write.

Fill up your clipboard!

[Interactive component: visit the article to see it...]

Can you already imagine how the magic trick works now that you've seen some code?

That's right; the trick is based on different content MIME types. Input fields and textareas handle pasted plain text just fine, but there are obviously other available MIME types.

A clipboard could hold types of image/gif, image/jpeg, text/rtf, the good old text/html, and all sorts of fanciness.

And thanks to the Clipboard API, you're in control of the MIME type and can even store text and images in the same write operation.

And it's not only a single operation; it's even a single clipboard entry.

navigator.clipboard.write([
  new ClipboardItem({
    'text/plain': new Blob(["That's some cool plain text, isn't it?"], {
      type: 'text/plain',
    }),
    'text/html': new Blob(
      [
        '<div style="/* some styles */">Oh yeah - text/html!</div>',
      ],
      {
        type: 'text/html',
      }
    ),
  }),
]);

The example above shows how to put different content as plain text and HTML into your clipboard. 😲

Now it's only a matter of where you paste the content to see this magic in action.

A div with an contentEditable attribute can accept and render HTML. 😲 If you paste content with the MIME type text/html into it, it will render it just fine.

To prove it, hit the button below and see what happens when you paste it into the input fields and the editable div.

[Interactive component: visit the article to see it...]

Cyrus' trick uses this functionality.

Initially, the magic trick puts plain text into the clipboard, but later on, it stores a ClipboardItem with multiple MIME types. text/plain holds his Twitter profile URL and text/html includes the ASCII art card. Google Docs then renders the pasted HTML, whereas the URL bar renders the plain text.

How to inspect your clipboard

While I was debugging the magic trick, I discovered that inspecting your clipboard isn't straightforward on MacOS. Even though the Finder provides a way to look at what's in the clipboard (Finder > Edit > Show clipboard), it always shows the plain text entry.

I built a quick clipboard inspector using the Clipboard API's read methods. And here it became very interesting.

Unfortunately, it's the same story of Firefox not supporting complex clipboard interactions (it's behind another flag – dom.events.asyncClipboard.read) and even though Safari supports navigator.clipboard.write it has a surprise for us.

MDN Compat Data (source)
Browser support info for clipboard.read
chrome chrome_android edge firefox firefox_android safari safari_ios samsunginternet_android webview_android
86 86 79 90* Nope 13.1 13.4 12.0 84

MDN explains to use navigator.read as follows:

try {
  const permission = await navigator.permissions.query({ name: 'clipboard-read' });
  if (permission.state === 'denied') {
    throw new Error('Not allowed to read clipboard.');
  }
  const clipboardContents = await navigator.clipboard.read();
  for (const item of clipboardContents) {
    // do things with the clipboard entries
  }
} catch (error) {
  console.error(error.message);
}

It works fine in Chromiums, but it turns out that Safari doesn't support navigator.permissions. 🤦‍♂️

MDN Compat Data (source)
Browser support info for Permissions
chrome chrome_android edge firefox firefox_android safari safari_ios samsunginternet_android webview_android
43 43 79 46 46 Nope Non 4.0 Nein

This means you have to check if navigator.permissions is available, too. And if it is, ask for permissions and if not, try to use navigator.clipboard.read anyways.

In this case, Safari shows a little "Paste" mini permission dialog. If you don't click it, navigator.clipboard.read will throw an exception. Ufff...

Here's a summary on how to use navigator.clipboard.read:

  • For Chromiums you should use the Permissions API.
  • You can't read the clipboard content using Firefox.
  • In Safari you just have to try it and see if it works.

Have fun with it below.

[Interactive component: visit the article to see it...]

Side note: not all clipboard content is accessible

Inspecting and accessing text-based clipboard content seemed to work fine in Chromiums. But if I copy an image from the MacOS Finder navigator.clipboard.read doesn't like that either and throws a No valid data on clipboard exception.

So, if you're planning to use navigator.clipboard.read, you have to feature detect the Permissions API and also make sure to try/catch all your read calls.

Conclusion

This little magic trick became quite a journey. But here's what I learned:

  1. The Clipboard API allows you to write multiple entries in different MIME types to the clipboard.
  2. Using the Clipboard API is still a pain if you're targeting all major browsers.
  3. Not everything in your clipboard is accessible via JavaScript.

If you want to learn more there's also a good article on the async Clipboard API on web.dev and with this, happy pasting! 👋


Reply to Stefan


This content originally appeared on Stefan Judis Web Development and was authored by Stefan Judis


Print Share Comment Cite Upload Translate Updates
APA

Stefan Judis | Sciencx (2022-04-27T22:00:00+00:00) A clipboard magic trick – how to use different MIME types with the Clipboard API (#note). Retrieved from https://www.scien.cx/2022/04/27/a-clipboard-magic-trick-how-to-use-different-mime-types-with-the-clipboard-api-note/

MLA
" » A clipboard magic trick – how to use different MIME types with the Clipboard API (#note)." Stefan Judis | Sciencx - Wednesday April 27, 2022, https://www.scien.cx/2022/04/27/a-clipboard-magic-trick-how-to-use-different-mime-types-with-the-clipboard-api-note/
HARVARD
Stefan Judis | Sciencx Wednesday April 27, 2022 » A clipboard magic trick – how to use different MIME types with the Clipboard API (#note)., viewed ,<https://www.scien.cx/2022/04/27/a-clipboard-magic-trick-how-to-use-different-mime-types-with-the-clipboard-api-note/>
VANCOUVER
Stefan Judis | Sciencx - » A clipboard magic trick – how to use different MIME types with the Clipboard API (#note). [Internet]. [Accessed ]. Available from: https://www.scien.cx/2022/04/27/a-clipboard-magic-trick-how-to-use-different-mime-types-with-the-clipboard-api-note/
CHICAGO
" » A clipboard magic trick – how to use different MIME types with the Clipboard API (#note)." Stefan Judis | Sciencx - Accessed . https://www.scien.cx/2022/04/27/a-clipboard-magic-trick-how-to-use-different-mime-types-with-the-clipboard-api-note/
IEEE
" » A clipboard magic trick – how to use different MIME types with the Clipboard API (#note)." Stefan Judis | Sciencx [Online]. Available: https://www.scien.cx/2022/04/27/a-clipboard-magic-trick-how-to-use-different-mime-types-with-the-clipboard-api-note/. [Accessed: ]
rf:citation
» A clipboard magic trick – how to use different MIME types with the Clipboard API (#note) | Stefan Judis | Sciencx | https://www.scien.cx/2022/04/27/a-clipboard-magic-trick-how-to-use-different-mime-types-with-the-clipboard-api-note/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.