首页
/ Puppeteer Browser.installExtension() 完整指南:在自动化浏览器中加载、使用与管理扩展

Puppeteer Browser.installExtension() 完整指南:在自动化浏览器中加载、使用与管理扩展

2026-09-04 18:49:39作者:殷蕙予

本文围绕 Puppeteer 的 Browser.installExtension() 方法展开,介绍该 API 的完整签名、参数与返回值,并深入其 CDP 与 WebDriver BiDi 两种协议下的真实源码实现,讲清 enabledInIncognito 选项的生效逻辑、enableExtensions 启动选项与该方法的关系,以及返回的扩展 ID 在 uninstallExtension 等后续操作中的用法。读完本文,你可以在 Node.js 脚本中可靠地加载未打包的 Chrome 扩展、控制其在隐身模式下的可用性,并掌握扩展全生命周期的编程控制能力。

1. API 定位与签名

Browser.installExtension()Browser 类上的抽象方法,用于将一个本地目录形式的 Chrome 扩展(即“未打包扩展”,unpacked extension)安装到当前受控浏览器实例中,并返回该扩展在浏览器内部的 ID。官方 API 文档见 Browser.installExtension

该方法在抽象基类 Browser.ts 中的声明如下:

/**
 * Installs an extension and returns the ID.
 */
abstract installExtension(
  path: string,
  options?: ExtensionInstallOptions,
): Promise<string>;

对应公开文档的完整签名为:

class Browser {
  abstract installExtension(
    path: string,
    options?: ExtensionInstallOptions,
  ): Promise<string>;
}

参数

参数 类型 说明
path string 扩展目录路径(扩展必须包含 manifest.json 的本地文件夹)
options ExtensionInstallOptions (可选)安装选项

返回值

Promise<string> —— 解析为安装成功后的扩展 ID(Chrome 扩展内部标识,通常为 32 位小写字母串)。这个 ID 是后续卸载、定位扩展后台页/Service Worker 的关键凭据。

2. ExtensionInstallOptions:唯一的安装选项

ExtensionInstallOptions 接口目前只包含一个属性(详见 ExtensionInstallOptions):

属性 类型 说明 默认值
enabledInIncognito boolean 是否在 Chrome 的隐身(Incognito / OTR)配置文件中启用该扩展 false

从源码结构看,该选项并非空壳:在 CDP 实现中它会被直接映射为 CDP Extensions.loadUnpacked 命令的 enableInIncognito 字段,且缺省值 false 是在客户端侧通过空值合并运算符补全的(见下文第 3 节)。也就是说,若不显式传入 { enabledInIncognito: true },扩展将只在常规配置文件生效,在隐身窗口中不可用。

3. 源码解析:CDP 与 BiDi 两条实现路径

Puppeteer 同时支持 CDP 与 WebDriver BiDi 两套协议,installExtension() 在两条路径下有各自独立的实现,但对外行为一致:都是“传路径、得 ID”。

3.1 CDP 实现:Extensions.loadUnpacked

CDP 版本位于 cdp/Browser.ts

override async installExtension(
  path: string,
  options?: ExtensionInstallOptions,
): Promise<string> {
  const {id} = await this.#connection.send('Extensions.loadUnpacked', {
    path,
    enableInIncognito: options?.enabledInIncognito ?? false,
  });
  this.#extensions.delete(id);
  return id;
}

可以从中读出三个实现细节:

  1. 底层命令:安装动作由 CDP Extensions.loadUnpacked 完成,pathenableInIncognito 原样下发;
  2. 隐身选项的默认值options?.enabledInIncognito ?? false 表明 enabledInIncognito 缺省为 false,与文档“Default”列一致;
  3. 扩展簿记CdpBrowser 内部维护了一个 #extensions 集合用于跟踪已安装扩展,安装与卸载操作均会对其做 delete(id) 清理(从源码结构看,这是浏览器生命周期内扩展状态管理的一部分)。

与之配套的卸载方法 uninstallExtension 同样位于该文件 cdp/Browser.ts:它发送 Extensions.uninstall,并针对 Service Worker 目标缺失 Target.targetDestroyed 事件导致的不稳定问题,手动向连接补发 targetDestroyed 事件,随后从簿记集合中移除该 ID。文档见 Browser.uninstallExtension

3.2 WebDriver BiDi 实现:webExtension.install

BiDi 路径由 bidi/Browser.ts 转发给核心类 bidi/core/Browser.ts

async installExtension(path: string): Promise<string> {
  const {
    result: {extension},
  } = await this.session.send('webExtension.install', {
    extensionData: {type: 'path', path},
  });
  return extension;
}

实现要点:

  • 通过 BiDi 会话发送 webExtension.install,扩展数据以 extensionData: {type: 'path', path} 形式传递,即 BiDi 的“按路径安装”模式;
  • 返回值为 result.extension,即扩展 ID,与 CDP 路径语义一致,上层代码无需感知协议差异;
  • 注意 BiDi 侧的签名为 installExtension(path: string)未暴露 options 参数bidi/Browser.ts)。因此在 BiDi 协议下,enabledInIncognito 选项不会经由该重载传递;而默认走 BiDi 的浏览器(如 Firefox,见 BrowserLauncher.ts 中 “Default to 'webDriverBiDi' for Firefox” 的默认协议选择)使用时应了解这一差异。

4. 与启动选项的配合:enableExtensions

除了“先启动浏览器、再手动调用 installExtension()”,Puppeteer 提供了在启动阶段批量安装扩展的捷径:puppeteer.launch()enableExtensions 数组选项。其内部正是逐个调用本文讨论的方法完成安装,见 BrowserLauncher.ts

if (Array.isArray(enableExtensions)) {
  await Promise.all([
    enableExtensions.map(path => {
      return browser.installExtension(path, {
        enabledInIncognito: extensionsEnabledInIncognito.includes(path),
      });
    }),
  ]);
}

这段代码揭示了两点:

  • enableExtensionsstring[])中的每个目录都会在浏览器建立连接后自动执行 browser.installExtension(path, ...),等价于手动循环调用;
  • 另一个启动选项 extensionsEnabledInIncognito(字符串数组)决定了哪些扩展传入 enabledInIncognito: true——只有当扩展路径出现在该数组中时,enabledInIncognito 才为 true。这与第 2 节的选项语义在启动路径上得到了一致落点。

5. 实战示例

5.1 手动安装并取回扩展 ID

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch({headless: true});

  // 安装本地扩展目录,并在隐身配置中启用
  const extensionId = await browser.installExtension('/path/to/my-extension', {
    enabledInIncognito: true,
  });
  console.log('installed extension id:', extensionId);

  // ...在此使用扩展能力(内容脚本、后台页等)...

  // 用返回的 ID 卸载扩展
  await browser.uninstallExtension(extensionId);

  await browser.close();
})();

返回值类型为 Promise<string>extensionId 即 Chrome 为该扩展分配的内部 ID,可直接传给 browser.uninstallExtension(id) 完成对称的卸载(文档见 Browser.uninstallExtension)。

5.2 通过启动选项批量安装

const browser = await puppeteer.launch({
  headless: true,
  // 数组形式:逐个目录调用 installExtension 完成安装
  enableExtensions: ['/path/to/ext-a', '/path/to/ext-b'],
  // 仅让 ext-b 在隐身配置中生效(对应 enabledInIncognito: true)
  extensionsEnabledInIncognito: ['/path/to/ext-b'],
});

两种写法功能等价:enableExtensions 方式适合“浏览器一启动扩展就要就位”的场景(如扩展需尽早注入后台 Service Worker),手动方式则适合需要按运行结果动态决定装不装、何时卸的场景。

5.3 结合扩展对象查看页面与 Worker

安装完成后,可通过 browser.extensions() 获取 Extension 对象集合,进一步访问扩展的后台页(extension.pages())、Service Worker(extension.workers())并触发浏览器操作(extension.triggerAction()),用于在测试中断言扩展行为。相关 API 文档见 Extension.pagesExtension.workersExtension.triggerAction

6. 协议差异小结与使用注意

结合上述源码证据,可以归纳出使用该 API 时的边界:

维度 CDP 实现 BiDi 实现
底层命令 Extensions.loadUnpackedcdp/Browser.ts webExtension.installextensionData: {type: 'path'}bidi/core/Browser.ts
options 参数 支持,enabledInIncognito 缺省 false 公开重载仅接收 path,不暴露选项
返回值 扩展 ID(string 扩展 ID(result.extension

补充说明:BiDi 侧 installPWAlaunchPWA 等 PWA 能力在当前实现中抛出 UnsupportedOperation(见 bidi/Browser.ts),但这不影响扩展安装/卸载能力在 BiDi 下可用;installExtensionuninstallExtension 在两条协议下均有完整实现。

最后提醒两点实践约束:

  1. path 必须是本地可直接读取的扩展目录(含 manifest.json),CDP 侧由浏览器端加载“未打包”扩展,远程/压缩形态需自行先解压为目录;
  2. 安装与卸载是成对操作:installExtension 返回的 ID 应妥善保存,测试结束前调用 uninstallExtension(id),避免扩展残留影响后续运行——尤其因为 CDP 卸载路径中还存在针对 Service Worker 目标清理的补偿逻辑(cdp/Browser.ts),规范收尾可以保证环境干净。

参考文件索引

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
528
588
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
906
1.82 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
docsdocs
暂无描述
Markdown
891
5.78 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.53 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.34 K
1.45 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
987
504
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384