首页
/ Puppeteer 浏览器管理指南:@puppeteer/browsers 的 CLI 命令、编程式 API 与自定义下载源实战

Puppeteer 浏览器管理指南:@puppeteer/browsers 的 CLI 命令、编程式 API 与自定义下载源实战

2026-09-07 11:11:52作者:尤峻淳Whitney

本指南以 Puppeteer 仓库中独立子包 @puppeteer/browsers 的 API 文档(docs/browsers-api/index.md)为主体,系统讲解如何通过 CLI 与编程式 API 统一管理 Chrome、Firefox、ChromeDriver 等浏览器与驱动的下载、安装、缓存与启动。读完你将掌握 npx @puppeteer/browsers 的全部常用命令、install / launch / computeExecutablePath 等核心函数的真实用法,以及如何为内网镜像等场景编写自定义 Provider 下载源。文中所有结论均可在 packages/browsers 包源码与测试中得到验证。

一、@puppeteer/browsers 是什么

@puppeteer/browsers 是 Puppeteer 仓库中独立发布、独立版本号的一个 Node 子包,负责"下载与启动浏览器"(其 package.json 描述即 "Download and launch browsers")。它与 Puppeteer 主库解耦,既可被 Puppeteer 内部缓存、安装浏览器时调用,也可被任何脚本、CI 或工具链单独使用。

它聚焦解决一个高频工程问题:在不同平台(Linux / macOS / Windows × x64 / ARM)上,以确定性的版本下载并管理 Chrome for Testing、ChromeDriver、Chromium、Firefox、chrome-headless-shell 等可执行文件,并把可执行文件路径以与 Puppeteer 缓存兼容的目录结构暴露给上层调用方。

系统要求(System requirements)

  • Node 版本:需满足该包 package.jsonengines 声明的版本。当前仓库中该包(version 3.2.1)要求 node >=22.12.0(见 packages/browsers/package.json)。
  • Firefox 下载的解压工具依赖:
    • Linux 构建产物为 .tar.gz / .tar.bz2,需要系统提供 xzbzip2 工具;
    • macOS 构建产物为 .dmg,需要系统提供 hdiutil
  • Chrome 下载的解压工具依赖:
    • Linux/macOS 需要 unzip
    • Windows 需要 tar.exe

若解压阶段失败,可优先排查这些系统工具是否可用。仓库测试目录中保留了 test.tar.xztest.tar.bz2test.zip 等夹具(见 packages/browsers/test/fixtures),对应解压逻辑可在 fileUtil.ts 中查看。

二、CLI:一条命令下载并管理浏览器

@puppeteer/browsers 提供开箱即用的 CLI。由于包的 bin 字段指向 lib/main-cli.js(见 packages/browsers/package.json),你可以直接用 npx 运行而无需事先安装:

# 若当前目录尚未安装该包,会临时安装并运行;若已安装则使用本地版本
npx @puppeteer/browsers --help

内置了针对每个子命令的 --help,是了解全部参数的第一手资料:

npx @puppeteer/browsers --help                 # 全部命令帮助
npx @puppeteer/browsers install --help         # install 命令帮助
npx @puppeteer/browsers launch --help          # launch 命令帮助
npx @puppeteer/browsers clear --help           # clear 命令帮助
npx @puppeteer/browsers list --help            # list 命令帮助

固定 npx 版本

npx 默认拉取注册表最新版本,可通过 @版本号 语法锁定:

# 总是使用注册表最新版
npx @puppeteer/browsers@latest --help
# 锁定某个具体版本
npx @puppeteer/browsers@2.4.1 --help
# 使用最新版并跳过 npx 的安装确认提示
npx --yes @puppeteer/browsers@latest --help

常用命令速览

clear:清空缓存目录中所有已安装浏览器(执行时会要求交互确认 yes/No,见 CLI.ts):

npx @puppeteer/browsers clear

list:列出缓存目录中所有已安装的浏览器,输出格式为 <browser>@<buildId> (<platform>) <executablePath>(对应实现见 CLI.ts):

npx @puppeteer/browsers list

install 的典型用法(browser@buildId 的定位参数解析逻辑见 CLI.ts):

# 下载与 Stable 频道对应的最新 Chrome for Testing 二进制
npx @puppeteer/browsers install chrome@stable

# 下载指定版本的 Chrome for Testing
npx @puppeteer/browsers install chrome@116.0.5793.0

# 下载指定 Milestone(大版本号) 下最新的 Chrome for Testing
npx @puppeteer/browsers install chrome@117

# 下载与 Canary 频道对应的最新 ChromeDriver
npx @puppeteer/browsers install chromedriver@canary

# 下载指定版本的 ChromeDriver
npx @puppeteer/browsers install chromedriver@116.0.5793.0

# 在 Ubuntu/Debian 上为 Chrome 安装浏览器二进制及所需系统依赖。
# 即使浏览器已装过也会尝试安装系统依赖;需要 root 权限。
npx puppeteer browsers install chrome --install-deps

install 的其它实用参数

CLI.ts 可以看到 install 还支持:

  • --platform <platform>:指定目标平台(choices 覆盖 BrowserPlatform 全部取值,例如 linuxmacmac-armwin32win64),默认自动探测当前系统。
  • --path <dir>:指定下载与安装的根目录;目录结构与 Puppeteer 使用的缓存结构兼容。默认当前工作目录。
  • --base-url <url>:指定下载镜像根地址(镜像场景下不必写自定义 Provider 也能替换下载源)。
  • --format <fmt>:安装成功后打印的结果模板,支持占位符 {{browser}}{{buildId}}{{path}}{{platform}},默认 {{browser}}@{{buildId}} {{path}}(实际替换逻辑见 CLI.ts)。
  • --install-deps:是否尝试通过 apt-get 安装系统依赖,仅 Linux 上受支持且需要 root 权限(实现细节见 install.ts)。

launch 命令则用于直接启动已缓存或系统自带的浏览器:

# 从缓存启动指定版本 Chrome
npx @puppeteer/browsers launch chrome@115.0.5790.170
# 启动后传入自定义参数(用 -- 分隔)
npx @puppeteer/browsers launch chrome@115.0.5790.170 -- --version
# 以 detached 模式启动,分离子进程
npx @puppeteer/browsers launch chrome@115.0.5790.170 --detached
# --system:放弃缓存,改在系统安装位置中查找 Canary 版 Chrome
npx @puppeteer/browsers launch chrome@canary --system
# --dumpio:将浏览器 stdout/stderr 转发到当前终端
npx @puppeteer/browsers launch firefox@112.0a1 --dumpio

Known limitations

文档明确列出一个已知限制:launch 启动"系统浏览器"的能力只适用于 Chrome/Chromium。对其它浏览器(如 Firefox),需要先通过该缓存结构下载安装后再启动。

三、代理(Proxies)

库与 CLI 均会读取并遵守 HTTP_PROXYHTTPS_PROXYNO_PROXY 三个环境变量,但它们要真正生效,还需要额外安装 proxy-agent 依赖包(在 package.json 中被声明为可选 peerDependency):

npm install proxy-agent

装好后在既有代理环境中设置对应环境变量即可,无需修改任何代码。

四、调试:NODE_DEBUG 分级日志

要观察下载进度、安装步骤与启动参数等内部细节,使用 Node 内置的 NODE_DEBUG 环境变量启用 @puppeteer/browsers 的分级日志:

env NODE_DEBUG="puppeteer:browsers:*" npx @puppeteer/browsers install chrome@stable

可用的调试频道(与 debug.ts 中定义的 DEBUG_PREFIXES 对应):

  • puppeteer:browsers:cache:缓存目录读写等缓存操作日志;
  • puppeteer:browsers:fileUtil:解压及其它文件工具日志;
  • puppeteer:browsers:install:下载与安装进度日志(含 Downloading <browser> <buildId> ... 之类的进度条信息与耗时统计,见 install.ts);
  • puppeteer:browsers:launcher:浏览器启动参数与进程状态日志(如 Launching <path> <args>Launched <pid>,见 launch.ts)。

需要更细粒度时可只开启单个频道,例如 NODE_DEBUG="puppeteer:browsers:launcher",减少无关噪音。

五、自定义 Provider:接入内网镜像等替代下载源

对于企业内网镜像、私有仓库或定制浏览器构建产物,@puppeteer/browsers 提供了 Provider(下载源提供者) 抽象。底层接口定义于 provider.ts,包含三个方法:

  • supports(options):判断该 Provider 是否支持某浏览器 + 平台组合;
  • getDownloadUrl(options):返回下载地址;若无法解析版本可返回 null,让调用方继续尝试下一个 Provider;
  • getExecutablePath(options):返回解压后相对安装目录的可执行文件路径;
  • getName():Provider 名称,用于日志与报错。

文档给出的 SimpleMirrorProvider 完整示例即实现上述接口,把下载 URL 拼到自定义镜像域名上,并按平台返回对应归档文件名与可执行文件相对路径:

import {
  BrowserProvider,
  DownloadOptions,
  Browser,
  BrowserPlatform,
} from '@puppeteer/browsers';

class SimpleMirrorProvider implements BrowserProvider {
  constructor(private mirrorUrl: string) {}

  supports(options: DownloadOptions): boolean {
    return options.browser === Browser.CHROME;
  }

  getDownloadUrl(options: DownloadOptions): URL | null {
    const {buildId, platform} = options;
    const filenameMap = {
      [BrowserPlatform.LINUX]: 'chrome-linux64.zip',
      [BrowserPlatform.MAC]: 'chrome-mac-x64.zip',
      [BrowserPlatform.MAC_ARM]: 'chrome-mac-arm64.zip',
      [BrowserPlatform.WIN32]: 'chrome-win32.zip',
      [BrowserPlatform.WIN64]: 'chrome-win64.zip',
    };
    const filename = filenameMap[platform];
    if (!filename) return null;
    return new URL(`${this.mirrorUrl}/chrome/${buildId}/${filename}`);
  }

  getExecutablePath(options: DownloadOptions): string {
    const {platform} = options;
    if (
      platform === BrowserPlatform.MAC ||
      platform === BrowserPlatform.MAC_ARM
    ) {
      return 'chrome-mac/Chromium.app/Contents/MacOS/Chromium';
    } else if (platform === BrowserPlatform.LINUX) {
      return 'chrome-linux64/chrome';
    } else if (platform.includes('win')) {
      return 'chrome-win64/chrome.exe';
    }
    throw new Error(`Unsupported platform: ${platform}`);
  }
}

随后把它传入 install API 的 providers 数组即可:

import {install} from '@puppeteer/browsers';

const customProvider = new SimpleMirrorProvider('https://internal.company.com');

await install({
  browser: Browser.CHROME,
  buildId: '120.0.6099.109',
  platform: BrowserPlatform.LINUX,
  cacheDir: '/tmp/puppeteer-cache',
  providers: [customProvider],
});

Provider 链与回退机制

多个 Provider 可以链式组合,按数组顺序依次尝试,直到某一个成功为止DefaultProvider(默认下载源)会被自动追加为最终兜底。真实的尝试、失败收集与回退逻辑见 install.ts:代码会依次调用每个 Provider 的 supportsgetDownloadUrl,拿到有效 URL 后执行下载与解压;全部失败时抛出汇总了每个 Provider 报错信息的 All providers failed for ... 异常。DefaultProvider 的实现(对所有浏览器都返回 supports = true,并根据 baseUrl 拼装官方下载地址)见 DefaultProvider.ts

⚠️ 重要提醒:文档与源码都反复强调——自定义 Provider 不受 Puppeteer 官方支持。使用方必须自行承担:二进制与 Puppeteer 期望的结构是否兼容、浏览器能否正常启动与工作、上游源变化后的持续适配,以及多平台混用不同来源时的版本一致性。Puppeteer 仅对默认下载的 Chrome for Testing 二进制做测试与兼容性保障。

六、编程式 API:在代码中管理浏览器生命周期

除了 CLI,该包导出一整套编程式 API(入口聚合见 packages/browsers/src/main.ts)。API 文档建议直接阅读包的 test 目录获取可直接运行的用法示例,对应测试代码位于 packages/browsers/test/src,按浏览器分目录组织了 installlaunch、CLI、缓存与卸载测试(例如 chrome/install.test.tschrome/launch.test.tslist.test.tsinstallWithProviders.test.ts)。

安装:install / canDownload / uninstall / getInstalledBrowsers

import {
  install,
  canDownload,
  uninstall,
  getInstalledBrowsers,
  Browser,
} from '@puppeteer/browsers';

// 下载并解压(返回 InstalledBrowser 实例)
const browser = await install({
  browser: Browser.CHROME,
  buildId: '116.0.5793.0',
  cacheDir: '/tmp/puppeteer-cache',
  // platform: 可选,默认自动探测
  // downloadProgressCallback: 'default' 会显示进度条,也可传自定义回调
});

// 预先探测:给定版本当前是否可下载(会向服务端发起 HEAD 请求)
const ok = await canDownload({
  browser: Browser.CHROME,
  buildId: '116.0.5793.0',
  cacheDir: '/tmp/puppeteer-cache',
});

// 卸载指定构建
await uninstall({
  browser: Browser.CHROME,
  buildId: '116.0.5793.0',
  cacheDir: '/tmp/puppeteer-cache',
});

// 列出缓存中的全部浏览器
const installed = await getInstalledBrowsers({cacheDir: '/tmp/puppeteer-cache'});

install 的完整选项定义于 install.ts,值得留意的参数包括:

  • unpack: false 时可只下载归档文件而不解压,函数返回归档的绝对路径(对应 API 文档中的第二个重载);
  • baseUrl:指定下载源根地址;
  • expectedHash:期望的 SHA-256 校验和,提供后下载文件不匹配将导致安装失败;
  • installDeps:是否安装系统依赖(仅 Chrome + Debian/Ubuntu + root);
  • buildIdAlias:为实际 buildId 维护一个本地别名(如 canary),便于 launch 时引用。

安装完成后,缓存目录内部结构为 rootDir/<browser>/<platform>-<buildId>/...,其中 .metadata 文件记录别名与可执行文件路径映射(见 Cache.ts 中的目录结构注释与读写逻辑)。

启动:launch 与进程管理

import {launch} from '@puppeteer/browsers';

const proc = launch({
  executablePath: '/tmp/puppeteer-cache/chrome/linux-116.0.5793.0/chrome',
  // pipe/dumpio/args/env/detached/handleSIGINT 等均为可选
  detached: true,
});

// 等待浏览器输出中匹配指定正则的行,典型用于捕获
// CDP / WebDriver BiDi 的 ws:// 端点地址
const wsEndpoint = await proc.waitForLineOutput(
  /^DevTools listening on (ws:\/\/.*)$/,
  30000,
);

// 读取浏览器最近的 stdout/stderr 日志
console.log(proc.getRecentLogs());

// 关闭或强杀进程
await proc.close();

Process 类(launch.ts)在构造时即通过 child_process.spawn 拉起浏览器进程,并封装了日志行缓冲(上限 1000 行)、waitForLineOutput 等待匹配、getRecentLogskill(Linux 下按进程组 SIGKILL、Windows 下走 taskkill /pid <pid> /T /F)与 close 等能力。与之配套的两个正则常量供上层解析自动化端点:

  • CDP_WEBSOCKET_ENDPOINT_REGEX:匹配 DevTools listening on (ws://...)
  • WEBDRIVER_BIDI_WEBSOCKET_ENDPOINT_REGEX:匹配 WebDriver BiDi listening on (ws://...)

进程对象默认处理父进程的 SIGINT(触发 kill 并 exit(130))、SIGTERM/SIGHUP(触发优雅 close),确保父进程退出时不会遗留孤儿浏览器进程。

路径计算:computeExecutablePath 与 computeSystemExecutablePath

computeExecutablePath 根据缓存根目录、浏览器、平台与 buildId 计算可执行文件绝对路径;当 cacheDirnull 时返回相对解压目录的相对路径(如 ./chrome-linux64/chrome)。可执行文件路径若存在于 .metadata(自定义 Provider 场景)则优先读取,否则按内置的 executablePathByBrowser 各浏览器目录规则计算(见 Cache.ts)。

computeSystemExecutablePath 则根据发布频道在系统已知安装位置查找 Chrome,找不到时抛出包含候选路径列表的错误;第二个参数 validatePathfalse 时可跳过存在性校验、直接返回首个候选路径(见 launch.ts)。

版本解析与其它工具函数

CLI 之所以能接受 stable/canary/117 等别名或里程碑号,是因为安装前先经过 resolveBuildId(browser, platform, tag) 解析为精确 buildId。以 chrome@117 为例,它会解析为 117 里程碑下最新可用的完整版本号后再下载(CLI 中的调用链见 CLI.ts)。API 文档中列出的其它重要导出还有:

  • BrowserBrowserPlatformBrowserTagChromeReleaseChannel 枚举:分别表示受支持的浏览器、平台-架构组合、发布渠道标签与 Chrome 发布频道(API 页面分别为 browsers.browser.mdbrowsers.browserplatform.mdbrowsers.browsertag.mdbrowsers.chromereleasechannel.md);
  • detectBrowserPlatform():自动探测当前系统对应的下载平台标识;
  • getDownloadUrl(browser, platform, buildId, baseUrl?):直接返回某浏览器某版本在某平台下的官方归档下载 URL;
  • getVersionComparator(browser):获取按版本语义排序的比较器,用于对版本列表排序;
  • resolveDefaultUserDataDir(browser, platform, channel):返回指定频道预期的默认用户数据目录(不检查目录是否存在);
  • createProfilebuildArchiveFilename:配置概要创建与标准归档文件名工具;
  • TimeoutError:等待超时时抛出的专用错误类型。

完整 API 分类索引可在 docs/browsers-api/index.md 的 Classes / Enumerations / Functions / Interfaces / Variables 五张表中逐项查阅,每项都链接到独立的 API 说明页(如 installlaunchBrowserProvider 等)。

七、总结与推荐实践

综合文档与源码,给出几条可直接落地的使用建议:

  1. CI 中固定版本:用 npx @puppeteer/browsers@<版本> 锁定工具版本,配合 chrome@<buildId>(建议用精确 buildId 保证可复现性),避免"今天能装、明天装不上"的漂移问题。
  2. 共享缓存目录:通过 --path(CLI)或 cacheDir(API)让多个任务共享同一缓存根目录,其结构与 Puppeteer 主库缓存兼容,可避免重复下载。
  3. 内网/镜像环境:优先尝试 --base-url 指向公司镜像;若镜像目录结构特殊,再实现 BrowserProvider 并链入 providers 数组,同时做好多 Provider 回退与二进制兼容性自测。
  4. 排障先开日志:安装失败先设 NODE_DEBUG="puppeteer:browsers:install"(或 puppeteer:browsers:*)定位下载/解压环节,再检查对应平台的系统工具(unzip/xz/bzip2/hdiutil/tar.exe)是否齐全。
  5. 进程清理交给 Process:在代码中以编程方式启动浏览器后,始终通过 Process.close()/kill() 收尾,其信号处理逻辑(Windows taskkill、Linux 进程组 SIGKILL)能最大程度避免残留进程。
登录后查看全文
热门项目推荐
相关项目推荐