clipboard-copy vs clipboard-polyfill vs copy-to-clipboard
Implementing Clipboard Functionality in Modern Web Applications
clipboard-copyclipboard-polyfillcopy-to-clipboardSimilar Packages:

Implementing Clipboard Functionality in Modern Web Applications

The packages clipboard-copy, clipboard-polyfill, and copy-to-clipboard all solve the problem of copying text to the user's system clipboard, but they approach it with different philosophies regarding browser compatibility and API usage. clipboard-copy is a lightweight wrapper that strictly uses the modern asynchronous Clipboard API, requiring no fallbacks. clipboard-polyfill acts as a comprehensive shim, attempting to use the modern API first but falling back to legacy document.execCommand methods for older browsers or specific contexts like iOS Safari. copy-to-clipboard is a focused utility that primarily relies on the legacy synchronous execution command, making it highly reliable for simple text copying in environments where the modern API might be restricted or unnecessary. Choosing between them depends on whether your project targets only modern browsers, requires maximum cross-browser compatibility including mobile Safari, or needs a zero-dependency solution for simple text strings.

Npm Package Weekly Downloads Trend

3 Years

Github Stars Ranking

Stat Detail

Package
Downloads
Stars
Size
Issues
Publish
License
clipboard-copy570,711634-76 years agoMIT
clipboard-polyfill0927404 kB92 years agoMIT
copy-to-clipboard01,40133.5 kB163 months agoMIT

Clipboard Utilities: Architecture, Compatibility, and API Design

Copying data to the system clipboard is a common requirement in web apps, from "Copy Link" buttons to data export features. While the browser landscape has standardized around the Async Clipboard API, real-world constraints like iOS Safari quirks and legacy enterprise browsers force developers to make careful choices. The packages clipboard-copy, clipboard-polyfill, and copy-to-clipboard represent three distinct strategies for solving this problem. Let's examine how they differ under the hood.

๐Ÿง  Core Strategy: Modern API vs. Fallback vs. Legacy

The fundamental difference lies in which browser APIs these libraries trust.

clipboard-copy bets entirely on the modern Async Clipboard API. It does not include any fallback logic. If the browser doesn't support navigator.clipboard.writeText, the promise rejects. This makes it tiny and predictable but unsuitable for older environments.

// clipboard-copy: Strictly modern
import copy from 'clipboard-copy';

// Returns a Promise
copy('Text to copy')
  .then(() => console.log('Copied!'))
  .catch((err) => console.error('Failed:', err));

clipboard-polyfill acts as a smart bridge. It attempts to use the modern Async API first. If that fails (or if the browser is known to be problematic, like older iOS Safari), it silently falls back to the legacy document.execCommand('copy') approach using a hidden textarea. This ensures the highest success rate across devices.

// clipboard-polyfill: Hybrid approach
import * as clipboard from 'clipboard-polyfill';

// Returns a Promise, but works everywhere
clipboard.writeText('Text to copy')
  .then(() => console.log('Copied!'))
  .catch((err) => console.error('Failed:', err));

copy-to-clipboard leans on the legacy synchronous API. It creates a temporary textarea, selects the text, and executes document.execCommand('copy'). It wraps this in a try/catch block and returns a boolean. It does not use the modern Async API by default, making it synchronous and blocking.

// copy-to-clipboard: Legacy synchronous
import copy from 'copy-to-clipboard';

// Returns a boolean immediately
const success = copy('Text to copy');
if (success) {
  console.log('Copied!');
} else {
  console.error('Failed to copy');
}

๐Ÿ“ฑ Handling Mobile Safari and User Gestures

Mobile Safari (iOS) has historically been strict about clipboard access, often requiring the operation to happen directly inside a user gesture event (like a click) and sometimes rejecting the modern API in certain contexts.

clipboard-copy will fail on older iOS versions because it doesn't implement the textarea fallback required for those browsers. You must handle the rejection manually if you support these devices.

// clipboard-copy on old iOS: Will likely reject
button.addEventListener('click', () => {
  copy('Link').catch(() => {
    // You must implement your own fallback here
    alert('Please copy manually');
  });
});

clipboard-polyfill specifically includes logic to detect iOS and other tricky environments. It manages the creation of hidden elements and selection ranges internally to satisfy mobile browser security requirements.

// clipboard-polyfill on old iOS: Handles fallback automatically
button.addEventListener('click', () => {
  // Works even if navigator.clipboard is missing
  clipboard.writeText('Link').catch(() => {
    // Only catches true failures, not missing API support
  });
});

copy-to-clipboard works well on mobile because the execCommand method is widely supported on iOS, provided it runs inside a click handler. However, it offers no help if the browser eventually deprecates this method entirely.

// copy-to-clipboard on old iOS: Works via execCommand
button.addEventListener('click', () => {
  const result = copy('Link');
  if (!result) {
    // Handle failure
  }
});

๐ŸŽจ Copying Rich Content (HTML and Images)

Sometimes you need to copy more than just plain text, such as formatted HTML or images.

clipboard-copy is limited to plain text only. It calls navigator.clipboard.writeText(). If you try to pass HTML, it treats it as a string.

// clipboard-copy: Text only
// Cannot copy formatted HTML
copy('<strong>Bold Text</strong>'); 
// Result in clipboard: "<strong>Bold Text</strong>" (raw string)

clipboard-polyfill supports rich content via the clipboard.write() method, which accepts a ClipboardItem array. This allows you to provide both HTML and plain text versions, letting the target application choose the best format.

// clipboard-polyfill: Rich content support
const item = new ClipboardItem({
  'text/html': new Blob(['<strong>Bold Text</strong>'], { type: 'text/html' }),
  'text/plain': new Blob(['Bold Text'], { type: 'text/plain' })
});

clipboard.write([item]);

copy-to-clipboard is strictly for plain text. It relies on selecting text within a textarea, which cannot hold rich HTML formatting for the clipboard in a way that preserves styles when pasted into rich text editors.

// copy-to-clipboard: Text only
// No API exists for HTML or images
const success = copy('<div>Content</div>');

โšก Synchronous vs. Asynchronous Flow

The execution model affects how you structure your code, especially regarding UI feedback.

clipboard-copy and clipboard-polyfill are asynchronous. They return Promises. This is crucial because the modern Clipboard API may prompt the user for permission, which takes time. You must handle the "pending" state in your UI.

// Async pattern (clipboard-copy / clipboard-polyfill)
const handleCopy = async () => {
  setIsCopying(true); // Show spinner
  try {
    await copyFunction('Data');
    setFeedback('Success!');
  } catch (e) {
    setFeedback('Failed');
  } finally {
    setIsCopying(false);
  }
};

copy-to-clipboard is synchronous. It executes immediately and returns a result. This simplifies state management since you don't need to wait for a Promise to resolve, but it also means it cannot handle permission prompts gracefully (it just fails if permission isn't already granted).

// Sync pattern (copy-to-clipboard)
const handleCopy = () => {
  // No spinner needed, it's instant
  const success = copy('Data');
  setFeedback(success ? 'Success!' : 'Failed');
};

๐Ÿ› ๏ธ Dependency and Bundle Considerations

While we aren't listing exact byte counts, the architectural weight differs.

  • clipboard-copy: Minimalist. It wraps the native API. If the native API grows or changes, this package adapts naturally. It adds almost no logic of its own.
  • clipboard-polyfill: Heavier. It contains detection logic, fallback implementations, and helpers for creating blobs and ranges. This code is always shipped, even if the user has a modern browser (though tree-shaking can help).
  • copy-to-clipboard: Lightweight but old-school. It contains the logic to create and clean up DOM nodes (textarea) but lacks the async machinery.

๐ŸŒฑ When Not to Use These

  • Don't use clipboard-copy if you must support Internet Explorer or older iOS Safari versions without writing your own fallback.
  • Don't use copy-to-clipboard if you are building a future-proof application that needs to copy images or HTML, or if you want to align with the latest web standards.
  • Don't use any of these if you only need to copy simple text in a modern-only app; consider using the native navigator.clipboard.writeText() directly to remove a dependency entirely.
// Native approach (No library needed)
if (navigator.clipboard) {
  await navigator.clipboard.writeText('Text');
} else {
  // Fallback needed manually
}

๐Ÿ“Š Summary Table

Featureclipboard-copyclipboard-polyfillcopy-to-clipboard
Primary APIAsync Clipboard APIHybrid (Async + Fallback)Legacy execCommand
Return TypePromise<void>Promise<void>boolean
Rich ContentโŒ Noโœ… Yes (HTML/Images)โŒ No
Mobile Safariโš ๏ธ Fails on old versionsโœ… Supported via fallbackโœ… Supported
ExecutionAsynchronousAsynchronousSynchronous
Best ForModern-only appsMaximum compatibilitySimple, sync text copy

๐Ÿ’ก The Big Picture

clipboard-copy is the choice for purists. If your analytics show 99% modern browser usage, this package keeps your code clean and promise-based without the bloat of legacy workarounds.

clipboard-polyfill is the safety net. For consumer-facing apps where you cannot predict the device, this package ensures that the "Copy" button works for everyone, handling the messy details of iOS and legacy browsers so you don't have to.

copy-to-clipboard is the veteran. It solves the problem with proven, synchronous logic. It's perfect for internal dashboards or simple tools where you need to copy a string instantly and don't care about rich content or future API deprecations.

Final Thought: If you are starting a new project today, check your browser support matrix. If you can drop legacy support, using the native API or clipboard-copy is the most sustainable path. If you need to support everyone, clipboard-polyfill remains the industry standard for reliability.

How to Choose: clipboard-copy vs clipboard-polyfill vs copy-to-clipboard

  • clipboard-copy:

    Choose clipboard-copy if your application targets only modern browsers (Evergreen) and you prefer working with native Promises without extra baggage. It is the best fit for projects that do not need to support Internet Explorer or older mobile Safari versions and want to avoid the complexity of fallback logic. Since it relies entirely on the asynchronous Clipboard API, it will fail gracefully in unsupported environments rather than attempting risky workarounds.

  • clipboard-polyfill:

    Choose clipboard-polyfill if you need robust cross-browser support, including legacy browsers and specific mobile quirks like iOS Safari's handling of user gestures. This package is ideal for public-facing applications where you cannot control the user's device or browser version. It automatically handles the transition between the modern Async Clipboard API and the legacy execCommand fallback, saving you from writing complex feature detection code.

  • copy-to-clipboard:

    Choose copy-to-clipboard if you need a simple, synchronous solution for copying plain text and want to minimize dependencies. It is well-suited for internal tools, dashboards, or environments where you know the legacy document.execCommand method is supported and sufficient. Avoid this package if you need to copy rich content (like HTML or images) or if you strictly require the modern asynchronous API pattern.

README for clipboard-copy

clipboard-copy travis npm downloads size javascript style guide

Lightweight copy to clipboard for the web

The goal of this package is to offer simple copy-to-clipboard functionality in modern web browsers using the fewest bytes. To do so, this package only supports modern browsers. No fallback using Adobe Flash, no hacks. Just 30 lines of code.

Unlike other implementations, text copied with clipboard-copy is clean and unstyled. Copied text will not inherit HTML/CSS styling like the page's background color.

Supported browsers: Chrome, Firefox, Edge, Safari.

Works in the browser with browserify!

install

npm install clipboard-copy

usage

const copy = require('clipboard-copy')

button.addEventListener('click', function () {
  copy('This is some cool text')
})

API

successPromise = copy(text)

Copy the given text to the user's clipboard. Returns successPromise, a promise that resolves if the copy was successful and rejects if the copy failed.

Note: in most browsers, copying to the clipboard is only allowed if copy() is triggered in direct response to a user gesture like a 'click' or a 'keypress'.

comparison to alternatives

testing

Testing this module is currently a manual process. Open test.html in your web browser and follow the short instructions. The web page will always load the latest version of the module, no bundling is necessary.

license

MIT. Copyright (c) Feross Aboukhadijeh.