Puppeteer Browser.createBrowserContext() 详解:创建隔离浏览器上下文的签名、配置与源码实现
本文基于 Puppeteer 官方 API 文档 Browser.createBrowserContext() 方法条目展开,完整覆盖该方法的签名、参数 BrowserContextOptions 各配置项(代理、下载行为等)、返回值与官方示例,并结合 puppeteer-core 源码 中 CDP 与 WebDriver BiDi 两条协议链路的实际实现,帮助你掌握在自动化脚本中创建相互隔离的浏览器上下文(cookies、缓存互不共享)的完整技术能力。
方法概述
Browser.createBrowserContext 方法用于在已启动的 Browser 实例中创建一个新的 浏览器上下文(BrowserContext)。它最核心的语义是:
Creates a new browser context. This won't share cookies/cache with other browser contexts.
即新创建的上下文拥有独立的一套存储(cookies、localStorage、缓存等),与其他上下文完全隔离。这一能力对应了 Chrome 的「隐身式」多会话模型——从 BrowserContext 源码注释 可以确认:
* When a browser is launched, it has at least one default
* browser context. Others can be created
* using Browser.createBrowserContext. Each context has isolated storage
* (cookies/localStorage/etc.)
同时源码中还明确了 Chrome 下的行为约定:所有非默认上下文在 Chrome 中都相当于 incognito(隐私)模式;如果你以 --incognito 参数启动浏览器,连默认上下文也处于隐私模式(BrowserContext.ts L99-L104)。另外,若某个页面通过 window.open 打开新页面,弹窗会归属于父页面所在的浏览器上下文。
方法签名
文档给出的 TypeScript 签名如下(源自 Browser 抽象类 的抽象方法声明):
class Browser {
abstract createBrowserContext(
options?: BrowserContextOptions,
): Promise<BrowserContext>;
}
参数说明:BrowserContextOptions
| 参数 | 类型 | 说明 |
|---|---|---|
options |
BrowserContextOptions | (Optional) 可选的上下文配置项 |
BrowserContextOptions 是一个可选参数,完整定义位于 api/Browser.ts L41-L58,共包含 3 个字段:
export interface BrowserContextOptions {
/**
* Proxy server with optional port to use for all requests.
* Username and password can be set in `Page.authenticate`.
*/
proxyServer?: string;
/**
* Bypass the proxy for the given list of hosts.
*/
proxyBypassList?: string[];
/**
* Behavior definition for when downloading a file.
*
* @remarks
* If not set, the default behavior will be used.
*/
downloadBehavior?: DownloadBehavior;
}
各字段含义与使用要点:
1. proxyServer(代理服务器)
- 类型:
string,可带端口的代理服务器地址,如http://HOST:PORT; - 作用于该上下文内的所有请求,实现「每个上下文走不同代理」的多通道采集/测试场景;
- 认证凭据不在此处设置,而是通过
Page.authenticate单独配置。
Puppeteer 的测试套件 test/src/proxy.test.ts 中就有真实用法:通过 browser.createBrowserContext({proxyServer: proxyServerUrl}) 创建走代理的上下文,并用 proxyBypassList 让本地测试页绕过代理:
const context = await browser.createBrowserContext({
proxyServer: proxyServerUrl,
proxyBypassList: [new URL(emptyPageUrl).host],
});
2. proxyBypassList(代理绕过列表)
- 类型:
string[],需要绕过代理的主机列表; - 在 CDP 实现中会被
join(',')拼接后传给浏览器,见下文源码分析。
3. downloadBehavior(下载行为)
- 类型:DownloadBehavior,不设置时使用浏览器默认行为;
- 其结构定义在 common/DownloadBehavior.ts:
export type DownloadPolicy = 'deny' | 'allow' | 'allowAndName' | 'default';
export interface DownloadBehavior {
/**
* Setting this to `allowAndName` will name all files
* according to their download guids.
*/
policy: DownloadPolicy;
/**
* The default path to save downloaded files to.
* Setting this is required if behavior is set to `allow` or `allowAndName`.
*/
downloadPath?: string;
}
即策略可取 deny(拒绝)、allow(允许并保存到 downloadPath)、allowAndName(允许并以下载 GUID 命名文件)、default(默认行为);只要策略为 allow 或 allowAndName,就必须提供 downloadPath。
返回值
方法返回 Promise<BrowserContext>,即一个 BrowserContext 实例。拿到上下文后即可调用其成员方法创建页面与管理状态,BrowserContext 抽象类 上可用能力包括:
newPage(options?):在该上下文中创建新页面(支持CreatePageOptions,如background: true后台创建);pages()/targets():枚举上下文内的页面与目标;setCookie/cookies/deleteCookie/deleteMatchingCookies:上下文级 Cookie 管理(默认上下文不可用browser上的快捷方法代替时,必须直接操作上下文);setPermission/overridePermissions/clearPermissionOverrides:按 origin 覆盖权限(如地理定位);waitForTarget(predicate):等待上下文中出现匹配的目标,默认超时 30000ms;close():关闭上下文及其所有页面(默认上下文不可关闭);- 事件:
targetcreated/targetchanged/targetdestroyed(见 BrowserContextEvent)。
基本用法示例
以下示例完整继承自官方文档 puppeteer.browser.createbrowsercontext.md,并补充了生命周期收尾步骤(源码示例见 api/Browser.ts L506-L523):
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');
// 使用完毕后关闭上下文(默认上下文无法关闭,自建上下文应当显式释放)
await context.close();
await browser.close();
BrowserContext 同时实现了 AsyncDisposable,支持现代 TypeScript 的 using 语义:从 api/BrowserContext.ts L380-L389 可以看到其 [Symbol.dispose] / [Symbol.asyncDispose] 都会调用 close(),因此也可以在支持显式资源管理的运行环境中让上下文被自动释放。
源码级实现:CDP 与 BiDi 双协议链路
createBrowserContext 是抽象方法,Puppeteer 当前仓库中由 CDP(Chrome DevTools Protocol)和 WebDriver BiDi 两套实现分别落地。
CDP 实现
CDP 分支位于 cdp/Browser.ts L267-L290:
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;
}
调用链拆解:
- 向浏览器发送 CDP 命令
Target.createBrowserContext,透传proxyServer;proxyBypassList数组被join(',')拼成逗号分隔字符串(这与 CDP 协议的参数格式一致); - 浏览器返回
browserContextId,Puppeteer 据此构造CdpBrowserContext实例; - 若指定了
downloadBehavior,额外调用context.setDownloadBehavior(...)应用下载策略; - 将上下文以 id 为键注册进
#contextsMap,之后browserContexts()会以「默认上下文 + Map 中所有自建上下文」的顺序返回(L292-L294)。
对应地,关闭自建上下文时 CDP 侧会发送 Target.disposeBrowserContext(L300-L308),并从注册表中移除。
BiDi 实现
BiDi 分支位于 bidi/Browser.ts L282-L287:
override async createBrowserContext(
options: BrowserContextOptions = {},
): Promise<BidiBrowserContext> {
const userContext = await this.#browserCore.createUserContext(options);
return this.#createBrowserContext(userContext);
}
从源码结构看,BiDi 路径将「浏览器上下文」映射为协议层的 user context:底层 browserCore.createUserContext(options) 负责真正创建,随后 #createBrowserContext(userContext)(L216-L247)构造 BidiBrowserContext 包装对象,将其登记进 #browserContexts,并把该上下文的 TargetCreated / TargetChanged / TargetDestroyed 事件向上汇聚转发为 Browser 级事件——这意味着无论你监听的是 Browser 还是 BrowserContext 的事件对象,目标创建/销毁的通知都能收到。浏览器连接建立时,#initialize() 还会遍历 browserCore.userContexts 把既有上下文全部包装进来(L181-L185),因此 connect 复用已有浏览器时也能正确枚举所有上下文。
上下文枚举与默认上下文的关系
结合 Browser 抽象类 中的相关抽象方法,可以建立完整的心智模型:
| 方法 | 说明 |
|---|---|
browser.browserContexts() |
返回当前全部上下文;全新启动的浏览器只包含一个(默认上下文) |
browser.defaultBrowserContext() |
获取默认上下文,该上下文不能被关闭 |
browser.newPage() |
等价于在默认上下文中开页;跨上下文的全部页面需用 browser.pages() 聚合 |
context.newPage() |
在指定上下文中开页,页面自动继承该上下文的隔离状态 |
值得注意的实现细节:Browser.pages() 是具体实现(非抽象方法),它会 Promise.all 地遍历所有上下文再扁平化页面列表(api/Browser.ts L637-L647)——从源码结构看,这是多上下文环境下避免漏页的官方聚合方式。
实战验证:测试套件中的隔离能力
仓库测试用真实用例印证了该方法的隔离语义:
- test/src/browsercontext.test.ts 中创建了多个上下文(如 L162-L163 同时
create1/create2两个上下文),验证了跨上下文的页面、cookie、存储隔离行为; - test/src/browsercontext-cookies.test.ts 专门验证了「同一浏览器内不同上下文的 Cookie 互不可见」这一核心承诺;
- test/src/proxy.test.ts 验证了
proxyServer/proxyBypassList选项在上下文级的生效路径。
一个典型的「双账号并行」场景写法(基于上述模式组合):
const browser = await puppeteer.launch();
// 已登录用户 A 的上下文(预置 cookie)
const contextA = await browser.createBrowserContext();
await contextA.setCookie({name: 'session', value: 'token-A', domain: 'example.com'});
// 完全干净的用户 B 上下文
const contextB = await browser.createBrowserContext();
const pageA = await contextA.newPage();
const pageB = await contextB.newPage();
// pageA 携带 token-A,pageB 不共享任何 cookie/缓存
小结
browser.createBrowserContext(options?)是 Puppeteer 中创建隔离会话的入口:新上下文与其他上下文不共享 cookies 与缓存,在 Chrome 下即等效于独立的隐私会话;- 可选参数
BrowserContextOptions提供proxyServer、proxyBypassList、downloadBehavior三项上下文级配置,覆盖代理路由与下载策略; - CDP 实现底层走
Target.createBrowserContext命令并以 id 注册管理,BiDi 实现则映射为 user context 的创建与包装,两条链路在行为上保持一致; - 使用完毕应调用
context.close()释放(默认上下文不可关闭),并可通过BrowserContext的targetcreated等事件跟踪上下文内目标变化。
相关延伸阅读:Browser 类文档、BrowserContext 类文档、BrowserContextOptions 类型文档、DownloadBehavior 类型文档。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0629
MiniCPM5-2BMiniCPM5-2B 是一款面向端侧、本地部署和资源受限场景的 2B 稠密 Transformer,能够达到同尺寸开源模型 SOTA 水平。Markdown00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
HivisionIDPhotos⚡️HivisionIDPhotos: a lightweight and efficient AI ID photos tools. 一个轻量级的AI证件照制作算法。Python07
DragonOSDragonOS is an operating system developed from scratch using Rust, with Linux compatibility. It is designed for **Serverless** scenarios. 使用Rust从0自研内核,具有Linux兼容性的操作系统,面向云计算Serverless场景而设计。Rust00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00