首页
/ Puppeteer Browser.setCookie() 完全指南:浏览器级 Cookie 注入与 CDP/BiDi 底层实现解析

Puppeteer Browser.setCookie() 完全指南:浏览器级 Cookie 注入与 CDP/BiDi 底层实现解析

2026-09-04 21:59:49作者:曹令琨Iris

本文基于 Puppeteer 官方 API 文档 Browser.setCookie() 展开,系统讲解该方法的签名、参数对象 CookieData 的每个字段、返回值与典型用法,并结合仓库源码还原它从 API 调用到 CDP(Storage.setCookies)和 WebDriver BiDi(storage.setCookie)协议的完整实现链路。读完后,你可以熟练地在浏览器层面预置 Cookie(如登录态注入),并理解 sameSitepartitionKey 等字段在两种协议下的转换细节与限制。

方法定位与签名

Browser.setCookie() 是 Puppeteer 提供的浏览器级 Cookie 写入接口,作用于浏览器的默认 BrowserContext。官方文档对它的定义非常明确:

Sets cookies in the default BrowserContext.

也就是说,它与页面级 page.setCookie()、上下文级 browserContext.setCookie() 相比,区别在于作用域:它写入的是默认浏览器上下文中的 Cookie 集合,适合在打开任何页面之前就完成会话凭据、测试用 Cookie 的预置。

方法签名(见 官方 API 文档):

class Browser {
  setCookie(...cookies: CookieData[]): Promise<void>;
}
  • 参数 cookiesCookieData 对象的可变参数列表,一次调用可以同时设置多个 Cookie;
  • 返回值:Promise<void>,没有数据返回,完成后即代表 Cookie 已提交给浏览器;
  • 备注(Remarks):它是 browser.defaultBrowserContext().setCookie() 的快捷方式。

从源码结构看,这一"快捷方式"的描述与实现完全一致。在 Browser.ts 中:

/**
 * Sets cookies in the default {@link BrowserContext}.
 *
 * @remarks
 *
 * Shortcut for
 * {@link BrowserContext.setCookie | browser.defaultBrowserContext().setCookie()}.
 */
async setCookie(...cookies: CookieData[]): Promise<void> {
  return await this.defaultBrowserContext().setCookie(...cookies);
}

实现只有一行转发:取出默认上下文,再把所有 CookieData 参数原样透传给其 setCookie()。同一文件中的 cookies()deleteCookie() 也是同样的快捷方式模式,三者构成默认上下文上的 Cookie 读写删完整闭环。

基本用法示例

import puppeteer from 'puppeteer';

const browser = await puppeteer.launch();

// 浏览器级写入:默认浏览器上下文
await browser.setCookie({
  name: 'session_id',
  value: 'abc123',
  domain: 'example.com', // 注意:domain 在 CookieData 中是必填字段
  path: '/',
  httpOnly: true,
  secure: true,
  sameSite: 'Lax',
  // 过期时间:UNIX 时间戳(秒);省略则为会话 Cookie
  expires: Math.floor(Date.now() / 1000) + 60 * 60,
});

// 可以一次写入多个 Cookie
await browser.setCookie(
  {name: 'theme', value: 'dark', domain: 'example.com'},
  {name: 'lang', value: 'zh', domain: 'example.com', path: '/app'},
);

// 用配套的 cookies() 快捷方法验证写入结果
const cookies = await browser.cookies();
console.log(cookies.map(c => `${c.name}=${c.value}`));

await browser.close();

典型应用场景包括:在 page.goto() 之前注入登录令牌以绕过登录流程、为测试环境预置功能开关(feature flag)Cookie、跨页面共享同一份凭据而不依赖某个具体页面的 URL。

CookieData 参数对象:逐字段说明

setCookie 的入参类型是 CookieData,其完整定义位于 Cookie.ts。它与页面级 API 使用的 CookieParam同文件 L93-L146)相比有一个关键差异:

差异点 CookieData(浏览器级) CookieParam(页面级)
domain 必填string 可选(url 存在时可由浏览器推导默认 domain)
url 不存在该字段 可选,用于关联 request-URI 并影响默认 domain/path

这是因为浏览器级 API 没有页面上下文可供推导,所以必须显式给出 domain——这也是调用 Browser.setCookie() 时最容易踩的坑:漏掉 domain 会直接触发 TypeScript 类型错误。

各字段含义与取值如下:

字段 类型 必填 说明
name string Cookie 名称
value string Cookie 值
domain string Cookie 域名
path string Cookie 路径
secure boolean 是否仅限安全(HTTPS)传输
httpOnly boolean 是否禁止页面脚本读取
sameSite CookieSameSite 取值 'Strict' | 'Lax' | 'None' | 'Default'
expires number 过期时间(UNIX 时间戳,秒);不设置则为会话 Cookie
priority CookiePriority 取值 'Low' | 'Medium' | 'High'仅 Chrome 支持
sourceScheme CookieSourceScheme 取值 'Unset' | 'NonSecure' | 'Secure'仅 Chrome 支持
partitionKey CookiePartitionKey | string 分区 Cookie(CHIPS)的分区键

这些类型别名的定义同样集中在 Cookie.ts

export type CookieSameSite = 'Strict' | 'Lax' | 'None' | 'Default';
export type CookiePriority = 'Low' | 'Medium' | 'High';
export type CookieSourceScheme = 'Unset' | 'NonSecure' | 'Secure';

export interface CookiePartitionKey {
  sourceOrigin: string;
  hasCrossSiteAncestor?: boolean; // 仅 Chrome 支持
}

几个使用上的要点:

  • 会话 Cookie:不传 expires 即得到会话 Cookie,浏览器关闭即失效。返回侧的 Cookie 接口(Cookie.ts L59-L85)会额外给出 session: booleanexpires(会话 Cookie 为 -1)用于回读确认。
  • partitionKey 双形态:可以传字符串(表示顶级站点)或对象 {sourceOrigin, hasCrossSiteAncestor?}。在 Chrome 中它对应 CDP 的 topLevelSite 分区键;在 Firefox 中对应 WebDriver BiDi 的 source origin。
  • Chrome 专属字段prioritysourceScheme 在文档中被明确标注 "Supported only in Chrome",跨浏览器使用时应做能力判断。
  • 读回的 Cookie 类型还包含 size(Cookie 大小)与 partitionKeyOpaque(分区键是否不透明,仅 Chrome),便于在断言时核对注入结果。

底层实现一:CDP 协议路径(Chrome / Chromium)

在 CDP 实现中,BrowserContext.setCookie() 位于 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),
      };
    }),
  });
}

调用链为:browser.setCookie()defaultBrowserContext().setCookie() → CDP 命令 Storage.setCookies,命令参数中携带 browserContextId 以限定作用域到具体浏览器上下文。这里值得注意两个字段在发送前的"净化"转换:

1. sameSite 的降级处理

转换函数 convertSameSiteFromPuppeteerToCdp 定义在 cdp/Page.ts

switch (sameSite) {
  case 'Strict':
  case 'Lax':
  case 'None':
    return sameSite;
  default:
    return undefined; // 'Default' 被映射为 undefined,即不发送
}

也就是说,'Default' 在 CDP 路径上会被显式丢弃,交由浏览器自行决定默认 SameSite 策略。

2. partitionKey 的形态归一

convertCookiesPartitionKeyFromPuppeteerToCdpcdp/Page.ts)把 Puppeteer 的双形态分区键统一转换成 CDP 协议对象:

if (typeof partitionKey === 'string') {
  return {topLevelSite: partitionKey, hasCrossSiteAncestor: false};
}
return {
  topLevelSite: partitionKey.sourceOrigin,
  hasCrossSiteAncestor: partitionKey.hasCrossSiteAncestor ?? false,
};

字符串形式等价于 hasCrossSiteAncestor: false;对象形式缺省时同样默认 false。这与 Cookie.ts 中"在 Chrome 中映射到 CDP 的 topLevelSite 分区键"的注释一致。

同一文件中回读方向也有对应处理:cookies() 方法(cdp/BrowserContext.ts L146-L161)调用 Storage.getCookies,并把 CDP 返回的 partitionKey 反向展开为 Puppeteer 的 {sourceOrigin, hasCrossSiteAncestor} 结构,保证写入/读出两侧的类型对称。

底层实现二:WebDriver BiDi 协议路径(Firefox / BiDi 模式)

当以 BiDi 协议驱动浏览器时,走的是另一条链路。BidiBrowserContext.setCookie() 位于 bidi/BrowserContext.ts

override async setCookie(...cookies: CookieData[]): Promise<void> {
  await Promise.all(
    cookies.map(async cookie => {
      const bidiCookie: Bidi.Storage.PartialCookie = {
        domain: cookie.domain,
        name: cookie.name,
        value: {type: 'string', value: cookie.value},
        ...(cookie.path !== undefined ? {path: cookie.path} : {}),
        ...(cookie.httpOnly !== undefined ? {httpOnly: cookie.httpOnly} : {}),
        ...(cookie.secure !== undefined ? {secure: cookie.secure} : {}),
        ...(cookie.sameSite !== undefined
          ? {sameSite: convertCookiesSameSiteCdpToBiDi(cookie.sameSite)}
          : {}),
        ...{expiry: convertCookiesExpiryCdpToBiDi(cookie.expires)},
        // Chrome-specific properties.
        ...cdpSpecificCookiePropertiesFromPuppeteerToBidi(
          cookie, 'sourceScheme', 'priority', 'url',
        ),
      };
      return await this.userContext.setCookie(
        bidiCookie,
        convertCookiesPartitionKeyFromPuppeteerToBiDi(cookie.partitionKey),
      );
    }),
  );
}

与 CDP 路径对比,有三个结构性差异:

  1. 逐条并发发送:BiDi 侧对每个 Cookie 单独构造 Bidi.Storage.PartialCookie 并调用 userContext.setCookie(),用 Promise.all 并发等待,而不是 CDP 那样一次性批量提交;
  2. 字段按需展开:所有可选字段都使用"未定义则不发送"的展开语法,避免把 undefined 当作有效值传给协议;
  3. Chrome 专属字段的透传sourceSchemepriority 等通过 cdpSpecificCookiePropertiesFromPuppeteerToBidi 处理,注释标明它们是 Chrome-specific properties——即 BiDi 通道下这些字段能否生效同样取决于底层浏览器能力。

UserContext.setCookie() 的终点在 bidi/core/UserContext.ts,发送的是 BiDi 命令 storage.setCookie。因此整个 BiDi 链路为:browser.setCookie() → 默认上下文 → storage.setCookie(按 user context 作用域写入)。

与页面级、上下文级 setCookie 的分工

Puppeteer 中存在三个层级的 Cookie 写入入口,从源码抽象层可以看到它们的职责划分:

  • api/BrowserContext.tsabstract setCookie(...cookies: CookieData[]): Promise<void>,真正的抽象契约,浏览器级方法就是它的一个转发;
  • api/Page.tsabstract setCookie(...cookies: CookieParam[]): Promise<void>,页面级版本使用 CookieParam,允许通过 url 字段让浏览器推导 domain/path;
  • 具体协议实现分别由 cdp/Page.tsNetwork.setCookies,按页面主 target 发送)与上文 CDP/BiDi 上下文实现承接。

实践选型建议:需要全局/跨页面生效的凭据(如站点登录态、全局配置开关),用 browser.setCookie();需要针对特定页面 URL 自动推导作用域时,用 page.setCookie();需要隔离环境(多账号、独立存储)时,先用 browser.createBrowserContext() 再对具体上下文调用 setCookie()

测试用例中的验证方式

仓库测试套件对该能力有直接覆盖,可作为断言写法的参考:

  • test/src/browsercontext-cookies.test.ts:在指定 BrowserContextcontext.setCookie({...}) 写入后,通过 context.cookies() 回读并按 name/value/domain 等字段做断言(如 L49L84 等多处写入用例);
  • test/src/cookies.test.ts:覆盖页面级写入、httpOnly/secure/sameSite 等属性回显、以及"两个页面共享浏览器上下文内 Cookie 的可见性"等场景;
  • test/src/defaultbrowsercontext.test.ts:专门验证默认浏览器上下文的行为——这正是 Browser.setCookie() 的目标作用域,包括默认上下文的不可关闭性等约束。

这些用例印证了文档的核心语义:浏览器级写入作用于默认上下文,回读接口 cookies() 会返回符合 Cookie 接口 的完整对象(含 pathexpiressizesession 等回填字段)。

关键限制与注意事项

  1. domain 必填CookieDataCookieParam 最重要的结构差异。TypeScript 项目中漏写会直接编译报错;JS 项目中则可能导致 Cookie 写入范围不符合预期。
  2. 会话 Cookie:省略 expires 即为会话 Cookie,仅在当前浏览器会话内有效;回读时 expires 表现为 -1sessiontrue
  3. sameSite: 'Default' 在 CDP 下被静默丢弃:从 convertSameSiteFromPuppeteerToCdp 的源码结构看,只有 'Strict'/'Lax'/'None' 会实际下发;需要精确控制时不要依赖 'Default'
  4. prioritysourceScheme 仅 Chrome 支持:在 Firefox 或 BiDi 通道下这两个字段的实际效果取决于底层浏览器能力(BiDi 实现中它们被归入 "Chrome-specific properties" 处理)。
  5. partitionKey 字符串简写:传字符串时等价于 {sourceOrigin: 该字符串, hasCrossSiteAncestor: false},需要表达跨站祖先关系时必须使用对象形态。
  6. 作用域是默认上下文:如果脚本此前通过 browser.createBrowserContext() 创建了隔离上下文,browser.setCookie() 不会写入那个隔离上下文,需显式调用对应上下文的 setCookie()

小结

Browser.setCookie() 是 Puppeteer 中面向自动化登录态注入、测试数据预置的高频 API:签名简单(可变参数 + Promise<void>),但参数对象 CookieData 覆盖了现代 Cookie 的全部维度——安全属性(secure/httpOnly/sameSite)、生命周期(expires)、作用域(domain/path)、以及 Chrome 专属的 priority/sourceScheme 与分区 Cookie(partitionKey)。其底层在 CDP 侧收敛为单条 Storage.setCookies 批量命令,在 BiDi 侧展开为按条并发的 storage.setCookie,两条路径都在发送前对 sameSitepartitionKey 做了协议化转换,理解这些转换细节是跨浏览器编写可靠 Cookie 注入逻辑的关键。

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

项目优选

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