Puppeteer读写剪贴板报Write permission denied错误解决方法
问题现象
运行代码时抛出异常:Uncaught Error Error: Evaluation failed: DOMException: Write permission denied.
复现环境
- Node.js 版本:v16.13.1
- Puppeteer 版本:puppeteer@14.4.1
已通过context.overridePermissions接口为目标站点https://google.com授予clipboard-read、clipboard-write权限,但调用navigator.clipboard.writeText执行剪贴板写入操作时仍触发权限拒绝错误,无法完成剪贴板读写。
原复现代码
'use strict'; const puppeteer = require('puppeteer'); const URL = 'https://google.com'; (async () => { const browser = await puppeteer.launch(); const context = browser.defaultBrowserContext(); context.overridePermissions(URL, ['clipboard-read', 'clipboard-write']); const page = await browser.newPage(); await page.goto(URL, { waitUntil: 'networkidle2', }); await page.evaluate(() => navigator.clipboard.writeText("Injected")); const value = await page.evaluate(() => navigator.clipboard.readText()); console.log(value); })();
故障原因
- 域名授权不匹配:访问
https://google.com时会自动重定向到带www前缀的地区谷歌域名(如https://www.google.com),仅给根域名google.com授权无法覆盖跳转后的实际访问域名,权限不生效。 - 页面状态不符合API调用要求:浏览器原生Clipboard API有强制安全限制,仅允许前台聚焦的活跃页面调用剪贴板读写方法,Puppeteer新建页面默认处于后台未激活状态,直接调用会触发权限拦截。
- 旧版无头模式兼容问题:Puppeteer@14.4.1默认使用的旧版无头Chrome对剪贴板权限的模拟存在已知缺陷,容易触发权限校验拦截。
- 异步时序问题:
navigator.clipboard下的读写方法均为异步接口,原代码未显式等待异步操作执行完成,容易出现时序异常。
修复方案
- 调整权限授权逻辑:等页面跳转完成后,取当前页面的实际源地址做权限授权,避免重定向导致的授权失效。
- 执行剪贴板操作前调用
page.bringToFront()将页面切到前台激活,满足Clipboard API的聚焦要求。 - 调整浏览器启动参数,使用可视模式启动或适配新版无头模式,规避旧版无头模式的兼容问题。
- 页面内执行剪贴板操作时显式添加
await等待异步操作完成,避免时序问题。
修复后可运行代码
'use strict'; const puppeteer = require('puppeteer'); const TARGET_URL = 'https://google.com'; (async () => { const browser = await puppeteer.launch({ // 高版本Puppeteer可替换为 headless: 'new' 启用新版无头模式 headless: false }); const context = browser.defaultBrowserContext(); const page = await browser.newPage(); await page.goto(TARGET_URL, { waitUntil: 'networkidle2', }); // 页面跳转完成后,给当前实际访问的域名源授权 await context.overridePermissions(new URL(page.url()).origin, ['clipboard-read', 'clipboard-write']); // 将页面激活到前台 await page.bringToFront(); // 显式等待剪贴板写入操作完成 await page.evaluate(async () => { await navigator.clipboard.writeText("Injected") }); const value = await page.evaluate(async () => await navigator.clipboard.readText()); console.log(value); await browser.close(); })();
内容的提问来源于stack exchange,提问作者Yehuda Alon
相关产品推荐
相关产品推荐

