使用 BotBrowser 管理 Cookie
了解如何使用 --bot-cookies 标志在 BotBrowser 中管理 Cookie,实现会话持久性、跨会话连续性和按身份隔离。
介绍
Cookie 是浏览器维护状态的基石。它们携带会话令牌、用户偏好、同意记录和认证凭证,在页面加载和访问之间保持状态。在为隐私研究、测试或多账户管理构建浏览器配置文件时,控制 Cookie 层与控制指纹层同等重要。一个指纹一致但没有 Cookie 的浏览器每次看起来像是全新安装,这并非真实浏览器的行为。
BotBrowser 提供了 --bot-cookies 标志(PRO 级)用于在启动时预加载 Cookie。这样 Cookie 会在首次导航、任何 JavaScript 执行之前就已存在,防止跟踪脚本在检查浏览器状态时发现缺失的 Cookie。配合指纹配置文件和其他身份信号,Cookie 管理可以完善真实且持久的浏览器身份。
隐私影响:为什么 Cookie 管理重要
网站和跟踪系统不会单独评估 Cookie,而是查看 Cookie 与其他浏览器信号之间的关联。一个呈现为返回用户的指纹但没有 Cookie 的浏览器会引发怀疑;同样,一个只有会话 Cookie 但完全新的指纹也显得不一致。
对于研究跟踪系统如何关联浏览器信号的隐私研究人员而言,控制 Cookie 至关重要。它允许你测试跟踪系统是仅基于 Cookie、仅基于指纹,还是基于两者的组合来链接会话。对于多账户管理,每个身份需要自己的 Cookie 存储并在会话间持久保存,以维持登录状态并避免重复认证流程。
Cookie 管理对于测试 Cookie 同意横幅、GDPR 合规流程以及网站对返回用户与新访客的不同表现也很重要。没有预加载 Cookie,每次会话都从“新访客”开始,无法测试返回用户体验。
技术背景
浏览器如何存储 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 来解决此问题,使 Cookie 在首次请求时就可用。
常见方法及其局限
框架级 Cookie API
Playwright 和 Puppeteer 都通过其 API 提供 Cookie 管理。它们在许多用例下有效,但存在局限:
- 时序晚:通过框架 API 添加的 Cookie 只有在上下文或页面创建后才可用,错过初始页面加载
- 与上下文绑定:Cookie 与浏览器上下文相关联,不是浏览器实例级别。除非显式配置,否则同一浏览器实例内的多个上下文不会共享 Cookie
- 格式差异:每个框架使用略有不同的 Cookie 对象格式,难以在工具间共享 Cookie 数据
手动持久化用户数据目录
另一种方法是跨会话重用相同的 --user-data-dir。这会自动保留 Cookie,因为它们保存在 SQLite 数据库中,但同时也会保留缓存、本地存储、IndexedDB、service worker 和浏览历史。该方法无法对保留哪些状态进行细粒度控制。
Cookie 扩展
浏览器扩展可以管理 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 对象数组:
[
{
"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"
# 内联 Cookies
./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');
// Cookies 在首次请求时已存在
const cookies = await context.cookies();
console.log('Active cookies:', cookies.length);
await browser.close();
})();
每个身份的 Cookie 隔离
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 以保持会话持久性
在会话结束时保存 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 文件。 不要在不同的指纹配置文件之间共享同一 Cookie 文件。
- 设置合理的到期时间。 与真实浏览器行为一致的远期到期时间更真实,避免使用过去的时间。
- 包含常见的同意 Cookie。 GDPR 或同意令牌可以阻止每次访问都弹出同意横幅,使返回用户行为更自然。
- 在轮换配置文件时同步轮换 Cookie。 更换指纹配置文件时,同时更新 Cookie 集以匹配新身份。
- 正确使用 HttpOnly 和 Secure 标志。 按目标站点实际设置的
Set-Cookie标志进行匹配。 - 对文件路径使用
@前缀。 处理大量 Cookie 时,使用@前缀可以让启动命令更简洁。
常见问题
--bot-cookies 接受什么格式的 Cookie?
该标志接受一个 Cookie 对象数组的 JSON。每个对象至少应包含 name、value 和 domain。可选字段包括 path、expirationDate、secure、httpOnly 和 sameSite。可以内联传递 JSON,或用 @ 前缀引用文件。
Cookie 相对于页面加载何时可用?
通过 --bot-cookies 加载的 Cookie 在首次页面导航之前就可用。它们在浏览器初始化期间即已存在,因此即使是最先发出的 HTTP 请求也会携带这些 Cookie。
我可以将 --bot-cookies 与 Playwright 的 addCookies() 一起使用吗?
可以。--bot-cookies 会在初始化阶段首先加载 Cookie。你可以在需要时使用 context.addCookies() 添加更多 Cookie,两者是互补的。
如何导出 Cookie 以便在下次会话重用?
在会话结束时使用自动化框架读取 Cookie(例如 Playwright 的 context.cookies()),保存为 JSON,然后在下次启动时将其传递给 --bot-cookies。
--bot-cookies 是否适用于多个浏览器上下文?
通过 --bot-cookies 加载的 Cookie 可用于浏览器实例内的所有上下文。如果你需要为不同上下文使用不同的 Cookie,请在额外需要的 Cookie 上使用框架的每上下文 Cookie API。
哪个级别需要 --bot-cookies?
--bot-cookies 标志为 PRO 级功能。
我可以将 --bot-cookies 与其他身份标志组合使用吗?
可以。将 --bot-cookies 与 --bot-bookmarks、--bot-inject-random-history、时区/语言相关标志等结合使用,可以创建在所有层面都一致的完整浏览器身份。
摘要
使用 --bot-cookies 进行的 Cookie 管理通过确保从首次请求开始就存在 Cookie 来完善 BotBrowser 的身份层。配合指纹配置文件和其他身份标志,它能创建在所有层面上保持一致状态的浏览器会话。
如需相关主题,请参见 Multi-Account Isolation、Proxy Configuration 和 Profile Management。
title: "BotBrowser Cookie 管理" description: "了解如何使用 --bot-cookies 标志和 Playwright 在 BotBrowser 中管理 cookie,实现会话持久化和按上下文隔离。" date: "2025-11-11" locale: zh category: identity tags: ["cookies", "management", "identity", "session", "privacy"] published: true
--bot-cookies 标志
BotBrowser 提供 --bot-cookies 标志(ENT Tier1)在启动时注入 cookie,让您在首次页面加载前完全控制会话状态。
./chrome \
--bot-profile=/path/to/profile.enc \
--bot-cookies=/path/to/cookies.json
Cookie 文件格式
cookie 文件使用标准 Chromium cookie 格式:
[
{
"domain": ".example.com",
"path": "/",
"name": "session_id",
"value": "abc123def456",
"expirationDate": 1774000000,
"secure": true,
"httpOnly": true,
"sameSite": "Lax"
},
{
"domain": ".example.com",
"path": "/",
"name": "user_pref",
"value": "dark_mode=1&lang=en",
"expirationDate": 1774000000,
"secure": false,
"httpOnly": false,
"sameSite": "None"
}
]
cookie 在浏览器启动时立即可用,在任何导航发生之前。
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');
const cookies = await context.cookies();
console.log('活跃 cookies:', cookies.length);
await browser.close();
})();
--bot-cookies 标志在浏览器上下文完全初始化之前加载 cookie,使其在页面加载的最早阶段就可用。这与 Playwright 的 context.addCookies() 方法不同,后者在上下文创建后添加 cookie。
按身份 Cookie 隔离
每个浏览器实例应携带自己的 cookie 集:
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 存储。
导出 Cookie 实现会话持久化
在每个会话结束时保存 cookie,在下次启动时重新加载:
const cookies = await context.cookies();
const fs = require('fs');
fs.writeFileSync('/cookies/user-a.json', JSON.stringify(cookies, null, 2));
下次运行时,将保存的文件传递给 --bot-cookies,会话将从上次中断处继续。
最佳实践
- 每个身份保持独立的 cookie 文件。 不要在不同的指纹配置之间共享 cookie 文件。
- 设置合理的过期日期。 具有远期过期时间的 cookie 看起来很正常。
- 包含常见的同意 cookie。 GDPR 或 cookie 同意令牌可防止每次访问都出现同意横幅。
- 随配置轮换 cookie。 轮换指纹配置时,更新 cookie 集以匹配。
- 正确使用 httpOnly 和 secure 标志。 匹配目标站点实际设置的标志。