跳转到内容

能力 · API

Async Clipboard API

发布于

自 2024-06 起新近可用W3C 草案

Async Clipboard API 即 navigator.clipboard,用 Promise 读写系统剪贴板,取代 document.execCommand('copy') 与 ('paste')。纯文本走 writeText() 和 readText();图片、HTML 与多格式载荷封装成 ClipboardItem,经 write() 和 read() 传输。

Chrome 66 提供了 writeText() 与 readText(),Chrome 76 补上 read()、write() 与 ClipboardItem;Edge 79 与 Samsung Internet 12.0 跟随 Chromium。Firefox 63 加入 writeText(),125 加入 readText(),127 加入 read()、write() 与 ClipboardItem。macOS 上的 Safari 13.1 与 iOS 上的 Safari 13.4 一次性提供四个方法(BCD api.Clipboard)。该 API 只存在于安全上下文的 Window 中:localhost 以外的 http:// 源上 navigator.clipboard 为 undefined,Chromium 在 worker 中的读取以 NotAllowedError 拒绝。

navigator.clipboard.readText()
navigator.clipboard.read()
navigator.clipboard.read(formats)
navigator.clipboard.writeText(data)
navigator.clipboard.write(data)
new ClipboardItem(items)
new ClipboardItem(items, options)
clipboardItem.getType(type)
ClipboardItem.supports(type)

readText() 返回 Promise<DOMString>;read() 返回 Promise<sequence<ClipboardItem>>,返回的条目只带类型名,字节在调用 getType() 时才读取;writeText() 与 write() 返回 Promise<undefined>。读取在 Firefox 125+ 与 Safari 13.1+ 需要瞬时用户激活,在 Chrome 中需要激活或已授予的 clipboard-read 权限。写入在 Firefox 63+ 与 Safari 13.1+ 需要瞬时激活,Chrome 自 107 起需要激活或 clipboard-write 权限(107 之前只看权限)。ClipboardItem.supports() 是静态同步方法,存在于 Chrome 121、Firefox 127 与 Safari 18.4。

三个方法参数加上 ClipboardItem 构造函数的两个参数,就是规范定义的全部输入。

参数 类型 必填 说明
data(writeText) DOMString 是 以 text/plain;charset=utf-8 blob 写入。Windows 上浏览器会先把 \n 换成 \r\n。
data(write) sequence<ClipboardItem> 是 Chrome 76+ 与 Firefox 127+ 只接受恰好一个条目;两个及以上的数组以 NotAllowedError 拒绝(BCD api.Clipboard.write)。
formats(read) ClipboardUnsanitizedFormats 否 只有一个成员 unsanitized: sequence<DOMString>,请求原始而非净化后的字节。Chrome 122 只对 text/html 生效;其他类型会拒绝。
items(构造函数) record<DOMString, ClipboardItemData> 是 MIME 类型到 Promise<Blob or DOMString> 的映射(直接传 Blob 或字符串会被包装)。以 "web " 为前缀的键是自定义格式(Chrome 104)。
options.presentationStyle "unspecified"、"inline" 或 "attachment" 否 默认 "unspecified",给粘贴目标的提示。Chrome 未实现;Firefox 127 与 Safari 13.1 在读取到的条目上暴露它。
type(getType、supports) DOMString 是 一个 MIME 类型,可带 "web " 前缀。

ClipboardItem 暴露 types(其 MIME 类型字符串的冻结数组)与 presentationStyle。每个浏览器都必须接受的强制类型是 text/plain、text/html 与 image/png;image/svg+xml 属于可选类型,Chrome 124 提供。

除 ClipboardItem 构造函数和 getType() 的同步部分外,所有方法都返回被拒绝的 Promise 而不是直接抛出。

异常 条件
NotAllowedError read() 或 readText() 的「check clipboard read permission」失败(没有瞬时激活也没有已授予的 clipboard-read);write() 或 writeText() 的写入检查失败;blob 类型不在强制与可选类型之内;净化未能完成;某个表示的 Promise 被拒绝;read(formats) 指定的 unsanitized 类型不在可选未净化列表内;Chrome 与 Firefox 中传入多个 ClipboardItem;Chromium 中文档没有焦点;clipboard-read 或 clipboard-write 被 Permissions Policy 拒绝。
NotFoundError readText() 时剪贴板没有 text/plain 表示,或该表示解码失败。
TypeError new ClipboardItem() 的 items 为空、某个键无法解析为 MIME 类型、或同一类型出现两次;getType() 的 type 无法解析。
InvalidStateError 对 read() 得到的条目调用 getType() 时系统剪贴板已变化,或该条目对应的系统条目已不存在。
DataError 仅 Chromium:ClipboardItemData 的 Promise 无法读取或解码,或处理 paste 事件期间剪贴板内容发生变化。

Firefox 多加了一道规范未命名的浏览器层关卡:read() 与 readText() 会弹出用户必须接受的粘贴提示,只有剪贴板内容同源时才跳过(BCD api.Clipboard.read)。拒绝该提示会以 NotAllowedError 拒绝。

每个示例都只检测它真正需要的方法,并给出方法缺失时走的分支。写入示例要在 click 处理函数中运行,这样瞬时激活仍然有效。

复制文本,缺少支持时回退到隐藏 textarea

Section titled “复制文本,缺少支持时回退到隐藏 textarea”

navigator.clipboard.writeText() 覆盖 Chrome 66+、Firefox 63+ 与 Safari 13.1+;更老的版本以及任何 http:// 页面需要已废弃的 document.execCommand('copy'),它在这些引擎中仍可用于纯文本。

async function copyText(text) {
if (navigator.clipboard?.writeText) {
await navigator.clipboard.writeText(text);
return 'async';
}
const area = document.createElement('textarea');
area.value = text;
area.setAttribute('readonly', '');
area.style.position = 'fixed';
area.style.opacity = '0';
document.body.append(area);
area.select();
const ok = document.execCommand('copy');
area.remove();
return ok ? 'legacy' : 'failed';
}
document.querySelector('#copy').addEventListener('click', async () => {
const result = await copyText(location.href);
console.log(`copied via ${result}`);
});

函数返回实际走的路径,界面只在其中一条成功时才显示「已复制」;浏览器拒绝时 execCommand 返回 false 而不是抛出。

在一个条目里同时写入 PNG 与 HTML 回退

Section titled “在一个条目里同时写入 PNG 与 HTML 回退”

一个 ClipboardItem 可以携带多种表示;粘贴目标挑选它能理解的最丰富的那种。有 ClipboardItem.supports() 时(Chrome 121、Firefox 127、Safari 18.4)先检查,没有时按「只有强制类型」处理。

async function copyChart(canvas, captionHtml) {
if (!navigator.clipboard?.write || !('ClipboardItem' in window)) {
return copyText(captionHtml.replace(/<[^>]+>/g, ''));
}
const png = new Promise((resolve) => canvas.toBlob(resolve, 'image/png'));
const items = { 'image/png': png };
const htmlOk = typeof ClipboardItem.supports !== 'function' || ClipboardItem.supports('text/html');
if (htmlOk) {
items['text/html'] = new Blob([captionHtml], { type: 'text/html' });
}
try {
await navigator.clipboard.write([new ClipboardItem(items)]);
} catch (err) {
if (err.name !== 'NotAllowedError') throw err;
return copyText(captionHtml.replace(/<[^>]+>/g, ''));
}
}

直接传入 toBlob 的 Promise 而不是先 await,浏览器就能在同一手势内启动写入、稍后再填入字节;Safari 13.1 是依赖这一顺序的引擎(web.dev,Unblocking clipboard access)。

不依赖 Chromium 专有权限查询读取剪贴板图片

Section titled “不依赖 Chromium 专有权限查询读取剪贴板图片”

只有 Chromium 把 clipboard-read 当作 Permissions API 名称;navigator.permissions.query({ name: 'clipboard-read' }) 在 Firefox 与 Safari 中抛出 TypeError。跳过查询,在手势内直接调用 read(),按拒绝原因分支。

document.querySelector('#paste').addEventListener('click', async () => {
if (!navigator.clipboard?.read) {
document.querySelector('#paste-area').focus(); // 让用户按 Ctrl+V / Cmd+V
return;
}
try {
const items = await navigator.clipboard.read();
const item = items.find((i) => i.types.includes('image/png'));
if (!item) {
console.log('剪贴板上没有 PNG,可用类型:', items.flatMap((i) => i.types));
return;
}
const blob = await item.getType('image/png');
document.querySelector('#preview').src = URL.createObjectURL(blob);
} catch (err) {
if (err.name === 'NotAllowedError') {
document.querySelector('#paste-area').focus();
return;
}
throw err;
}
});

聚焦一个 contenteditable 或 textarea 并监听 paste 事件是可移植的回退:paste 事件的 clipboardData.files 在每个引擎里都能交出同一张 PNG,不需要任何权限。

规范

规范状态
Async Clipboard API(异步剪贴板)W3C 草案
Clipboard API and events: read() methodW3C
Clipboard API and events: write() methodW3C
  • 图例
  • 支持
  • 部分支持
  • 需开启标志
  • 不支持
  • 未知
浏览器 / 平台支持版本置信度来源备注
Chrome (Desktop)支持76高来源1
Chrome (Android)支持76高来源23
Edge (Desktop)支持79高来源45
Firefox (Desktop)支持127高来源678
Firefox (Android)支持127高来源9101112
Safari (macOS)支持13.1高来源—
Safari (iOS)支持13.4高来源13
Samsung Internet支持12.0高来源1415
WebView (Android)支持76高来源1617
  1. 用户必须授予 `clipboard-read` 权限。
  2. 用户必须授予 `clipboard-read` 权限。
  3. 由 browser-compat-data 镜像自 Chrome 的数据推导。
  4. 用户必须授予 `clipboard-read` 权限。
  5. 由 browser-compat-data 镜像自 Chrome 的数据推导。
  6. 此方法必须在用户手势事件的处理函数内调用。
  7. 读取剪贴板时会显示粘贴提示;若剪贴板内容来自同源,则不显示该提示。
  8. manifest 中声明了 `clipboardRead` 权限的 Web 扩展可以不经粘贴提示直接读取数据。Firefox 147 之前,没有该权限的扩展无法读取剪贴板数据。
  9. 此方法必须在用户手势事件的处理函数内调用。
  10. 读取剪贴板时会显示粘贴提示;若剪贴板内容来自同源,则不显示该提示。
  11. manifest 中声明了 `clipboardRead` 权限的 Web 扩展可以不经粘贴提示直接读取数据。Firefox 147 之前,没有该权限的扩展无法读取剪贴板数据。
  12. 由 browser-compat-data 镜像自 Firefox 的数据推导。
  13. 由 browser-compat-data 镜像自 Safari 的数据推导。
  14. 用户必须授予 `clipboard-read` 权限。
  15. 由 browser-compat-data 镜像自 Chrome Android 的数据推导。
  16. 用户必须授予 `clipboard-read` 权限。
  17. 由 browser-compat-data 镜像自 Chrome Android 的数据推导。

源数据: /compatibility/clipboard.json · 全球使用占比: 93 % (StatCounter 2026-05)

来源: 规范 · MDN · 最近核验 2026-10-03 · 置信度: 高 (由来源计算)