自定义 HTTP 头:使用 BotBrowser 控制请求头
了解如何使用 BotBrowser 的 --bot-custom-headers 标志和 CDP API 在浏览器引擎级别设置自定义 HTTP 头,以获得一致的请求身份。
介绍
HTTP 头是浏览器发送的每个请求的一部分。像 User-Agent、Accept-Language、Sec-CH-UA 和 Referer 这样的头构成了浏览器网络身份的重要部分。当这些头与您的指纹配置不一致,或者您需要注入用于认证和路由的应用专用头时,标准浏览器 API 往往力不从心。
BotBrowser 通过 --bot-custom-headers 标志和 BotBrowser.setCustomHeaders CDP 命令提供引擎级的头控制。与在请求形成后才拦截请求的扩展不同,BotBrowser 在请求离开浏览器网络栈之前修改头,覆盖所有请求类型且不会产生时间差。
隐私影响
HTTP 头泄露了关于浏览器环境的丰富信息。User-Agent 标识浏览器版本和操作系统;Accept-Language 暴露语言偏好并间接指示地理区域。Client Hints 头(例如 Sec-CH-UA、Sec-CH-UA-Platform、Sec-CH-UA-Mobile)提供有关浏览器品牌、平台和设备类型的结构化数据。
当这些头与指纹的其他方面不一致时,会产生可被关联的不匹配。例如:Accept-Language: de-DE 但时区为美国,或 Sec-CH-UA-Platform: "Windows" 但 navigator 属性显示 macOS,这些都会形成可检测的差异。
BotBrowser 配置会自动将所有标准头与配置文件的身份对齐。User-Agent、所有 Sec-CH-UA-* 头和 Accept-Language 都源自配置文件的浏览器、平台和区域设置。通过 --bot-custom-headers 添加的自定义头在扩展此基线的同时不会破坏标准头集合。
技术背景
浏览器如何构建请求头
浏览器发送 HTTP 请求时,头来自多个来源:
- 内置头:
User-Agent、Accept、Accept-Encoding、Accept-Language由浏览器引擎根据内部设置添加。 - Client Hints:
Sec-CH-UA、Sec-CH-UA-Mobile、Sec-CH-UA-Platform默认发送。高熵提示(如Sec-CH-UA-Full-Version-List)仅在服务器通过Accept-CH请求时发送。 - 应用级头:通过
fetch()或XMLHttpRequest在 JavaScript 中设置的头。 - 扩展注入的头:通过
webRequestAPI 添加的头。
这些头的顺序和组成为每个浏览器形成一致的模式。Chrome、Edge 和 Firefox 在头的顺序与组合上各有差异。
基于配置文件的头一致性
当 BotBrowser 加载指纹配置时,会配置所有标准头以匹配配置文件的身份:
User-Agent与配置文件的浏览器版本和平台匹配Sec-CH-UA包含正确顺序的品牌令牌Sec-CH-UA-Platform与配置文件的操作系统一致Accept-Language反映配置的区域和语言偏好
这些头在引擎级设置,适用于所有请求,包括初始导航请求、子资源加载和 JS 发起的请求,不会存在可以被观察到的时间差。
自定义头与标准头的区别
自定义头(以 X- 开头或应用专用名称)承载应用级数据:认证令牌、会话标识、应用版本或路由信息。BotBrowser 的 --bot-custom-headers 标志添加这些自定义头,同时不修改由配置文件管理的标准头。
常见方法及其局限
基于扩展的头修改
浏览器扩展可以通过 webRequest.onBeforeSendHeaders API 修改头,但存在若干缺点:
- 时序问题:首次导航请求可能在扩展监听器完全注册之前触发
- 覆盖不全:Service Worker 请求、CORS 预检请求及部分内部请求可能不会触发扩展监听器
- 可检测痕迹:修改头的扩展会在扩展 API 面暴露痕迹
- 性能开销:每个请求都经过扩展的 JS 处理器,增加延迟
基于 CDP 的头覆盖
Puppeteer 和 Playwright 提供通过 CDP 的头覆盖 API:
// Puppeteer - limited approach
await page.setExtraHTTPHeaders({ 'X-Custom': 'value' });
此方法适用于页面级头,但有限制:
- 仅适用于特定页面
- Service Worker 和 Shared Worker 可能无法接收到这些头
- CDP 的
Network.setExtraHTTPHeaders需要Network.enable,这本身可能影响指纹
JavaScript Fetch/XHR 头
在单个 fetch() 或 XMLHttpRequest 调用中设置头只覆盖 JS 发起的请求。导航、图像加载、样式表和其他浏览器发起的请求不受影响。
BotBrowser 的方法
--bot-custom-headers 标志
BotBrowser 的 --bot-custom-headers 标志(PRO)在浏览器引擎级注入自定义头:
chrome --bot-profile="/path/to/profile.enc" \
--bot-custom-headers='{"X-Custom-Header":"value","X-Auth-Token":"abc123"}' \
--user-data-dir="$(mktemp -d)"
由于修改发生在 Chromium 网络栈内部,自定义头会添加到:
- 初始导航请求
- 子资源请求(图片、脚本、样式、字体)
- XHR 和 Fetch API 请求
- WebSocket 升级请求
- Service Worker 请求
不存在时间差或遗漏的请求类型。
BotBrowser.setCustomHeaders CDP 命令
要在运行时管理头,BotBrowser 提供可发送到浏览器级会话的 CDP 命令:
Puppeteer:
const cdpSession = await browser.target().createCDPSession();
await cdpSession.send('BotBrowser.setCustomHeaders', {
headers: { 'x-requested-with': 'com.example.app' }
});
Playwright:
const cdpSession = await browser.newBrowserCDPSession();
await cdpSession.send('BotBrowser.setCustomHeaders', {
headers: { 'x-requested-with': 'com.example.app' }
});
重要:该命令必须发送到浏览器级 CDP 会话,而不是页面级会话。发送到页面目标将返回 ProtocolError: 'BotBrowser.setCustomHeaders' wasn't found。
配置文件级设置
也可以在配置文件的 configs.customHeaders 中设置自定义头,这在希望将头嵌入配置文件而不是在启动时指定时非常有用。
配置与使用
CLI 使用示例
chrome --bot-profile="/path/to/profile.enc" \
--bot-custom-headers='{"X-App-Version":"2.1.0","X-Session-ID":"sess_abc123"}' \
--proxy-server=socks5://user:pass@proxy:1080 \
--user-data-dir="$(mktemp -d)"
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-custom-headers={"X-Auth":"token123","X-Client":"webapp"}',
],
headless: true,
});
const context = await browser.newContext();
const page = await context.newPage();
await page.goto('https://example.com');
await browser.close();
})();
Puppeteer 集成
const puppeteer = require('puppeteer-core');
(async () => {
const browser = await puppeteer.launch({
executablePath: '/path/to/botbrowser/chrome',
args: [
'--bot-profile=/path/to/profile.enc',
'--bot-custom-headers={"X-Auth":"token123"}',
],
headless: true,
defaultViewport: null,
});
const page = await browser.newPage();
await page.goto('https://example.com');
await browser.close();
})();
JavaScript 中的引号注意
从 JavaScript 传递 --bot-custom-headers 时,不要在值中包含 shell 风格的引号:
// 正确
const headers = { 'X-Custom': 'value', 'X-Auth': 'token' };
args.push('--bot-custom-headers=' + JSON.stringify(headers));
// 错误 - 单引号会成为 JSON 值的一部分
args.push(`--bot-custom-headers='${JSON.stringify(headers)}'`);
通过 CDP 运行时更新头
对于需要在会话中更改自定义头的工作流:
const { chromium } = require('playwright-core');
(async () => {
const browser = await chromium.launch({
executablePath: '/path/to/botbrowser/chrome',
args: [
'--bot-profile=/path/to/profile.enc',
],
headless: true,
});
const cdpSession = await browser.newBrowserCDPSession();
// 设置初始头
await cdpSession.send('BotBrowser.setCustomHeaders', {
headers: { 'x-requested-with': 'com.example.app' }
});
const page = await (await browser.newContext()).newPage();
await page.goto('https://example.com');
// 会话中更新头
await cdpSession.send('BotBrowser.setCustomHeaders', {
headers: { 'x-requested-with': 'com.example.app', 'x-session': 'refreshed' }
});
await page.goto('https://example.com/dashboard');
await browser.close();
})();
验证
启动 BotBrowser 并设置自定义头后,验证其是否生效:
- 打开回显请求头的页面(如 https://httpbin.org/headers)
- 确认自定义头出现在响应中
- 在 DevTools 的 Network 面板检查所有请求类型的头
- 验证标准头(User-Agent、Sec-CH-UA)仍与配置文件一致
const page = await context.newPage();
await page.goto('https://httpbin.org/headers');
const headersText = await page.textContent('body');
console.log('Request headers:', headersText);
最佳实践
-
静态头使用
--bot-custom-headers。 如果头在会话期间不变,CLI 标志比 CDP 更简单。 -
动态头使用
BotBrowser.setCustomHeaders。 需要在会话中轮换认证令牌时使用 CDP 命令。 -
不要覆盖配置文件管理的标准头。 自定义头应新增字段,而非替换 User-Agent 或 Sec-CH-UA;覆盖会导致不一致。
-
避免使用常见扩展头名。 像
X-Forwarded-For或X-Real-IP可能与代理基础设施冲突,优先使用应用专用名称。 -
使用 httpbin.org/headers 进行测试。 该端点会回显所有收到的头,便于验证配置。
-
始终通过浏览器级 CDP 会话调用 setCustomHeaders。 页面级会话会返回错误,因为该命令在浏览器级别运行。
常见问题
自定义头是否应用于所有请求还是仅导航? 适用于所有请求。BotBrowser 在引擎级别应用自定义头,覆盖导航、子资源、XHR、Fetch、WebSocket 和 Service Worker 请求。
可以为每个 context 设置不同的自定义头吗?
--bot-custom-headers 适用于所有 context。若需按 context 区分,使用 BotBrowser.setCustomHeaders 并在 context 操作之间更新。
自定义头会影响指纹吗?
不属于标准浏览器头集合的自定义头(如 X-Custom-Header)不会影响浏览器指纹,它们只是请求中的附加字段。
可以移除标准头吗? BotBrowser 不支持通过自定义头移除标准头。为维护指纹一致性,配置文件管理的头始终包含。
--bot-custom-headers 与 --proxy-server 一起使用吗?
可以。无论是否配置代理,自定义头都会添加到请求中,代理会看到完整的头集合。
可设置的自定义头数量有限制吗? 没有明确限制。但过多的头会增大请求大小,可能触发服务端限制。
可以用 --bot-custom-headers 设置 Cookie 头吗?
请使用专用的 --bot-cookies 标志管理 Cookie,它提供域范围和过期的正确处理。
总结
HTTP 头控制对于维持一致的浏览器身份至关重要。BotBrowser 通过配置文件(用于标准头)、--bot-custom-headers 标志(用于静态自定义头)和 BotBrowser.setCustomHeaders CDP 命令(用于运行时动态头)提供引擎级的头管理。这些工具确保每个请求都携带一致且完整的头信息。
相关阅读:Proxy Configuration 和 User Agent Control and Client Hints。有关多账户身份管理,请参阅 Multi-Account Browser Isolation。
title: "自定义 HTTP 头:使用 BotBrowser 控制请求头" description: "了解如何使用 BotBrowser 的 --bot-custom-headers 标志设置自定义 HTTP 头以保持一致的浏览器身份。" date: "2025-09-23" locale: zh category: network tags: ["http-headers", "custom-headers", "network", "privacy", "request"] published: true
为什么头部控制很重要
User-Agent、Accept-Language 和 Sec-CH-UA 等 HTTP 头是浏览器身份的一部分。BotBrowser 通过配置自动管理所有标准头,并允许您在引擎级别添加自定义头。
基于配置的头部一致性
加载指纹配置时,BotBrowser 自动将所有标准头与配置的身份对齐。User-Agent、Sec-CH-UA 和 Accept-Language 头都匹配配置的浏览器、平台和区域设置。
chrome --bot-profile="/path/to/profile.enc" \
--bot-config-locale="de-DE" \
--bot-config-languages="de-DE,de,en-US,en" \
--user-data-dir="$(mktemp -d)"
这确保 Accept-Language 匹配配置的区域设置,所有 Client Hints 头与配置对齐。
添加自定义头
--bot-custom-headers 标志允许您在浏览器引擎级别设置额外的 HTTP 头:
chrome --bot-profile="/path/to/profile.enc" \
--bot-custom-headers='{"X-Custom-Header":"value","Another-Header":"value2"}' \
--user-data-dir="$(mktemp -d)"
自定义头的使用场景包括认证令牌、应用特定标识符和自定义跟踪防护头。
引擎级修改
由于 BotBrowser 在 Chromium 引擎级别修改头,更改适用于所有请求:
- 初始页面加载
- 子资源请求(图片、脚本、样式表)
- XHR 和 Fetch API 请求
- WebSocket 升级请求
这与基于扩展的头修改根本不同,后者可能遗漏早期请求。
Puppeteer 示例
const puppeteer = require('puppeteer-core');
const browser = await puppeteer.launch({
executablePath: '/path/to/botbrowser/chrome',
args: [
'--bot-profile=/path/to/profile.enc',
'--bot-custom-headers={"X-Auth":"token123"}',
],
headless: true,
defaultViewport: null,
});
const page = await browser.newPage();
await page.goto('https://example.com');
await browser.close();
验证
使用自定义头启动 BotBrowser 后:
- 打开 DevTools 检查 Network 标签页中的请求头
- 验证自定义头出现在所有请求类型中
- 确认标准头与加载的配置匹配
开始使用
- 从 GitHub 下载 BotBrowser
- 使用
--bot-profile加载指纹配置 - 使用
--bot-custom-headers添加自定义头 - 验证所有请求类型中的头一致性