返回博客
身份

用户代理控制与客户端提示 (UA-CH) 在 BotBrowser 中的管理

了解 BotBrowser 如何在引擎层管理 User-Agent 字符串、Client Hints 头和 navigator.userAgentData,以确保一致的浏览器身份。

介绍

User-Agent 字符串长期以来一直是浏览器识别的核心。但现代浏览器身份系统更复杂。客户端提示(UA-CH)通过 HTTP 头和 JavaScript API 提供了结构化的浏览器信息。Sec-CH-UA 头、navigator.userAgentDatagetHighEntropyValues() 都以标准格式暴露品牌、平台、版本和设备信息。当这些值与传统的 User-Agent 字符串不一致时,会产生明显的追踪信号。

BotBrowser 通过配置文件和 CLI 覆盖来管理所有 User-Agent 和 Client Hints 信号。配置文件自动设置基线,CLI 标志在运行时提供自定义身份的控制。本文解释 UA 与 Client Hints 如何协同工作、哪些信号重要,以及如何正确配置它们。

隐私影响

User-Agent 与 Client Hints 是服务器首先接收到的信号之一。它们随初始 HTTP 请求到达,在任何 JavaScript 执行之前。这使得它们成为服务器端指纹和追踪的主要输入。

不匹配的 UA/Client Hints 的隐私风险包括:

  • 服务器端不一致检测:服务器会比较请求中的 User-AgentSec-CH-UA,不匹配表明该值被修改。
  • JavaScript 与头比较:页面可以比较 navigator.userAgentnavigator.userAgentData.brands 来检查一致性,任何差异都会被标记。
  • 高熵值关联getHighEntropyValues() 返回详细的 platform、architecture 与 version 信息,这些必须与总体身份匹配。
  • 跨上下文一致性:UA 值需在主线程、Web Worker、Service Worker 与 HTTP 头中保持一致。仅在部分上下文覆盖会产生可检测的差距。

BotBrowser 在这些层面保证一致性,因为它在引擎层控制 UA 与 Client Hints,在请求发送或任何 JavaScript 执行之前就设置好。

技术背景

User-Agent 字符串

传统的 User-Agent 头是一个较长的字符串,用于标识浏览器、版本、操作系统和渲染引擎:

Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.7444.60 Safari/537.36

该字符串随每个 HTTP 请求发送,并可通过 JavaScript 的 navigator.userAgent 访问。虽然浏览器逐步减少 UA 字符串中包含的信息(Chrome 的 UA Reduction),但它仍然是重要的身份信号。

客户端提示(UA-CH)

Client Hints 通过 HTTP 头和 JavaScript API 以结构化形式提供相同的信息:

默认头(随每次请求发送):

  • Sec-CH-UA:带有主版本号的品牌标记。例如:"Chromium";v="142", "Google Chrome";v="142", "Not:A-Brand";v="99"
  • Sec-CH-UA-Mobile:是否为移动设备。例如:?0
  • Sec-CH-UA-Platform:操作系统。例如:"Windows"

高熵头(仅在服务器通过 Accept-CH 请求时发送):

  • Sec-CH-UA-Full-Version-List
  • Sec-CH-UA-Platform-Version
  • Sec-CH-UA-Arch
  • Sec-CH-UA-Bitness
  • Sec-CH-UA-Model

JavaScript API (navigator.userAgentData):

// 低熵(始终可用,无需许可)
navigator.userAgentData.brands       // [{brand: "Chromium", version: "142"}, ...]
navigator.userAgentData.mobile       // false
navigator.userAgentData.platform     // "Windows"

// 高熵(返回 Promise)
const data = await navigator.userAgentData.getHighEntropyValues([
  'platformVersion', 'architecture', 'bitness',
  'fullVersionList', 'model'
]);

GREASE Token

Chromium 会在 Client Hints 中加入随机的 "GREASE"(Generate Random Extensions And Sustain Extensibility)标记,用以防止服务器对标记格式做硬编码假设。典型的 Sec-CH-UA 值会包含一个 GREASE 标记:

"Not:A-Brand";v="99", "Chromium";v="142", "Google Chrome";v="142"

GREASE 标记的格式、版本与位置会随浏览器版本与品牌变化。BotBrowser 会为每个配置文件与品牌生成正确的 GREASE 标记。

一致性要求

要构建可信的浏览器身份,以下各项都必须保持一致:

  1. User-Agent 头与 navigator.userAgent 一致
  2. Sec-CH-UA 中的品牌标记与 navigator.userAgentData.brands 一致
  3. Sec-CH-UA-Platformnavigator.userAgentData.platform 一致
  4. UA 字符串中的主版本与 Sec-CH-UA 品牌标记中的版本一致
  5. Sec-CH-UA-Full-Version-ListgetHighEntropyValues().fullVersionList 一致
  6. 平台版本需对所声明的 OS 合理(例如 Windows 11 的 "15.0.0" 或更高)
  7. 架构与位宽需与平台匹配(例如 Windows 为 x86/64,M 系 Mac 为 arm/64
  8. 主线程、Worker 与 HTTP 头中的值应相同

常见方法及限制

框架层 UA 覆盖

Playwright 与 Puppeteer 提供 UA 覆盖选项:

// Playwright
const context = await browser.newContext({
  userAgent: 'Custom UA String'
});

// Puppeteer
await page.setUserAgent('Custom UA String');

这些方法会改变 navigator.userAgentUser-Agent 頭,但不會更新:

  • Sec-CH-UA
  • navigator.userAgentData.brands
  • getHighEntropyValues() 的返回值
  • Worker 級別的 UA(可能不一致)

因此,覆蓋後的 UA 字符串與未改變的 Client Hints 之間的差異很容易被檢測到。

CDP 的 Network.setUserAgentOverride

CDP 提供 Network.setUserAgentOverride,並對 Client Hints 提供部分支持:

await cdpSession.send('Network.setUserAgentOverride', {
  userAgent: 'Custom UA',
  userAgentMetadata: {
    brands: [...],
    platform: 'Windows',
    // ...
  }
});

儘管比框架級覆蓋更全面,但仍有缺陷:

  • 需要 Network.enable,可能影響指紋採集
  • 需對每個目標(頁面、Worker)單獨設置
  • GREASE 標記不會自動生成
  • 版本對齊需手動處理,容易出錯

手動注入頭部

使用 page.setExtraHTTPHeaders() 可以覆蓋 Sec-CH-UA,但 JavaScript API (navigator.userAgentData) 仍返回真實值,這會產生 HTTP 與 JS 層的不一致。

BotBrowser 的方法

基於配置文件的自動配置

BotBrowser 的配置文件包含完整的 UA 與 Client Hints 配置,來自真實瀏覽器環境。加載配置文件後,所有信號會自動對齊:

chrome --bot-profile="/path/to/profile.enc"

配置文件設置:

  • User-Agent 字符串(頭與 JS)
  • 所有默認 Client Hints 頭
  • 所有高熵 Client Hints 值
  • navigator.userAgentData(brands、platform、mobile)
  • 對應瀏覽器版本的 GREASE 標記
  • 在主線程、Worker 與 HTTP 頭間保持一致的值

標準用法無需額外標志。

使用 CLI 覆蓋以構建自定義身份

當需要超出配置文件提供的自定義身份時,BotBrowser 提供細粒度的 CLI 標志:

(此處保留原文示例的標志列表)

自定義 User-Agent 支持佔位符(在運行時替換)示例:

chrome --bot-profile="/path/to/profile.enc" \
       --user-agent="Mozilla/5.0 (Linux; Android {platform-version}; {model}) AppleWebKit/537.36 Chrome/{ua-full-version} Mobile Safari/537.36" \
       --bot-config-platform=Android \
       --bot-config-platform-version=13 \
       --bot-config-model=SM-G991B \
       --bot-config-ua-full-version=142.0.7444.60

BotBrowser 會用對應的 --bot-config-* 值替換佔位符,然後自動生成匹配的 navigator.userAgentData 與所有 Client Hints 頭。

跨所有表面保證一致性

BotBrowser 確保 UA/Client Hints 在以下方面一致:

  • HTTP 頭:所有請求的 User-AgentSec-CH-UA-*
  • 主線程 JSnavigator.userAgent, navigator.userAgentData
  • Web Worker:Worker 上下文的 navigator.userAgentnavigator.userAgentData
  • Service Worker:Service Worker 範圍內的相同值
  • 高熵值getHighEntropyValues() 的返回與其他信號一致

配置與使用

(此處保留原文的示例與驗證代碼塊,保持不翻譯以保留可用性)

驗證

配置後請驗證對齊:

  1. 檢查 navigator.userAgent 是否包含正確的瀏覽器名與版本
  2. 驗證 navigator.userAgentData.brands 是否包含正確的品牌標記
  3. 確認 Sec-CH-UA 頭與 JS 報告的品牌一致
  4. 測試 getHighEntropyValues() 是否返回正確的 platform、architecture 與 version
  5. 在 Web Worker 上下文中驗證一致性

常見檢查點:

  • Windows 11 vs Windows 10Sec-CH-UA-Platform-Version"15.0.0" 或更高表示 Windows 11,值須與 UA 字符串匹配。
  • 品牌標記順序:檢查 GREASE、Chromium 與品牌標記的順序。
  • 版本對齊:UA 字符串的主版本應與 Sec-CH-UA 品牌標記的主版本一致。

最佳實踐

  1. 首選配置文件而非手動配置。 配置文件來源於真實瀏覽器,完整且一致。手動配置需要仔細對齊版本。
  2. 避免使用 Playwright/Puppeteer 的 UA 覆蓋。 框架級覆蓋只改變 UA 字符串,不會改變 Client Hints。使用配置文件可避免此類問題。
  3. 保持版本合理。 使用近期的瀏覽器版本,過舊的版本反而更顯眼。
  4. 對品牌特定的版本進行對齊。 使用 --bot-config-browser-brand=edge 時,配合真實的 Edge 品牌版本。
  5. 使用指紋驗證工具進行測試。 每次配置變更後驗證 UA 與 Client Hints 的一致性。
  6. 定期更新配置文件。 瀏覽器版本頻繁變化,使用最新配置文件以匹配大多數用戶。

常見問題

(此處保留 FAQ 原文要點的翻譯,保留技術術語不變)

總結

User-Agent 與 Client Hints 是瀏覽器身份的網絡層基礎。BotBrowser 通過捕獲真實瀏覽器配置的配置文件與提供運行時自定義的 CLI 標志來管理這些信號。HTTP 頭、JavaScript API 與 Worker 上下文等所有信號都會自動保持一致。

如需品牌身份控制,請參閱 Browser Brand Switching。如需地理身份,請參閱 Timezone, Locale, and Language Configuration。如需完整身份隔離,請參閱 Multi-Account Browser Isolation

title: "BotBrowser 中的 User Agent 控制与 Client Hints (UA-CH)" description: "了解 BotBrowser 如何在引擎级别管理 User-Agent 字符串和 Client Hints,实现一致的浏览器身份。" date: "2025-10-22" locale: zh category: identity tags: ["user-agent", "client-hints", "identity", "ua-ch", "privacy"] published: true

BotBrowser 如何管理 UA 和 Client Hints

BotBrowser 配置包含来自真实浏览器环境的完整 User-Agent 和 Client Hints 值集。加载配置时,所有信号自动对齐:

  • HTTP 头User-Agent 和所有 Sec-CH-* 头都匹配
  • JavaScript APInavigator.userAgentnavigator.userAgentData.brandsgetHighEntropyValues() 返回一致的值
  • 平台信号:平台、架构、位数和版本信息全部匹配

配置自动设置一切。无需额外标志:

chrome --bot-profile="/path/to/profile.enc"

要覆盖浏览器品牌同时保持其他值一致:

chrome --bot-profile="/path/to/profile.enc" \
       --bot-config-browser-brand=edge

管理的内容

默认头在每个请求中发送:Sec-CH-UA(品牌令牌)、Sec-CH-UA-MobileSec-CH-UA-Platform

高熵值通过 JavaScript 可用:Sec-CH-UA-Full-Version-ListSec-CH-UA-Platform-VersionSec-CH-UA-ArchSec-CH-UA-BitnessSec-CH-UA-Model

通过 navigator.userAgentData 进行 JavaScript 访问:

// 低熵(始终可用)
navigator.userAgentData.brands
navigator.userAgentData.platform

// 高熵(需要 promise)
const data = await navigator.userAgentData.getHighEntropyValues([
  'platformVersion', 'architecture', 'bitness', 'fullVersionList'
]);

验证示例

const puppeteer = require('puppeteer-core');

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

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

  const ua = await page.evaluate(() => navigator.userAgent);
  const brands = await page.evaluate(() =>
    navigator.userAgentData.brands.map(b => `${b.brand} v${b.version}`)
  );
  const highEntropy = await page.evaluate(async () => {
    return await navigator.userAgentData.getHighEntropyValues([
      'platformVersion', 'architecture', 'bitness', 'fullVersionList'
    ]);
  });

  console.log('User-Agent:', ua);
  console.log('Brands:', brands);
  console.log('High-entropy:', highEntropy);
  await browser.close();
})();

常见陷阱

覆盖 UA 但不覆盖 Client Hints。 Puppeteer 的 page.setUserAgent() 或 Playwright 的 userAgent 选项只更改 UA 字符串。Client Hints 保持不变,造成不匹配。使用 BotBrowser 配置,您不需要这些覆盖。

平台版本不匹配。 Windows 11 的 Sec-CH-UA-Platform-Version 从 "13.0.0" 开始,而 Windows 10 报告较低的值。BotBrowser 配置包含正确的版本。

品牌顺序错误。 Chrome、Edge、Brave 和 Opera 各有特定的品牌令牌顺序。BotBrowser 配置保持正确的顺序。

开始使用

  1. GitHub 下载 BotBrowser
  2. 使用 --bot-profile 加载配置以自动实现 UA 和 Client Hints 一致性
  3. 可选使用 --bot-config-browser-brand 切换品牌身份
  4. 使用指纹工具验证所有 UA 信号匹配
#user-agent#client-hints#identity#ua-ch#privacy