clipboard-copy and clipboard-polyfill are both JavaScript libraries designed to simplify copying text to the system clipboard in web applications. clipboard-copy provides a minimal, modern wrapper around the native Clipboard API (navigator.clipboard.writeText), targeting environments where this API is available. In contrast, clipboard-polyfill implements a full polyfill that ensures clipboard functionality works across a wide range of browsers by falling back to legacy techniques like document.execCommand and temporary DOM elements when the modern API is unavailable.
Both clipboard-copy and clipboard-polyfill are lightweight npm packages designed to simplify copying text to the user's clipboard in web applications. While they share a common goal, their implementation strategies, browser support philosophies, and usage patterns differ significantly. Let’s break down how each works and where they shine.
clipboard-copy is a tiny utility that wraps the modern Clipboard API (navigator.clipboard.writeText) with minimal fallback logic. It assumes you're working in an environment where the Clipboard API is available or where graceful degradation is acceptable.
// Using clipboard-copy
import copy from 'clipboard-copy';
async function copyToClipboard(text) {
try {
await copy(text);
console.log('Copied!');
} catch (err) {
console.error('Failed to copy', err);
}
}
clipboard-polyfill provides a full-featured polyfill for the Clipboard API, including robust fallbacks for older browsers using hidden <textarea> elements and document.execCommand. It aims to make navigator.clipboard.writeText() work everywhere — even in environments where it’s natively unsupported.
// Using clipboard-polyfill
import { writeText } from 'clipboard-polyfill';
async function copyToClipboard(text) {
try {
await writeText(text);
console.log('Copied!');
} catch (err) {
console.error('Failed to copy', err);
}
}
💡 Note:
clipboard-polyfillalso patches the globalnavigator.clipboardobject by default (unless configured otherwise), so you can use the standard API directly after importing it.
clipboard-copy targets modern browsers only. It uses navigator.clipboard.writeText() and throws an error if the API isn’t available (e.g., in older browsers or insecure contexts like HTTP). It does not include any fallback mechanism.
This means:
clipboard-polyfill actively polyfills missing functionality. It detects whether navigator.clipboard exists and, if not, implements its own version using legacy techniques (execCommand + temporary DOM elements).
This gives you:
clipboard-copy has zero side effects. It doesn’t modify global objects or inject DOM elements. It simply calls the native API and returns the promise.
// Internally, clipboard-copy does roughly this:
export default async function copy(text) {
if (!navigator.clipboard) {
throw new Error('Clipboard API not supported');
}
return navigator.clipboard.writeText(text);
}
clipboard-polyfill may modify the DOM temporarily during copy operations. When falling back to execCommand, it creates a hidden <textarea>, appends it to the document, selects its content, and executes the copy command — then cleans up afterward.
It also patches navigator.clipboard by default:
// After import, this works even in old browsers:
await navigator.clipboard.writeText('hello');
If you prefer not to pollute globals, you can use the named export (writeText) instead.
Both libraries are subject to the same user activation requirement: clipboard writes must happen in response to a user gesture (e.g., a click). However, their behavior differs when this rule is violated.
clipboard-copy will reject with a NotAllowedError (as per spec)clipboard-polyfill will also fail, but its fallback path might behave inconsistently across older browsersAdditionally, clipboard-copy requires HTTPS because the native Clipboard API blocks access on insecure origins. clipboard-polyfill’s fallback works on HTTP, which can be useful during local development — but remember that execCommand is deprecated and unreliable in many contexts.
clipboard-copy errors are straightforward: either the API isn’t supported, or the copy operation was denied. Errors map directly to browser-native exceptions.
clipboard-polyfill abstracts away browser differences, but this can make debugging harder. For example, a failure in the fallback path might manifest as a generic error rather than a clear “execCommand not allowed” message.
You can enable debug logging in clipboard-polyfill:
import { setDebugLog } from 'clipboard-polyfill';
setDebugLog(console.log);
clipboard-copy offers no such utilities — by design.
You’re building a SaaS dashboard that only supports evergreen browsers and runs on HTTPS.
clipboard-copy// Clean, modern, and sufficient
import copy from 'clipboard-copy';
function CopyButton({ text }) {
return (
<button onClick={() => copy(text)}>
Copy
</button>
);
}
You run a documentation site that must work on older mobile browsers and during local HTTP development.
clipboard-polyfill// Reliable everywhere
import { writeText } from 'clipboard-polyfill';
function CopySnippet({ code }) {
const handleCopy = () => writeText(code);
return <button onClick={handleCopy}>Copy</button>;
}
You’re publishing a UI component library and don’t want to modify navigator.clipboard.
clipboard-polyfill (using named exports)// Safe for libraries
import { writeText } from 'clipboard-polyfill';
// navigator.clipboard remains untouched
While bundle size isn’t part of this comparison per instructions, it’s worth noting architecturally:
clipboard-copy is ~300 bytes minified — essentially negligibleclipboard-polyfill is larger due to fallback logic, but still under 5KBBoth packages are actively maintained as of 2024, with no deprecation notices on npm or GitHub.
| Feature | clipboard-copy | clipboard-polyfill |
|---|---|---|
| Core Philosophy | Thin wrapper around native API | Full polyfill with fallbacks |
| Browser Support | Modern browsers only | IE9+ via execCommand fallback |
| HTTPS Required? | Yes (enforced by browser) | No (fallback works on HTTP) |
| Global Side Effects | None | Patches navigator.clipboard by default |
| DOM Manipulation | Never | Temporarily during fallback |
| Ideal For | Modern apps on secure origins | Broad compatibility needs |
Choose clipboard-copy if:
Choose clipboard-polyfill if:
In practice, most new applications targeting contemporary browsers can safely use clipboard-copy. But if your audience includes users on legacy systems or constrained environments, clipboard-polyfill remains the more resilient choice.
Choose clipboard-copy if you're building a modern web application that runs exclusively over HTTPS and targets recent browsers (Chrome, Firefox, Safari, Edge). It’s ideal when you want the smallest possible dependency with zero side effects, and you’re comfortable with clipboard operations failing gracefully in unsupported environments. This package is perfect for SPAs, dashboards, and internal tools where browser requirements are controlled.
Choose clipboard-polyfill if you need broad browser compatibility—including older browsers like IE11—or if your application must support clipboard operations during local development over HTTP. It’s also the right choice when you want a consistent, standardized API (navigator.clipboard.writeText) to work reliably across all environments without managing fallback logic yourself. This package suits public-facing websites, documentation sites, and applications with diverse user bases.
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!
npm install clipboard-copy
const copy = require('clipboard-copy')
button.addEventListener('click', function () {
copy('This is some cool text')
})
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'.
clipboard-copy (this package): 524 B gzippedclipboard-js: 1.7 kB gzippedclipboard: 3.2 kB gzippedTesting 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.
MIT. Copyright (c) Feross Aboukhadijeh.