Puppeteer 25.9:用一套 API 同时控制 Chrome 和 Firefox 的自动化边界
适用于 Chrome 和 Firefox 的 JavaScript API
秒懂
- 它是什么?
- Puppeteer 是 JavaScript 生态中最常用的浏览器自动化库,本文基于 25.9.0 版本,拆解它的双协议架构、安装陷阱和适用边界。
- 适合谁用?
- Puppeteer 适合需要精确控制 Chromium 系浏览器、且能接受安装脚本被包管理器拦截后手动补下载的团队。不适合只跑 Firefox 且不想依赖 Chrome 下载的跨浏览器测试场景,这类需求应优先考虑纯 WebDriver BiDi 实现。
- 能商用吗?
- 可以。Apache-2.0 是宽松许可证:你可以使用、修改并销售基于它的软件,只需保留版权和许可证声明。
- 还在维护吗?
- 在维护。仓库在最近一天内有新的提交。
- 用什么语言写的?
- 主要是 TypeScript(依据 GitHub 的语言统计)。
以上回答依据项目的 GitHub 数据(最近同步于 2026年9月15日)和我们的分析,不构成法律意见。
开源项目深度解析
它解决的不是「打开浏览器」的问题
很多自动化工具能启动浏览器,但 Puppeteer 解决的是另一件事:给 JavaScript 开发者一个高层次的 API,把浏览器内部那些底层协议细节藏起来。你不需要手写 WebSocket 帧,不需要理解 DevTools Protocol 的每个方法名,只要调用 `browser.newPage()` 和 `page.goto()` 就行。它的目标用户是写爬虫、做端到端测试、或者需要程序化生成 PDF 的前端工程师。值得注意的是,它默认跑在 headless 模式,也就是没有可见界面,这跟 Selenium 时代默认弹出窗口的习惯完全不同。如果你只是偶尔手动操作浏览器,这个库对你来说过重了。
双协议架构:DevTools 为主,WebDriver BiDi 为辅
Puppeteer 25.9 的控制层不是单一协议。对 Chrome,它走 DevTools Protocol,这是 Chromium 自家的调试协议,粒度细,支持 `page.locator('::-p-aria(Search)')` 这类基于可访问性树的定位。对 Firefox,它走 WebDriver BiDi,这是一个 W3C 标准的双向协议,设计上更接近 WebDriver 传统,但支持事件推送。README 明确说这是「over the DevTools Protocol or WebDriver BiDi」,意味着两套协议在 API 层被统一了。但统一不等于对等,Firefox 的支持历来比 Chrome 滞后,某些 API 可能只在 Chromium 上完整可用。这个双轨设计是务实的选择,但也让「一次编写,处处运行」打了折扣。
安装陷阱:install script 被默认拦截
安装 Puppeteer 不是简单 `npm i puppeteer` 就完事。现代包管理器,包括 npm、pnpm、Yarn、Bun 和 Deno,出于安全考虑默认阻止依赖的安装脚本执行。如果脚本被拦截,Puppeteer 不会在安装时下载配套的 Chrome,你会在运行时遇到浏览器找不到的错误。README 给出了两条出路:一是安装后手动执行 `npx puppeteer browsers install` 补下载;二是在 `package.json` 里给 npm 添加 `"allowScripts": ["puppeteer"]` 这样的配置。这个设计反映了供应链安全的大趋势,但也意味着 CI 流水线里必须显式处理这一步,否则构建会静默失败。
puppeteer 与 puppeteer-core 的分工
仓库里有两个 npm 包,`puppeteer` 和 `puppeteer-core`,它们共享同一份代码,但定位不同。`puppeteer` 安装时会自动下载兼容版本的 Chrome,适合大多数测试和脚本场景,开箱即用。`puppeteer-core` 不下载任何浏览器,只提供库本身,你必须自己管理浏览器二进制。这个区分很有价值:如果你在 CI 里已经有缓存的 Chrome,或者你想用系统自带的浏览器,选 `puppeteer-core` 能省掉每次安装时的下载流量。但代价是版本匹配的责任落到你头上,Chrome 版本和 Puppeteer 版本不兼容时,API 行为可能偏离预期。README 对两者的介绍很简短,实际使用中这个选择直接影响部署复杂度。
从示例看 API 风格:locator 优先
README 给的示例代码展示了当前推荐的用法。启动浏览器后,`page.goto('https://developer.chrome.com/')` 导航,`page.setViewport({width: 1080, height: 1024})` 设置视口,然后用 `page.keyboard.press('/')` 打开搜索菜单,最后用 `page.locator('::-p-aria(Search)').fill('automate beyond recorder')` 定位输入框。注意最后一行,它用的是 `::-p-aria(Search)` 这种伪元素选择器,基于 ARIA 标签而非 CSS 类名。这意味着 Puppeteer 在推动更语义化的定位方式,减少对页面结构变化的脆弱依赖。但这也要求目标页面有良好的 ARIA 标注,否则选择器会失效。示例里没有展示等待元素出现的方法,实际复杂页面里 `waitForSelector` 之类的调用是避不开的。
MCP 和 WebMCP:自动化边界的延伸
Puppeteer 的生态不止于库本身。README 单独提了一个 `chrome-devtools-mcp` 项目,它是一个基于 Puppeteer 的 MCP(Model Context Protocol)服务器,用于浏览器自动化和调试。这显然是为 AI 代理操作浏览器准备的接口。同时 Puppeteer 还支持实验性的 WebMCP API。这部分信息在 README 里只有一两行,没有详细文档。从仓库布局看,MCP 支持是独立项目,不是 Puppeteer 核心的一部分。如果你打算让大模型直接控制浏览器,这个方向值得关注,但它属于实验性质,稳定性和文档完整度都未知,生产环境采用前需要额外验证。
真实局限:Firefox 不是一等公民
Puppeteer 的 README 说支持 Chrome 和 Firefox,但细看会发现 Chrome 是主路径。DevTools Protocol 是 Chromium 原生的,WebDriver BiDi 是后来为跨浏览器加的。这意味着 Firefox 用户能用的 API 子集可能更小,某些高级功能如性能追踪、内存分析可能只在 Chrome 上可用。另一个局限是安装流程的脆弱性:如果公司网络屏蔽了 Chrome 下载源,`npm i puppeteer` 会失败,而 `puppeteer-core` 又要求你自备浏览器。对于只想跑 Firefox 的团队,Puppeteer 可能不是最优解,因为 WebDriver BiDi 已经有独立的 Node.js 实现(比如 `webdriverio`),它们不依赖 Chromium 下载。Puppeteer 的优势在于 API 的简洁和 Chromium 的深度集成,跨浏览器只是附带能力。
维护成本和许可证
仓库最后推送是 2026 年 8 月 25 日,发布 v25.9.0,说明维护活跃,版本迭代频繁。License 是 Apache-2.0,对商业使用友好,没有传染性条款,但这不是法律建议,具体用法要咨询你的法务。维护成本主要体现在浏览器版本跟随上:Puppeteer 每个大版本都会绑定一个 Chrome 版本,升级 Puppeteer 意味着要重新下载或重新匹配浏览器。如果你用 `puppeteer-core`,还得自己跟踪 Chrome 的发布周期。另外,install script 的拦截问题意味着每个新开发机器或 CI 节点都要额外执行 `npx puppeteer browsers install`,这个步骤容易被人遗忘。相比 Selenium 那种通过 WebDriver 驱动系统浏览器的模式,Puppeteer 的浏览器管理更集中,但也就更依赖下载流程的顺畅。
编辑结论
Puppeteer 适合需要精确控制 Chromium 系浏览器、且能接受安装脚本被包管理器拦截后手动补下载的团队。不适合只跑 Firefox 且不想依赖 Chrome 下载的跨浏览器测试场景,这类需求应优先考虑纯 WebDriver BiDi 实现。采用前先验证三件事:你的 npm 或 pnpm 是否默认拦截 install scripts,若是则必须配置 allowScripts 或每次部署后运行 npx puppeteer browsers install;确认目标环境能访问 Chrome 下载源;检查 `puppeteer-core` 的版本与自带 `puppeteer` 的版本是否同步,避免 API 差异。25.9.0 的发布节奏表明项目维护活跃,但协议支持范围仍以 Chromium 为第一优先。
社区笔记