Puppeteer BrowserContext.setCookie 详解:在浏览器上下文中直接写入 Cookie 的完整指南
本文围绕 Puppeteer 的 BrowserContext.setCookie() 方法展开,讲清它的函数签名、CookieData 参数对象的每一个字段、底层 CDP 与 WebDriver BiDi 两套实现路径,以及在自动化测试和登录态保持等场景中可直接复制的用法。读完后,你可以独立完成"在任意浏览器上下文中预设 Cookie、验证 Cookie 写入、再将其删除"的完整闭环,并理解不同字段在 Chrome 与 Firefox 下的行为差异。
方法定位:它属于 BrowserContext 的存储隔离层
BrowserContext 代表浏览器中独立的"用户上下文",每个上下文拥有完全隔离的存储(cookies、localStorage 等)。Puppeteer 启动浏览器时至少存在一个默认上下文,也可以通过 Browser.createBrowserContext() 创建新的上下文(在 Chrome 中,所有非默认上下文都是 incognito)。Cookie 操作就是定义在这一抽象层上的:
import puppeteer from 'puppeteer';
const browser = await puppeteer.launch();
// 创建一个独立的(incognito)上下文
const context = await browser.createBrowserContext();
// 在上下文中直接预设 Cookie,无需先打开任何页面
await context.setCookie({
name: 'auth_token',
value: 'my-token-value',
domain: 'example.com',
path: '/',
});
const page = await context.newPage();
await page.goto('https://example.com/profile'); // 已携带 Cookie
await context.close();
抽象声明位于 api/BrowserContext.ts:
// packages/puppeteer-core/src/api/BrowserContext.ts
abstract class BrowserContext {
/**
* Gets all cookies in the browser context.
*/
abstract cookies(): Promise<Cookie[]>;
/**
* Sets a cookie in the browser context.
*/
abstract setCookie(...cookies: CookieData[]): Promise<void>;
}
对应文档见 BrowserContext.setCookie、BrowserContext 与 Cookies 指南。
函数签名与参数
官方签名(来自 API 文档):
class BrowserContext {
abstract setCookie(...cookies: CookieData[]): Promise<void>;
}
| 参数 | 类型 | 说明 |
|---|---|---|
cookies |
CookieData[] | 一个或多个要写入的 Cookie 参数对象,支持变长参数一次性批量写入 |
| 返回值 | Promise<void> |
写入完成时 resolve;不返回已写入的 Cookie,需用 cookies() 回读验证 |
CookieData 是"浏览器级"Cookie 写入 API 的参数类型,与页面级的 CookieParam(Page.setCookie 使用)的关键区别在于:CookieData 中 domain 是必填项,而页面级 API 允许通过 url 推导域名。这一点决定了 BrowserContext.setCookie 可以在没有任何页面打开的情况下预设 Cookie——这正是测试场景中最常用的模式。
CookieData 字段逐项说明
以下字段完整继承自 CookieData 接口文档,并与源码 common/Cookie.ts 中的定义一一对应:
| 字段 | 必填 | 类型 | 说明 |
|---|---|---|---|
name |
是 | string |
Cookie 名称 |
value |
是 | string |
Cookie 值 |
domain |
是 | string |
Cookie 所属域名 |
path |
否 | string |
Cookie 路径,未指定时由浏览器按默认规则处理(通常为 /) |
secure |
否 | boolean |
是否为 Secure Cookie(仅通过 HTTPS 发送) |
httpOnly |
否 | boolean |
是否为 HttpOnly Cookie(JS 不可读写) |
sameSite |
否 | CookieSameSite:'Strict' | 'Lax' | 'None' | 'Default' |
SameSite 属性;'Default' 表示交给浏览器采用默认策略 |
expires |
否 | number |
过期时间(UNIX 时间戳,秒);不设置则为会话 Cookie,会话 Cookie 的约定表示为 -1 |
priority |
否 | CookiePriority:'Low' | 'Medium' | 'High' |
Cookie 优先级,仅 Chrome 支持 |
sourceScheme |
否 | CookieSourceScheme:'Unset' | 'NonSecure' | 'Secure' |
原始设置方所在的 source scheme,仅 Chrome 支持 |
partitionKey |
否 | CookiePartitionKey | string |
Cookie 分区键:在 Chrome 中对应分区 Cookie 可用的顶级站点(topLevelSite),在 Firefox 中对应 BiDi PartitionKey 的 source origin |
几个容易被忽略的语义细节:
expires: -1是"会话 Cookie"的显式写法。cookies()回读时,会话 Cookie 会以expires: -1, session: true的形式出现,测试 browsercontext-cookies.test.ts 中就断言了这一点。sameSite: 'Default'是一个特殊值。在 CDP 路径上,convertSameSiteFromPuppeteerToCdp 只会把Strict/Lax/None原样传给 Chrome,Default会被映射为undefined(即"不设 SameSite"),由浏览器自行决定默认策略——测试中因此断言回读结果可能是'Default'、'Lax'或undefined,取决于浏览器。partitionKey的双形态:Chrome 下是对象{sourceOrigin, hasCrossSiteAncestor?}(hasCrossSiteAncestor也仅 Chrome 支持),Firefox 下通常传sourceOrigin字符串即可;测试用例展示了两种形态的对照写法。
底层实现:CDP 与 BiDi 两条路径
从源码结构看,BrowserContext.setCookie 是抽象方法,两套协议后端各自实现,这是理解其行为边界的关键。
CDP 路径(Chrome 默认)
CdpBrowserContext.setCookie 直接把整批 Cookie 转换为 CDP 参数后发出一次 Storage.setCookies 调用:
// packages/puppeteer-core/src/cdp/BrowserContext.ts
override async setCookie(...cookies: CookieData[]): Promise<void> {
return await this.#connection.send('Storage.setCookies', {
browserContextId: this.#id,
cookies: cookies.map(cookie => {
return {
...cookie,
partitionKey: convertCookiesPartitionKeyFromPuppeteerToCdp(
cookie.partitionKey,
),
sameSite: convertSameSiteFromPuppeteerToCdp(cookie.sameSite),
};
}),
});
}
注意其中 browserContextId 被显式传入——这意味着写入是上下文级操作,Cookie 只会落在该上下文的隔离存储中,不会污染其他 incognito 上下文或默认上下文。
WebDriver BiDi 路径(Firefox / BiDi 模式)
BidiBrowserContext.setCookie 采用逐条写入:每条 CookieData 被转换为 BiDi 的 Storage.PartialCookie,最终通过 UserContext.setCookie 发送 storage.setCookie 命令,并在 partition 参数中携带 userContext 标识,保证写入落在正确的用户上下文。值得注意的转换细节:
expires通过convertCookiesExpiryCdpToBiDi转换为 BiDi 的expiry(-1即无过期时间,仍表示会话 Cookie);sameSite经convertCookiesSameSiteCdpToBiDi映射为 BiDi 枚举;- 注释标明
sourceScheme、priority、url属于 "Chrome-specific properties",通过cdpSpecificCookiePropertiesFromPuppeteerToBidi处理——这与CookieData文档中"Supported only in Chrome"的标注一致,在 Firefox 下设置这些字段不产生语义。
与 Browser.setCookie 的关系:默认上下文快捷方式
Browser.setCookie 只是默认上下文的转发:
// packages/puppeteer-core/src/api/Browser.ts
async setCookie(...cookies: CookieData[]): Promise<void> {
return await this.defaultBrowserContext().setCookie(...cookies);
}
cookies.md 指南中的示例就是在 Browser 上调用,等价于对 browser.defaultBrowserContext() 调用 setCookie:
import puppeteer from 'puppeteer';
const browser = await puppeteer.launch();
// 为 localhost 域名一次性写入两条 Cookie
await browser.setCookie(
{
name: 'cookie1',
value: '1',
domain: 'localhost',
path: '/',
expires: -1,
httpOnly: false,
secure: false,
sourceScheme: 'NonSecure',
},
{
name: 'cookie2',
value: '2',
domain: 'localhost',
path: '/',
expires: -1,
httpOnly: false,
secure: false,
sourceScheme: 'NonSecure',
},
);
console.log(await browser.cookies()); // 打印可用 cookies
选择建议:若只想给默认上下文注入登录态等 Cookie,用 browser.setCookie 最简洁;若需要多账号隔离、并行会话或验证"上下文间 Cookie 不串扰",则应通过 createBrowserContext() 拿到独立上下文并在其上调用 setCookie。
配套方法:deleteCookie 的巧妙实现
BrowserContext 的 deleteCookie 并没有单独的底层命令,而是复用 setCookie 完成——把待删 Cookie 展开后强制设置 expires: 1(一个已过去的时间戳),让浏览器自行清除:
async deleteCookie(...cookies: Cookie[]): Promise<void> {
return await this.setCookie(
...cookies.map(cookie => {
return {
...cookie,
expires: 1,
};
}),
);
}
这意味着:
- 删除操作与写入走完全相同的 CDP/BiDi 通道,行为一致性有保障;
- 删除的前提是提供完整的 Cookie 对象(由
cookies()回读得到),匹配依据是 name + domain + path 等字段; - 更灵活的批量删除由 deleteMatchingCookies 提供,它先
cookies()回读全量,再按DeleteCookiesRequest过滤条件(name、domain、path、url、partitionKey)筛选后调用deleteCookie,实现逻辑见 api/BrowserContext.ts。
写入后验证:测试中的标准闭环
官方测试 browsercontext-cookies.test.ts 展示了"写入 → 访问 → 页面内可见"的完整验证流程,这正是实际使用中推荐的做法:
// 写入会话 Cookie
await context.setCookie({
name: 'infoCookie',
value: 'secret',
domain: 'localhost',
path: '/',
expires: -1,
httpOnly: false,
secure: false,
sourceScheme: 'NonSecure',
});
await page.goto(server.EMPTY_PAGE);
// 页面内 JS 直接可见(非 HttpOnly)
expect(
await page.evaluate(() => document.cookie),
).toEqual('infoCookie=secret');
验证时注意两点:
- 非
httpOnlyCookie 可在页面内通过document.cookie读到;httpOnly: true的 Cookie 只会随请求发送,页面 JS 读不到,此时只能用context.cookies()验证。 secure: true的 Cookie 需要通过 HTTPS 页面(或测试环境开启acceptInsecureCerts: true)才能被正常携带和回读。
典型应用场景
结合 Cookies 指南的定位——"在操作浏览器存储层面提前 get/set/delete cookies,方便在测试中存取和恢复特定 Cookie"——BrowserContext.setCookie 最典型的落地场景是:
- 登录态保持:从生产环境或上一次会话导出 Cookie(
cookies()返回的完整对象数组本身就是可序列化的 JSON),在新会话启动后通过setCookie(...savedCookies)一次性注入,跳过登录页与验证码; - 多租户/多账号隔离测试:每个
createBrowserContext()是一个独立存储域,向不同上下文分别setCookie注入不同账号的身份,互不干扰,测试结束context.close()即自动清空该账号的全部存储; - 模拟服务端 Set-Cookie:对无法直接控制的第三方站点,可预先按目标域写入 Cookie(如 A/B 实验标记、地区标记),再观察页面行为差异。
小结
BrowserContext.setCookie(...cookies: CookieData[]) 是 Puppeteer 在浏览器上下文存储层写入 Cookie 的入口:必填 name/value/domain,可选字段覆盖 path、过期、SameSite、Secure、HttpOnly 及 Chrome 专属的 priority/sourceScheme/partitionKey;CDP 实现一次发送 Storage.setCookies,BiDi 实现逐条发送 storage.setCookie;Browser.setCookie 只是默认上下文的快捷方式,deleteCookie 则是借由"过期时间置为过去"复用的同一通道。掌握字段语义(尤其是 expires: -1、sameSite: 'Default' 与分区键的双形态)与写入后的验证方法,即可在测试与自动化脚本中可靠地管理任意上下文的 Cookie 状态。
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 StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00