返回博客
网络

自定义 HTTP 头:使用 BotBrowser 控制请求头

了解如何使用 BotBrowser 的 --bot-custom-headers 标志和 CDP API 在浏览器引擎级别设置自定义 HTTP 头,以获得一致的请求身份。

介绍

HTTP 头是浏览器发送的每个请求的一部分。像 User-AgentAccept-LanguageSec-CH-UAReferer 这样的头构成了浏览器网络身份的重要部分。当这些头与您的指纹配置不一致,或者您需要注入用于认证和路由的应用专用头时,标准浏览器 API 往往力不从心。

BotBrowser 通过 --bot-custom-headers 标志和 BotBrowser.setCustomHeaders CDP 命令提供引擎级的头控制。与在请求形成后才拦截请求的扩展不同,BotBrowser 在请求离开浏览器网络栈之前修改头,覆盖所有请求类型且不会产生时间差。

隐私影响

HTTP 头泄露了关于浏览器环境的丰富信息。User-Agent 标识浏览器版本和操作系统;Accept-Language 暴露语言偏好并间接指示地理区域。Client Hints 头(例如 Sec-CH-UASec-CH-UA-PlatformSec-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 请求时,头来自多个来源:

  1. 内置头User-AgentAcceptAccept-EncodingAccept-Language 由浏览器引擎根据内部设置添加。
  2. Client HintsSec-CH-UASec-CH-UA-MobileSec-CH-UA-Platform 默认发送。高熵提示(如 Sec-CH-UA-Full-Version-List)仅在服务器通过 Accept-CH 请求时发送。
  3. 应用级头:通过 fetch()XMLHttpRequest 在 JavaScript 中设置的头。
  4. 扩展注入的头:通过 webRequest API 添加的头。

这些头的顺序和组成为每个浏览器形成一致的模式。Chrome、Edge 和 Firefox 在头的顺序与组合上各有差异。

基于配置文件的头一致性

当 BotBrowser 加载指纹配置时,会配置所有标准头以匹配配置文件的身份:

  • User-Agent 与配置文件的浏览器版本和平台匹配
  • Sec-CH-UA 包含正确顺序的品牌令牌
  • Sec-CH-UA-Platform 与配置文件的操作系统一致
  • Accept-Language 反映配置的区域和语言偏好

这些头在引擎级设置,适用于所有请求,包括初始导航请求、子资源加载和 JS 发起的请求,不会存在可以被观察到的时间差。

自定义头与标准头的区别

自定义头(以 X- 开头或应用专用名称)承载应用级数据:认证令牌、会话标识、应用版本或路由信息。BotBrowser 的 --bot-custom-headers 标志添加这些自定义头,同时不修改由配置文件管理的标准头。

Header Sources in BotBrowser Profile (Automatic) User-Agent, Sec-CH-UA-* Accept-Language CLI Override --bot-config-locale --bot-config-languages Custom Headers --bot-custom-headers BotBrowser.setCustomHeaders Final Request Headers All sources merge at the engine level before the request is sent

常见方法及其局限

基于扩展的头修改

浏览器扩展可以通过 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 并设置自定义头后,验证其是否生效:

  1. 打开回显请求头的页面(如 https://httpbin.org/headers)
  2. 确认自定义头出现在响应中
  3. 在 DevTools 的 Network 面板检查所有请求类型的头
  4. 验证标准头(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);

最佳实践

  1. 静态头使用 --bot-custom-headers 如果头在会话期间不变,CLI 标志比 CDP 更简单。

  2. 动态头使用 BotBrowser.setCustomHeaders 需要在会话中轮换认证令牌时使用 CDP 命令。

  3. 不要覆盖配置文件管理的标准头。 自定义头应新增字段,而非替换 User-Agent 或 Sec-CH-UA;覆盖会导致不一致。

  4. 避免使用常见扩展头名。X-Forwarded-ForX-Real-IP 可能与代理基础设施冲突,优先使用应用专用名称。

  5. 使用 httpbin.org/headers 进行测试。 该端点会回显所有收到的头,便于验证配置。

  6. 始终通过浏览器级 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 ConfigurationUser 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-AgentAccept-LanguageSec-CH-UA 等 HTTP 头是浏览器身份的一部分。BotBrowser 通过配置自动管理所有标准头,并允许您在引擎级别添加自定义头。

基于配置的头部一致性

加载指纹配置时,BotBrowser 自动将所有标准头与配置的身份对齐。User-AgentSec-CH-UAAccept-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 后:

  1. 打开 DevTools 检查 Network 标签页中的请求头
  2. 验证自定义头出现在所有请求类型中
  3. 确认标准头与加载的配置匹配

开始使用

  1. GitHub 下载 BotBrowser
  2. 使用 --bot-profile 加载指纹配置
  3. 使用 --bot-custom-headers 添加自定义头
  4. 验证所有请求类型中的头一致性
#http-headers#custom-headers#network#privacy#request