← Guides

Paste to Clipboard: How Paste Works and How to Debug It

"Paste to clipboard" is a common phrase, but it is technically backwards — you paste from the clipboard into an application. Still, the question behind the phrase is the one people really want answered: what happens when I press Ctrl+V, and why does the result sometimes look different from what I copied? This page answers that, and gives you a tool to see the paste payload with your own eyes.

→ See what your paste actually contains: open Clipboard Inspector, copy something, then paste (Ctrl+V / ⌘+V) onto the page. Every MIME type on the clipboard is displayed.

Paste shortcuts on every platform

  • Windows, Linux, ChromeOS: Ctrl + V
  • macOS: ⌘ Command + V
  • Paste as plain text (strip formatting): Ctrl + Shift + V (Windows/Linux) or ⌘ + Shift + V (Mac) — supported in most browsers and editors
  • iOS / iPadOS: Tap and hold, then Paste
  • Android: Tap and hold in the input, then Paste

What happens when you paste

  1. The OS hands the receiving application a dictionary of MIME types and their values.
  2. The application picks the MIME type it can handle best. A plain-text input picks text/plain; a rich-text editor picks text/html; an image upload picks image/png or reads a file handle.
  3. The application runs its own sanitisation or parsing. This step is why the same paste looks different in different apps — Word keeps the formatting, a <textarea> strips it, Notion rewrites it.

You never see the full dictionary unless you inspect it. Clipboard Inspector shows every entry at once so you can see what the receiving app will have to choose from.

Paste from JavaScript: the paste event

document.body.addEventListener('paste', (e) => {
  const types = e.clipboardData.types
  console.log('Paste contains:', types)

  for (const type of types) {
    const value = e.clipboardData.getData(type)
    console.log(type, value)
  }

  // Files (image paste from screenshots, etc.)
  for (const file of e.clipboardData.files) {
    console.log('File:', file.name, file.type, file.size)
  }
})

The paste event fires on the focused element first, then bubbles up. If you want to intercept paste site-wide, attach to document or document.body. If you want to stop the default insertion and handle it yourself — for example, to sanitise pasted HTML before placing it into your editor — call e.preventDefault(). See When to Call preventDefault for the full rules.

Paste to clipboard from JavaScript: the async Clipboard API

If you want to put something on the clipboard from JavaScript (so the user can paste it elsewhere), use navigator.clipboard.writeText() or navigator.clipboard.write(). This is what "copy to clipboard" buttons do. Full guide: Copy to Clipboard.

Paste as plain text: how it works

Ctrl + Shift + V in most browsers tells the receiving app to read only the text/plain representation from the clipboard and ignore the text/html. Rich-text editors implement this by listening for a modifier on the paste event, re-reading clipboardData, and inserting only the plain string. From the clipboard's perspective, both pastes contain the same data — only the consumer's behaviour changes.

If you are building a rich-text editor and want a "paste as plain text" option, the cleanest implementation is:

editor.addEventListener('paste', (e) => {
  if (e.shiftKey) {
    e.preventDefault()
    const plain = e.clipboardData.getData('text/plain')
    insertText(plain)
  }
})

Common paste bugs

  • Paste comes in with 50 KB of Word styles. The source writes heavy text/html; your editor is inserting it verbatim. Sanitise with DOMPurify — see Sanitising Pasted HTML.
  • Paste into a password field truncates at a tab. Some apps split on whitespace. Copy the password as a single contiguous string.
  • Paste image into a web app does nothing. The handler checks clipboardData.getData('text/plain') but not clipboardData.files.
  • Paste event does not fire in a custom component. The component is not focused or not contenteditable. Add tabindex="0" and focus it.

Inspect what your paste produced

Open Clipboard Inspector in another tab, copy the content you are trying to paste, and press Ctrl+V on the inspector page. You will see every MIME type and value the clipboard contains — the exact same data your real paste handler would receive.

Related reading