首页
/ Puppeteer 浏览器上下文隔离机制详解:Browser.createBrowserContext() 方法与 BrowserContextOptions 配置全解析

Puppeteer 浏览器上下文隔离机制详解:Browser.createBrowserContext() 方法与 BrowserContextOptions 配置全解析

2026-09-04 16:30:34作者:董宙帆

在 Chrome/Firefox 自动化中,多用户会话隔离(Cookie、缓存、localStorage 互不污染)是一个高频需求。Puppeteer 通过 Browser.createBrowserContext() 方法提供浏览器级上下文(Browser Context)能力:在一个已启动的浏览器实例内创建彼此完全隔离的"沙箱",每个上下文拥有独立的存储与网络配置。读完本文,你将掌握该方法的签名、BrowserContextOptions 全部参数(代理服务器、代理绕过列表、下载行为)的含义与底层 CDP 实现原理,并能结合测试用例理解上下文的生命周期管理。

方法签名与返回值

根据官方 API 文档 Browser.createBrowserContext(),该方法定义在抽象类 Browser 上:

class Browser {
  abstract createBrowserContext(
    options?: BrowserContextOptions,
  ): Promise<BrowserContext>;
}
参数 类型 说明
options BrowserContextOptions 可选。创建上下文时的配置项

返回值: Promise<BrowserContext>,解析为一个独立的 BrowserContext 实例。

文档的核心语义有两点:

  • 创建一个新的浏览器上下文,该上下文是浏览器内一个独立的用户环境;
  • 不与其它浏览器上下文共享 Cookie / 缓存——这正是该方法的价值所在。

在抽象基类 packages/puppeteer-core/src/api/Browser.ts 中,createBrowserContext 被声明为抽象方法,由 CDP(packages/puppeteer-core/src/cdp/Browser.ts)与 BiDi(packages/puppeteer-core/src/bidi/Browser.ts)两种协议后端各自实现,对上层使用者而言调用方式完全一致。

基本用法示例

官方文档给出的最小可运行示例:

import puppeteer from 'puppeteer';

const browser = await puppeteer.launch();
// Create a new browser context.
const context = await browser.createBrowserContext();
// Create a new page in a pristine context.
const page = await context.newPage();
// Do stuff
await page.goto('https://example.com');

注意示例中的措辞 "pristine context"(干净的上下文):新创建的上下文没有任何历史 Cookie、缓存或本地存储,相当于每次都是"全新浏览器"。完整生命周期还应包含关闭上下文这一步,BrowserContext 文档中的示例补充了这一收尾操作:

// Create a new browser context
const context = await browser.createBrowserContext();
// Create a new page inside context.
const page = await context.newPage();
// ... do stuff with page ...
await page.goto('https://example.com');
// Dispose context once it's no longer needed.
await context.close();

此外,BrowserContext 的文档注释中还有一个重要行为说明:在 Chrome 中,所有非默认的上下文都是 incognito(无痕)模式;默认上下文是否无痕,取决于启动时是否传入 --incognito 参数。

BrowserContextOptions 参数详解

BrowserContextOptions 定义于 packages/puppeteer-core/src/api/Browser.ts,与 API 文档 BrowserContextOptions 完全对应,共三个可选属性:

属性 类型 说明
proxyServer string(可选) 为该上下文所有请求使用的代理服务器,可带端口。用户名与密码通过 Page.authenticate 单独设置
proxyBypassList string[](可选) 绕过代理的主机列表,列表中的主机请求不经过 proxyServer
downloadBehavior DownloadBehavior(可选) 定义该上下文下载文件时的行为;不设置时使用默认行为

完整配置示例如下:

import puppeteer from 'puppeteer';

const browser = await puppeteer.launch();

const context = await browser.createBrowserContext({
  // 该上下文的所有请求走代理(认证信息另行用 page.authenticate 设置)
  proxyServer: 'http://127.0.0.1:8080',
  // 这些主机不走代理
  proxyBypassList: ['127.0.0.1', 'localhost'],
  // 下载行为:可配置下载目录等行为
  downloadBehavior: { behavior: 'allow', downloadPath: '/tmp/downloads' },
});

const page = await context.newPage();
await page.goto('https://example.com');
await context.close();

从源码看参数如何生效

CDP 协议后端的具体实现位于 packages/puppeteer-core/src/cdp/Browser.ts

override async createBrowserContext(
  options: BrowserContextOptions = {},
): Promise<CdpBrowserContext> {
  const {proxyServer, proxyBypassList, downloadBehavior} = options;

  const {browserContextId} = await this.#connection.send(
    'Target.createBrowserContext',
    {
      proxyServer,
      proxyBypassList: proxyBypassList && proxyBypassList.join(','),
    },
  );
  const context = new CdpBrowserContext(
    this.#connection,
    this,
    browserContextId,
    this.logger,
  );
  if (downloadBehavior) {
    await context.setDownloadBehavior(downloadBehavior);
  }
  this.#contexts.set(browserContextId, context);
  return context;
}

从这段实现可以确认三个事实:

  1. 代理参数通过 CDP 命令下发proxyServerproxyBypassList 被直接透传给 CDP 的 Target.createBrowserContext 命令。注意 proxyBypassList 在 JS 侧是字符串数组,而 CDP 侧要求逗号分隔的字符串,Puppeteer 在发送前执行了 proxyBypassList.join(',') 的转换——如果手写原始 CDP 调用,需要自己完成这一步。
  2. 下载行为是二次设置downloadBehavior 并不随 Target.createBrowserContext 下发,而是在创建 CdpBrowserContext 实例之后,单独调用 context.setDownloadBehavior(downloadBehavior) 生效。
  3. 上下文以 id 注册管理:每个新上下文以浏览器返回的 browserContextId 为键存入内部的 #contexts 映射。后续当新 target(如 window.open 弹出的页面)出现时,实现会通过 targetInfo.browserContextId 反查所属上下文(见 packages/puppeteer-core/src/cdp/Browser.ts),找不到时回落到默认上下文——这解释了"子窗口继承父页面上下文"的行为。

上下文隔离性的验证(来自测试套件)

仓库测试 test/src/browsercontext.test.ts 提供了多条可直接复用的断言逻辑,可用于验证你所创建上下文的行为:

创建与销毁的计数一致性browsercontext.test.ts):

const contextCount = browser.browserContexts().length;
const context = await browser.createBrowserContext();
expect(browser.browserContexts()).toHaveLength(contextCount + 1);
expect(browser.browserContexts().indexOf(context) !== -1).toBe(true);
await context.close();
expect(browser.browserContexts()).toHaveLength(contextCount);

要点:browser.browserContexts() 会包含新创建的上下文,context.close() 后数量恢复原值。

关闭窗口级联关闭browsercontext.test.ts):调用 context.close() 时,该上下文内所有页面一并关闭(测试中 browser.pages() 从 2 变回 1)。

弹出窗口继承上下文browsercontext.test.ts):页面通过 window.open 打开的弹窗,其 target.browserContext() 与父页面属于同一个上下文。

默认上下文不可关闭browsercontext.test.ts):browser.defaultBrowserContext().close() 会抛出包含 "cannot be closed" 的错误。这与 Browser 文档中"default browser context cannot be closed" 的说明一致。

另外,Browser.cookies() / setCookie() / deleteCookie() 等便捷方法(packages/puppeteer-core/src/api/Browser.ts)实际都是 defaultBrowserContext() 上的快捷调用,因此它们只操作默认上下文的 Cookie;要管理某个自建上下文的 Cookie,必须在该上下文实例上调用对应方法。

与默认上下文的关系及生命周期建议

  • 浏览器启动后至少存在一个默认上下文,browser.newPage() 创建的页面都落在默认上下文中;createBrowserContext() 创建的页面则必须通过 context.newPage() 获得。
  • browser.pages() 会聚合所有上下文的页面(实现见 packages/puppeteer-core/src/api/Browser.ts);如需只看某个上下文内的页面,使用 context.pages()
  • 上下文支持 targetcreated / targetchanged / targetdestroyed 事件(BrowserContextEvent),可以监听上下文内页面的创建、URL 变化与销毁,测试用例 browsercontext.test.ts 演示了完整的事件序列断言。
  • 使用完毕后应调用 context.close() 释放隔离环境;上下文关闭后其内部所有 target 一并销毁。

小结

Browser.createBrowserContext() 是 Puppeteer 实现会话隔离的核心入口:一次调用即得到一个 Cookie、缓存、本地存储完全独立的环境,可选参数还能按上下文粒度指定代理服务器、代理绕过主机列表与下载行为。其 CDP 实现本质上是 Target.createBrowserContext 命令加一次 setDownloadBehavior 调用的封装,并通过 browserContextId 完成 target 与上下文的归属管理。结合 browsercontext.test.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