身份

浏览器 Cookie 管理:多身份工作流指南

如何管理 Cookie 以实现会话持久化、跨会话连续性以及按身份隔离的自动化浏览器工作流。

文档中心

想直接看维护中的产品文档?

这篇文章对应的主题已经有文档中心页面。需要规范流程、当前参数和长期参考时,优先看 docs。

简介

Cookie 是 Web 浏览器维护状态的基石。它们在页面加载和访问之间承载会话令牌、用户偏好、同意记录和身份验证凭据。在构建用于隐私研究、测试或多账户管理的浏览器配置文件时,控制 Cookie 层与控制指纹层同样重要。一个指纹一致但 Cookie 为空的浏览器,每次看起来都像是全新安装,这不符合真实浏览器的行为特征。

BotBrowser 提供 --bot-cookies 标志(PRO 层级),可在启动时预加载 Cookie。这意味着 Cookie 在第一次导航发生之前、任何 JavaScript 执行之前、任何追踪脚本检查浏览器状态之前就已经存在。结合指纹配置文件和其他身份信号,Cookie 管理完善了真实、持久浏览器身份的完整画面。

网站和追踪系统不会孤立地评估 Cookie。它们会观察 Cookie 与其他浏览器信号之间的关系。一个呈现返回用户指纹但不携带任何 Cookie 的浏览器会引发疑问。同样,一个携带会话 Cookie 但指纹完全全新的浏览器看起来也不一致。

对于研究追踪系统如何关联浏览器信号的隐私研究人员来说,控制 Cookie 至关重要。它允许你测试追踪系统是仅基于 Cookie、仅基于指纹,还是基于两者的组合来关联会话。对于多账户管理,每个身份都需要自己的 Cookie 存储,并在会话之间持久化,以维护登录状态和避免重复的身份验证流程。

Cookie 管理对于测试 Cookie 同意横幅、GDPR 合规流程以及网站对回访用户与新访客的不同行为也很重要。如果没有 Cookie 预加载,每次会话都从"新访客"开始,无法测试回访用户体验。

技术背景

Chromium 将 Cookie 存储在用户数据目录中的 SQLite 数据库中。浏览器启动时,会将 Cookie 从数据库加载到内存中。每个 Cookie 有以下属性:

  • Domain 和 Path:决定哪些请求包含该 Cookie
  • Name 和 Value:Cookie 携带的实际数据
  • Expiration:Cookie 应被删除的时间(会话 Cookie 没有过期时间)
  • Secure 标志:Cookie 是否仅通过 HTTPS 发送
  • HttpOnly 标志:JavaScript 是否可以访问该 Cookie
  • SameSite:控制跨站 Cookie 行为(Strict、Lax 或 None)

当页面加载时,浏览器会将匹配的 Cookie 附加到每个 HTTP 请求中。页面上的 JavaScript 也可以通过 document.cookie 读写 Cookie,但受 HttpOnly 限制。

时序问题

大多数自动化框架通过其 API 提供 Cookie 管理。Playwright 有 context.addCookies(),Puppeteer 有 page.setCookie()。然而,这些方法是在浏览器上下文或页面创建之后才添加 Cookie。这意味着最初的网络请求(包括初始页面加载和预检请求)发出时并不携带这些 Cookie。

这个时序间隙很重要,因为一些追踪系统会检查初始请求是否携带 Cookie。如果第一个请求没有 Cookie 但后续请求携带了 Cookie,这种不一致性在服务端日志中是可见的。

BotBrowser 的 --bot-cookies 标志通过在浏览器上下文完全初始化之前注入 Cookie 来解决这个问题,使其从第一个请求起就可用。

常见方案及其局限性

Playwright 和 Puppeteer 都通过各自的 API 提供 Cookie 管理。这些对许多用例很有效,但有局限性:

  1. 初始化后时序:通过框架 API 添加的 Cookie 仅在上下文或页面创建后才可用,错过了初始页面加载
  2. 上下文作用域:Cookie 绑定到浏览器上下文,而非浏览器实例。同一浏览器实例中的多个上下文不会共享 Cookie,除非显式配置
  3. 格式差异:每个框架使用略有不同的 Cookie 对象格式,使得在工具之间共享 Cookie 数据更加困难

手动用户数据目录持久化

另一种方案是跨会话重用相同的 --user-data-dir。这会自动保留 Cookie,因为它们持久存储在 SQLite 数据库中。然而,它也会保留所有其他状态:缓存、本地存储、IndexedDB、Service Worker 和浏览历史。这种方案无法细粒度地控制保留哪些状态、重置哪些状态。

浏览器扩展可以管理 Cookie,但它们运行在错误的权限级别。它们无法在第一次页面加载之前注入 Cookie,而且扩展本身的存在就是一个可检测的信号。

BotBrowser 的方案

BotBrowser 通过 --bot-cookies 标志在引擎级别实现 Cookie 预加载。与上述替代方案相比,这种设计具有多项优势。

引擎级注入

通过 --bot-cookies 加载的 Cookie 在初始化期间插入浏览器的 Cookie 存储中,在任何浏览器上下文创建之前、任何页面加载之前。这意味着:

  • 对任何域名的第一个 HTTP 请求已经携带了适当的 Cookie
  • 页面加载时运行的 JavaScript 可以通过 document.cookie 读取这些 Cookie
  • 服务端追踪系统从第一个请求起就看到一致的 Cookie 存在

灵活的输入格式

--bot-cookies 标志以两种方式接受 Cookie 数据:

内联 JSON,适用于少量 Cookie 或动态生成:

--bot-cookies='[{"name":"session","value":"abc123","domain":".example.com"}]'

文件引用,使用 @ 前缀引用较大的 Cookie 集合:

--bot-cookies="@/path/to/cookies.json"

文件应包含 Cookie 对象的 JSON 数组:

[
  {
    "name": "session_id",
    "value": "abc123def456",
    "domain": ".example.com",
    "path": "/",
    "expirationDate": 1774000000,
    "secure": true,
    "httpOnly": true,
    "sameSite": "Lax"
  },
  {
    "name": "user_pref",
    "value": "dark_mode=1&lang=en",
    "domain": ".example.com",
    "path": "/",
    "expirationDate": 1774000000,
    "secure": false,
    "httpOnly": false,
    "sameSite": "None"
  }
]

按身份隔离

每个 BotBrowser 实例都有自己独立的 Cookie 存储。通过将不同的 Cookie 文件与不同的指纹配置文件配对,你可以创建完全隔离的浏览器身份,其中指纹层和 Cookie 层都是独立的。

配置和用法

基本 CLI 用法

# 从文件加载 Cookie
./chrome \
  --bot-profile=/path/to/profile.enc \
  --bot-cookies="@/path/to/cookies.json"

# 内联 Cookie
./chrome \
  --bot-profile=/path/to/profile.enc \
  --bot-cookies='[{"name":"consent","value":"granted","domain":".example.com"}]'

Playwright 集成

const { chromium } = require('playwright-core');

(async () => {
  const browser = await chromium.launch({
    executablePath: '/path/to/botbrowser/chrome',
    args: [
      '--bot-profile=/path/to/profile.enc',
      '--bot-cookies=@/path/to/cookies.json',
    ],
    headless: true,
  });

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

  // Cookie 从第一个请求起就已存在
  const cookies = await context.cookies();
  console.log('Active cookies:', cookies.length);
  await browser.close();
})();
async function createIdentity(profilePath, cookiesPath) {
  return chromium.launch({
    executablePath: '/path/to/botbrowser/chrome',
    args: [
      `--bot-profile=${profilePath}`,
      `--bot-cookies=@${cookiesPath}`,
    ],
    headless: true,
  });
}

const userA = await createIdentity('/profiles/user-a.enc', '/cookies/user-a.json');
const userB = await createIdentity('/profiles/user-b.enc', '/cookies/user-b.json');

在每次会话结束时保存 Cookie,并在下次启动时重新加载:

// 会话结束时
const cookies = await context.cookies();
const fs = require('fs');
fs.writeFileSync('/cookies/user-a.json', JSON.stringify(cookies, null, 2));

// 下次会话:使用 --bot-cookies=@/cookies/user-a.json 启动

验证

使用 --bot-cookies 启动后,验证 Cookie 是否正确加载:

const page = await context.newPage();

// 在任何导航之前检查 Cookie 是否存在
const cookies = await context.cookies('https://example.com');
console.log('Pre-loaded cookies:', cookies.map(c => c.name));

// 导航并验证 Cookie 随请求发送
await page.goto('https://example.com');

// 验证 JavaScript 可访问的 Cookie
const jsCookies = await page.evaluate(() => document.cookie);
console.log('JS-visible cookies:', jsCookies);

你还可以使用框架的网络拦截功能检查初始请求头,以确认从第一个请求起就包含了 Cookie。

Cookie Loading Timeline --bot-cookies Engine init Context created Cookies ready First request Cookies sent addCookies() Too late --bot-cookies loads before context. Framework APIs load after.

最佳实践

  • 每个身份使用独立的 Cookie 文件。 不要在不同的指纹配置文件之间共享 Cookie 文件。
  • 设置合理的过期日期。 过期时间较远的 Cookie 符合正常浏览器行为。避免使用过去的日期。
  • 包含常见的同意 Cookie。 GDPR 或 Cookie 同意令牌可以防止每次访问时出现同意横幅,符合回访用户行为。
  • 在轮换配置文件时同步轮换 Cookie。 当你轮换指纹配置文件时,更新 Cookie 集合以匹配新身份。
  • 正确使用 HttpOnly 和 Secure 标志。 将标志设置为与目标网站在其 Set-Cookie 头中实际设置的一致。
  • 使用 @ 前缀引用文件路径。 这使你的启动命令更简洁,尤其是在处理大量 Cookie 时。

常见问题

该标志接受 Cookie 对象的 JSON 数组。每个对象至少应有 namevaluedomain。可选字段包括 pathexpirationDatesecurehttpOnlysameSite。你可以内联传递 JSON 或使用 @ 前缀引用文件。

通过 --bot-cookies 加载的 Cookie 在第一次页面导航之前就已可用。它们在浏览器初始化期间就存在于 Cookie 存储中,因此即使是第一个 HTTP 请求也会携带它们。

我可以将 --bot-cookies 与 Playwright 的 addCookies() 一起使用吗?

可以。--bot-cookies 的 Cookie 在初始化期间首先加载。如果需要,你可以稍后使用 context.addCookies() 添加更多 Cookie。这两种方法是互补的。

使用你的自动化框架在会话结束时读取 Cookie。使用 Playwright 时,用 context.cookies()。将结果保存为 JSON,然后在下次启动时传递给 --bot-cookies

--bot-cookies 可以与多个浏览器上下文一起工作吗?

通过 --bot-cookies 加载的 Cookie 对浏览器实例内的所有上下文可用。如果你需要每个上下文有不同的 Cookie,请使用框架的按上下文 Cookie API 来添加额外的 Cookie。

--bot-cookies 需要什么层级?

--bot-cookies 标志在 PRO 层级可用。

我可以将 --bot-cookies 与其他身份标志组合使用吗?

可以。将 --bot-cookies--bot-bookmarks--bot-inject-random-history 以及地区/时区标志组合使用,可以创建跨所有层级具有一致状态的完整浏览器身份。

总结

使用 --bot-cookies 进行 Cookie 管理,通过确保从第一个请求起 Cookie 就已存在,完善了 BotBrowser 的身份层。结合指纹配置文件和其他身份标志,它创建了跨所有层级保持一致状态的浏览器会话。

相关主题请参阅多账户隔离了解运行多个身份,代理配置了解将网络身份与 Cookie 对齐,以及配置文件管理了解如何组织配置文件和 Cookie 集合。

#Cookies#Management#Identity#Session#Privacy

让 BotBrowser 从研究走向生产

先用这些指南理解模型,再进入跨平台验证、隔离上下文和面向规模化的浏览器部署。