clipboard, clipboard-polyfill, copy-to-clipboard, react-copy-to-clipboard, and vue-clipboard2 are JavaScript libraries that simplify copying text to the system clipboard across different browsers and environments. They abstract away the complexities of the native document.execCommand('copy') API (now deprecated) and the modern asynchronous navigator.clipboard.writeText() API, handling fallbacks, permissions, and browser inconsistencies. These packages differ significantly in scope: some are framework-agnostic utilities (clipboard, clipboard-polyfill, copy-to-clipboard), while others provide React or Vue-specific bindings (react-copy-to-clipboard, vue-clipboard2).
Copying text to the clipboard seems simple, but browser inconsistencies, security restrictions, and the deprecation of execCommand make it surprisingly tricky. The five packages under review tackle this problem differently — from DOM-centric helpers to modern promise-based utilities and framework wrappers. Let’s cut through the noise and see which tool fits your architecture.
Before diving in, note that vue-clipboard2 is officially deprecated. Its GitHub repository and npm page state: "This package is no longer maintained. Please use @soerenmartius/vue3-clipboard instead." Do not use it in new projects. We’ll still cover it briefly for legacy context, but treat it as a cautionary tale.
clipboard: Declarative DOM Bindingclipboard attaches copy behavior directly to HTML elements using data attributes. You never call a function — just add attributes like data-clipboard-text to a button, and the library handles the rest on click.
<!-- HTML setup -->
<button id="btn" data-clipboard-text="Hello World">Copy</button>
// JS initialization
import ClipboardJS from 'clipboard';
new ClipboardJS('#btn');
It listens for clicks, extracts text from attributes, and attempts to copy. Works only in response to user gestures (required by browser security).
clipboard-polyfill: Standards-Based Promise APIclipboard-polyfill provides a clean, modern interface aligned with the official navigator.clipboard API. It returns promises and handles fallbacks internally.
import { writeText } from 'clipboard-polyfill';
async function copyHandler() {
try {
await writeText('Hello World');
console.log('Copied!');
} catch (err) {
console.error('Failed to copy', err);
}
}
It automatically uses navigator.clipboard.writeText() when available and falls back to legacy methods (with proper sandboxing) in older browsers. Also works in non-DOM environments like Web Workers.
copy-to-clipboard: Minimalist Functioncopy-to-clipboard exports a single synchronous function that tries to copy text and returns a boolean success status.
import copy from 'copy-to-clipboard';
function handleClick() {
const success = copy('Hello World');
if (success) {
console.log('Copied!');
}
}
No promises, no callbacks — just fire-and-forget. Internally, it uses a temporary textarea element to perform the copy operation.
react-copy-to-clipboard: React Component WrapperThis package wraps copy-to-clipboard in a React component. You render it with text and onCopy props, and it clones its child with extra props.
import { CopyToClipboard } from 'react-copy-to-clipboard';
function App() {
return (
<CopyToClipboard text="Hello World" onCopy={() => console.log('Copied!')}>
<button>Copy</button>
</CopyToClipboard>
);
}
Under the hood, it calls copy-to-clipboard when the child element is clicked.
vue-clipboard2: Deprecated Vue DirectiveHistorically, this provided a Vue directive for copying:
// ❌ DO NOT USE — deprecated
import VueClipboard from 'vue-clipboard2';
Vue.use(VueClipboard);
<template>
<button v-clipboard:copy="'Hello World'">Copy</button>
</template>
But again — this package is unmaintained and should be avoided.
All these libraries must contend with two hard constraints:
navigator.clipboard outside of secure contexts.Here’s how they handle it:
clipboard: Only works on click events. Fails silently in unsupported contexts.clipboard-polyfill: Uses the standard permission API when possible. Throws clear errors when blocked, and includes a shouldShowPermissionPrompt() helper.copy-to-clipboard: Tries to copy immediately. Returns false if blocked, but gives no details why.react-copy-to-clipboard: Inherits copy-to-clipboard’s behavior — no error context.vue-clipboard2: Same as clipboard — gesture-bound with minimal error feedback.Your choice depends heavily on whether you prefer programmatic control (calling functions from JS) or declarative binding (attaching behavior via HTML/JSX).
clipboard-polyfill if you want modern promise handling and detailed error reporting.copy-to-clipboard if you just need a fire-and-forget boolean result.// clipboard-polyfill: async/await with error details
try {
await writeText(text);
} catch (err) {
if (err.name === 'NotAllowedError') {
showPermissionGuide();
}
}
// copy-to-clipboard: simple boolean
if (!copy(text)) {
alert('Copy failed — try manually');
}
clipboard for vanilla JS/jQuery apps with static buttons.react-copy-to-clipboard if you’re in React and like component composition.<!-- clipboard: pure HTML -->
<button data-clipboard-text="...">Copy</button>
{/* react-copy-to-clipboard: JSX */}
<CopyToClipboard text="..."><button>Copy</button></CopyToClipboard>
react-copy-to-clipboard feels natural but adds an extra dependency layer. Many teams skip it and call clipboard-polyfill directly inside event handlers for more control.// Common React pattern without wrapper
function CopyButton({ text }) {
const handleCopy = async () => {
try {
await writeText(text);
// update UI state, etc.
} catch (err) { /* handle */ }
};
return <button onClick={handleCopy}>Copy</button>;
}
vue-clipboard2 is dead, the best path is using clipboard-polyfill directly in methods:// Vue 3 Composition API example
import { writeText } from 'clipboard-polyfill';
export default {
methods: {
async copyText(text) {
try {
await writeText(text);
// handle success
} catch (err) {
// handle error
}
}
}
};
clipboard-polyfill is the safest bet for new projects. It’s actively maintained, follows web standards, and works everywhere from SPAs to Web Workers.| Package | API Style | Async Support | Error Details | Framework-Specific | Maintenance Status |
|---|---|---|---|---|---|
clipboard | Declarative DOM | ❌ | ❌ | None | ✅ Active |
clipboard-polyfill | Programmatic | ✅ Promise | ✅ | None | ✅ Active |
copy-to-clipboard | Programmatic | ❌ | ❌ (boolean) | None | ✅ Active |
react-copy-to-clipboard | React Component | ❌ | ❌ | React | ✅ Active |
vue-clipboard2 | Vue Directive | ❌ | ❌ | Vue 2 | ❌ Deprecated |
clipboard-polyfill. It’s the most future-proof, gives you detailed error handling, and aligns with web standards. Call it directly from your framework’s event handlers.copy-to-clipboard is fine.clipboard works well if you’re already using data attributes extensively.react-copy-to-clipboard unless you strongly prefer its component API — most teams gain more flexibility by using clipboard-polyfill directly.vue-clipboard2 entirely. Use clipboard-polyfill in methods or composables.Remember: no library can bypass browser security. Always design your UI to handle copy failures gracefully — show a fallback tooltip, highlight the text for manual selection, or guide users through permission prompts when needed.
Choose copy-to-clipboard if you want the simplest possible function-based API for programmatic copying without any DOM coupling. It’s a good fit for utility-heavy applications where you trigger copies from JavaScript logic rather than HTML attributes, and you prefer minimal abstraction over feature richness.
Choose clipboard if you need a DOM-focused utility that binds copy behavior directly to HTML elements via data attributes, and your app uses buttons or other interactive elements where declarative markup is preferred. It’s ideal for simple static sites or jQuery-style apps but requires manual DOM setup and doesn’t support programmatic copying outside of user-triggered events.
Avoid vue-clipboard2 in new projects — it is officially deprecated as of 2021 and unmaintained. The author recommends migrating to @soerenmartius/vue3-clipboard for Vue 3 or using a framework-agnostic alternative like clipboard-polyfill. Do not use it for production applications due to lack of updates and security patches.
Choose clipboard-polyfill if you require a lightweight, modern, framework-agnostic solution that prioritizes standards compliance and works reliably in both browser and non-browser environments (like Web Workers). It supports both promise-based and callback APIs, handles permission prompts gracefully, and actively maintains compatibility with the latest web standards.
Choose react-copy-to-clipboard only if you’re working in a React codebase and prefer a component-based API that integrates naturally with JSX. Note that it wraps copy-to-clipboard under the hood, so it inherits its simplicity but adds React-specific ergonomics like render props or children-as-function patterns.
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';