clipboard-polyfill, copy-to-clipboard, react-clipboard.js, react-copy-to-clipboard, and use-clipboard-copy are npm packages that help web applications copy text (and sometimes rich content) to the user's clipboard. They address limitations of the native Clipboard API by providing cross-browser compatibility, fallback mechanisms for older browsers, and convenient abstractions—especially within React applications. While all aim to solve the same core problem, they differ significantly in scope, browser support strategy, API design, and suitability for modern versus legacy environments.
Copying text to the clipboard is a common feature in web apps — from sharing links to copying code snippets. While the modern navigator.clipboard.writeText() API works well in secure contexts, legacy browser support and complex use cases (like copying rich content or handling fallbacks) often require a dedicated library. The five packages under review — clipboard-polyfill, copy-to-clipboard, react-clipboard.js, react-copy-to-clipboard, and use-clipboard-copy — each approach this problem differently. Let’s examine their technical trade-offs.
clipboard-polyfillThis package provides a standards-compliant polyfill for the Clipboard API. It implements writeText(), readText(), and even supports writing rich content like HTML or images via write(). Crucially, it detects native support and only falls back to legacy methods (like document.execCommand) when needed.
import { writeText } from 'clipboard-polyfill';
// Works in all browsers, uses native API where available
await writeText('Hello, world!');
It also ships with optional modules (clipboard-polyfill/text, clipboard-polyfill/overwrite-globals) for fine-grained control over bundle size and global pollution.
copy-to-clipboardA minimal, zero-dependency utility focused solely on copying plain text. It uses navigator.clipboard.writeText() when available and gracefully degrades to execCommand in older environments. Unlike clipboard-polyfill, it does not expose read operations or rich content support.
import copy from 'copy-to-clipboard';
// Returns boolean indicating success
const success = copy('Hello, world!');
It offers basic configuration like specifying a temporary DOM element for the fallback path:
copy('text', { target: document.body });
react-clipboard.jsThis is a React wrapper around the original clipboard.js (a popular vanilla JS library by Zeno Rocha). It requires you to attach a data-clipboard-text attribute to a DOM element and then initialize the clipboard behavior via a React hook or component.
import { useClipboard } from 'react-clipboard.js';
function MyComponent() {
const { copied, copy } = useClipboard();
return (
<button data-clipboard-text="Hello, world!" onClick={copy}>
{copied ? 'Copied!' : 'Copy'}
</button>
);
}
Note: This library depends on the underlying clipboard.js, which manipulates the DOM directly and requires a real DOM node with specific attributes.
react-copy-to-clipboardA straightforward React component that wraps copy-to-clipboard. It provides a render-prop-style API or a simple component that triggers copy on click.
import { CopyToClipboard } from 'react-copy-to-clipboard';
function App() {
return (
<CopyToClipboard text="Hello, world!">
<button>Copy</button>
</CopyToClipboard>
);
}
It passes through an onCopy callback with success status:
<CopyToClipboard text="text" onCopy={(text, result) => console.log(result)}>
<button>Copy</button>
</CopyToClipboard>
use-clipboard-copyA custom React hook that encapsulates clipboard logic using copy-to-clipboard under the hood. It returns state (value, success) and an action (copy). Designed for composition rather than wrapping JSX.
import useClipboard from 'use-clipboard-copy';
function App() {
const clipboard = useClipboard();
return (
<div>
<input value={clipboard.value} onChange={e => clipboard.copy(e.target.value)} />
{clipboard.success && <span>Copied!</span>}
</div>
);
}
It also supports options like timeout to auto-reset the success state:
const clipboard = useClipboard({ timeout: 1000 });
clipboard-polyfill aims for full spec compliance. It handles edge cases like Safari’s clipboard permission model and iOS quirks more robustly because it’s built as a true polyfill.copy-to-clipboard, react-copy-to-clipboard, and use-clipboard-copy use a simpler fallback strategy: try navigator.clipboard.writeText(), else use execCommand. They may fail silently in some older or restricted environments.react-clipboard.js inherits the behavior of clipboard.js, which relies entirely on execCommand and does not use the modern Clipboard API at all. This means it won’t benefit from async/await patterns or proper error handling in modern browsers.clipboard-polyfill throws standard DOMExceptions (e.g., NotAllowedError) that you must catch:try {
await writeText('text');
} catch (err) {
console.error('Copy failed:', err.name);
}
copy-to-clipboard returns false on failure but doesn’t explain why:if (!copy('text')) {
alert('Copy failed — please try manually');
}
react-copy-to-clipboard passes the boolean result to onCopy, same as above.use-clipboard-copy only tracks success/failure state, not the cause.react-clipboard.js provides no programmatic error feedback — you only get a copied boolean.clipboard-polyfill is modular. You can import only writeText to keep size minimal.copy-to-clipboard is tiny (~500 bytes minified) and has zero dependencies.react-clipboard.js pulls in the entire clipboard.js (~3KB), which includes DOM manipulation logic irrelevant in React.react-copy-to-clipboard and use-clipboard-copy both depend on copy-to-clipboard, so their overhead is minimal beyond the React integration layer.Only clipboard-polyfill supports copying HTML or images via the write() method:
import { write } from 'clipboard-polyfill';
const dt = new DataTransfer();
dt.items.add('Formatted text', 'text/html');
dt.items.add('Plain text', 'text/plain');
write(dt);
All other packages are text-only.
You just need to copy a URL string on button click, with visual feedback.
use-clipboard-copy or react-copy-to-clipboard// With use-clipboard-copy
const clipboard = useClipboard({ timeout: 1500 });
return (
<button onClick={() => clipboard.copy(url)}>
{clipboard.success ? 'Copied!' : 'Copy link'}
</button>
);
You want to preserve formatting when users paste into Word or email.
clipboard-polyfillconst html = '<code class="language-js">console.log("hello")</code>';
const text = 'console.log("hello")';
const dt = new DataTransfer();
dt.items.add(html, 'text/html');
dt.items.add(text, 'text/plain');
await write(dt);
Your app must run in old browsers without async/await support.
copy-to-clipboard (used synchronously)execCommand, and doesn’t rely on Promises.// Synchronous fallback
var success = copy('text');
if (!success) {
// Fallback to manual instructions
}
Note:
clipboard-polyfilldropped IE11 support in v4+. Use v3 if you must support it.
You have a table where each row has a “copy” button for its ID, and you don’t want to wrap every button in a component.
copy-to-clipboard (direct import)function Row({ id }) {
const handleCopy = () => {
if (copy(id)) {
showToast('Copied!');
}
};
return <button onClick={handleCopy}>Copy ID</button>;
}
As of 2024:
react-clipboard.js is effectively deprecated. Its underlying dependency, clipboard.js, is in maintenance mode and hasn’t been updated since 2020. More critically, it doesn’t use the modern Clipboard API, relying solely on the obsolete execCommand method. Avoid in new projects.clipboard-polyfill, copy-to-clipboard, react-copy-to-clipboard, use-clipboard-copy) are actively maintained and compatible with current browsers.| Package | Modern API | Rich Content | React Hook | IE11 Support | Error Details |
|---|---|---|---|---|---|
clipboard-polyfill | ✅ | ✅ | ❌ | ❌ (v4+) | ✅ (exceptions) |
copy-to-clipboard | ✅ (with fallback) | ❌ | ❌ | ✅ | ❌ (boolean only) |
react-clipboard.js | ❌ | ❌ | ✅ | ✅ | ❌ |
react-copy-to-clipboard | ✅ (via copy-to-clipboard) | ❌ | ❌ (component) | ✅ | ❌ |
use-clipboard-copy | ✅ (via copy-to-clipboard) | ❌ | ✅ | ✅ | ❌ |
clipboard-polyfill.use-clipboard-copy (hook) or react-copy-to-clipboard (component).copy-to-clipboard directly.react-clipboard.js — it’s outdated and doesn’t leverage modern browser capabilities.Choose based on whether you need rich content support, how much you care about error diagnostics, and whether you’re in a React context. For most modern web apps, clipboard-polyfill or use-clipboard-copy will serve you best.
Choose copy-to-clipboard if you want a tiny, zero-dependency utility that copies plain text with a simple synchronous or asynchronous interface. It’s perfect for non-React projects or when you need minimal overhead and basic fallback to execCommand for older browsers, including IE11. However, it provides only boolean success feedback and no rich content support.
Choose clipboard-polyfill if you need full compliance with the modern Clipboard API specification, including support for copying rich content like HTML or images, and robust handling of permissions and edge cases across browsers. It’s ideal for applications that prioritize standards compliance and must work reliably in both modern and slightly older secure contexts, but note it no longer supports IE11 as of v4+.
Avoid react-clipboard.js in new projects. It wraps the outdated clipboard.js library, which relies exclusively on the deprecated execCommand API and does not use the modern navigator.clipboard at all. This limits its reliability in modern browsers and prevents proper async error handling. Existing implementations should migrate to alternatives.
Choose react-copy-to-clipboard if you're in a React environment and prefer a declarative component-based API that wraps copy-to-clipboard. It’s straightforward for simple use cases like wrapping a button to copy static text, but offers no additional features beyond what copy-to-clipboard provides and lacks rich content or detailed error reporting.
Choose use-clipboard-copy if you're building a React application and want a clean, composable hook that manages both the copy action and success state (with optional auto-reset). It’s built on copy-to-clipboard, so it inherits its simplicity and IE11 support, making it ideal for typical React UIs that only need to copy plain text with visual feedback.
Simple module exposing copy function that will try to use execCommand with fallback to IE-specific clipboardData interface and finally, resort to usual prompt with proper text content and message.
import copy from 'copy-to-clipboard';
copy('Text');
// Copy with options
copy('Text', {
debug: true,
message: 'Press #{key} to copy',
});
copy(text: string, options: object): boolean — tries to copy text to clipboard. Returns true if no additional keystrokes were required from user (so, execCommand, IE's clipboardData worked) or false.
| Value | Default | Notes |
|---|---|---|
| options.debug | false | Boolean. Optional. Enable output to console. |
| options.message | Copy to clipboard: #{key}, Enter | String. Optional. Prompt message. * |
| options.format | "text/html" | String. Optional. Set the MIME type of what you want to copy as. Use text/html to copy as HTML, text/plain to avoid inherited styles showing when pasted into rich text editor. |
| options.onCopy | null | function onCopy(clipboardData: object): void. Optional. Receives the clipboardData element for adding custom behavior such as additional formats |
* all occurrences of #{key} are replaced with ⌘+C for macOS/iOS users, and Ctrl+C otherwise.
Works everywhere where prompt* is available. Works best (i.e. without additional keystrokes) in Chrome, FF, Safari 10+, and, supposedly, IE/Edge.
Note: does not work on some older iOS devices.
* – even though Safari 8 has prompt, you cannot specify prefilled content for prompt modal – thus it doesn't work as expected.
npm i --save copy-to-clipboard
<script src="https://wzrd.in/standalone/copy-to-clipboard@latest" async></script>
You will have window.copyToClipboard exposed for you to use.
This project has some automated tests, that will run using nightwatch on top of selenium.
npm i
npm test
This library has built-in Typescript definitions.
import * as copy from 'copy-to-clipboard';