身份

User-Agent 和 Client Hints (UA-CH):完整控制指南

User-Agent 字符串、Client Hints 头和 navigator.userAgentData 如何协同工作,以及如何在引擎级别一致地管理它们。

文档中心

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

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

简介

User-Agent 字符串几十年来一直是浏览器身份识别的基石。但现代浏览器身份系统更加复杂。Client Hints (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-Agent 头和 Sec-CH-UA 头。不匹配表明有修改。
  • JavaScript 与头比较:页面可以比较 navigator.userAgentnavigator.userAgentData.brands 并检查对齐情况。任何差异都会被标记。
  • 高熵值关联getHighEntropyValues() 返回详细的平台、架构和版本信息。这些必须与更广泛的身份匹配。
  • 跨上下文一致性: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 缩减),但它仍然是一个重要的身份信号。

Client Hints (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:操作系统版本(例如 Windows 11 为 "15.0.0"
  • Sec-CH-UA-Arch:CPU 架构(例如 "x86"
  • Sec-CH-UA-Bitness:系统位数(例如 "64"
  • Sec-CH-UA-Model:设备型号(主要用于移动端)

JavaScript APInavigator.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 令牌

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-Platform 中的平台与 navigator.userAgentData.platform 匹配
  4. UA 字符串中的主版本号与 Sec-CH-UA 品牌令牌中的版本匹配
  5. Sec-CH-UA-Full-Version-List 中的完整版本与 getHighEntropyValues().fullVersionList 匹配
  6. 平台版本对于声称的操作系统是合理的(例如 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 提供带有部分 Client Hints 支持的 Network.setUserAgentOverride

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 级别和 JavaScript 级别的身份之间造成不匹配。

BotBrowser 的方案

基于配置文件的自动配置

BotBrowser 配置文件包含从真实浏览器环境中采集的完整 UA 和 Client Hints 配置。当你加载配置文件时,所有信号自动对齐:

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

配置文件设置:

  • User-Agent 字符串(头和 JavaScript)
  • 所有默认 Client Hints 头
  • 所有高熵 Client Hints 值
  • navigator.userAgentData(brands、platform、mobile)
  • 适合浏览器版本的 GREASE 令牌
  • 主线程、Worker 和 HTTP 头之间的一致值

标准 UA/Client Hints 配置不需要额外标志。

用于自定义身份的 CLI 覆盖

当你需要构建超出配置文件提供范围的自定义身份时,BotBrowser 提供细粒度的 CLI 标志:

核心身份标志:

  • --bot-config-browser-brand=chrome|edge|brave|opera|webview(ENT Tier2):切换浏览器品牌
  • --bot-config-ua-full-version=142.0.7444.60(ENT Tier2):设置 Chromium 完整版本
  • --bot-config-brand-full-version=142.0.3595.65(ENT Tier2):设置品牌特定版本(用于 Edge、Opera 等)

平台和设备标志(ENT Tier3):

  • --bot-config-platform=Windows|Android|macOS|Linux:平台名称
  • --bot-config-platform-version=13:操作系统版本字符串
  • --bot-config-model=SM-G991B:设备型号(移动端)
  • --bot-config-architecture=x86|arm|arm64:CPU 架构
  • --bot-config-bitness=32|64:系统位数
  • --bot-config-mobile=true|false:移动设备标志

带占位符的自定义 User-Agent:

--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 将 {platform-version}{model}{ua-full-version} 替换为相应的标志值,然后自动生成匹配的 navigator.userAgentData 和所有 Client Hints 头。

跨所有表面的一致性

BotBrowser 确保 UA/Client Hints 在以下各处保持一致:

  • HTTP 头:每个请求上的所有 User-AgentSec-CH-UA-*
  • 主线程 JavaScriptnavigator.userAgentnavigator.userAgentData
  • Web Worker:Worker 上下文中的 navigator.userAgentnavigator.userAgentData
  • Service Worker:Service Worker 作用域中可用的相同值
  • 高熵值getHighEntropyValues() 返回与所有其他信号一致的值

配置和用法

标准配置文件用法

对于大多数用例,配置文件会处理一切:

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

带版本对齐的品牌覆盖

切换品牌时,对齐版本号:

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

Playwright 验证示例

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 context = await browser.newContext();
  const page = await context.newPage();
  await page.goto('https://example.com');

  // 验证 UA 字符串
  const ua = await page.evaluate(() => navigator.userAgent);
  console.log('User-Agent:', ua);

  // 验证低熵 Client Hints
  const brands = await page.evaluate(() =>
    navigator.userAgentData.brands.map(b => `${b.brand} v${b.version}`)
  );
  console.log('Brands:', brands);

  // 验证高熵 Client Hints
  const highEntropy = await page.evaluate(async () => {
    return await navigator.userAgentData.getHighEntropyValues([
      'platformVersion', 'architecture', 'bitness',
      'fullVersionList', 'model'
    ]);
  });
  console.log('Platform:', highEntropy.platform);
  console.log('Platform Version:', highEntropy.platformVersion);
  console.log('Architecture:', highEntropy.architecture);
  console.log('Bitness:', highEntropy.bitness);
  console.log('Full Version List:', highEntropy.fullVersionList);

  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-config-browser-brand=edge',
    ],
    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)
  );
  console.log('User-Agent:', ua);
  console.log('Brands:', brands);

  await browser.close();
})();

验证

配置 UA 和 Client Hints 后,验证对齐情况:

  1. 检查 navigator.userAgent 包含正确的浏览器名称和版本
  2. 验证 navigator.userAgentData.brands 包含正确的品牌令牌
  3. 确认 Sec-CH-UA 头与 JavaScript 报告的品牌匹配
  4. 测试 getHighEntropyValues() 获取正确的平台、架构和版本信息
  5. 验证 Web Worker 上下文中的一致性

常见检查要点:

  • Windows 11 对 Windows 10Sec-CH-UA-Platform-Version"15.0.0" 开始表示 Windows 11。较低值表示 Windows 10。该值必须与 User-Agent 的 Windows 版本字符串匹配。
  • 品牌令牌排序:每个品牌有特定的顺序。检查 GREASE 令牌、Chromium 令牌和品牌令牌是否以正确的顺序出现。
  • 版本号对齐:UA 字符串中的主版本号应与 Sec-CH-UA 品牌令牌中的主版本号匹配。

最佳实践

  1. 优先使用配置文件而非手动配置。 配置文件从真实浏览器中采集完整、一致的 UA/Client Hints 配置。手动配置需要仔细的版本对齐。

  2. 不要使用 Playwright/Puppeteer 的 UA 覆盖。 这些框架级覆盖只改变 UA 字符串,不改变 Client Hints。使用 BotBrowser 配置文件时,你不需要它们。

  3. 保持版本真实。 使用最近的、当前的浏览器版本。过时的版本不常见,会引起注意。

  4. 对齐品牌特定版本。 使用 --bot-config-browser-brand=edge 时,将 --bot-config-brand-full-version 设置为对应 Chromium 主版本的真实 Edge 版本。

  5. 使用指纹验证工具进行测试。 每次配置更改后验证所有 UA 和 Client Hints 信号是否对齐。

  6. 定期更新配置文件。 浏览器版本变化频繁。使用与大多数用户版本匹配的当前配置文件。

常见问题

BotBrowser 是否处理 UA 缩减(Chrome 的精简 User-Agent 字符串)? 是的。BotBrowser 配置文件反映其所代表浏览器版本的实际 UA 字符串格式,包括任何 UA 缩减更改。

我可以为每个浏览器上下文设置不同的 UA 值吗? 每个上下文的 UA 自定义可通过 Playwright 的 userAgent 选项实现,但这只改变 UA 字符串。要获得完整的 Client Hints 一致性,请使用具有不同配置文件或品牌设置的单独浏览器实例。

如果我设置了 --user-agent 但没有 Client Hints 标志会怎样? BotBrowser 将使用自定义 UA 字符串,但从配置文件派生 Client Hints。如果自定义 UA 字符串与配置文件的 Client Hints 不一致,可能会出现不匹配。最好使用占位符语法配合相应的 --bot-config-* 标志。

navigator.userAgentData 在 Worker 中工作吗? 是的。BotBrowser 确保 navigator.userAgentData 在主线程、Web Worker 和 Service Worker 中返回一致的值。

BotBrowser 如何处理 GREASE 令牌? BotBrowser 生成与每个品牌和版本的真实浏览器实例中观察到的模式匹配的 GREASE 令牌。GREASE 格式、版本号和位置都是正确的。

我可以使用包含特殊字符的自定义 UA 字符串吗? 可以。--user-agent 标志接受任意字符串。使用 {platform-version} 等占位符时,它们会被替换为对应标志的值。

getHighEntropyValues() 是否受用户同意影响? 在标准 Chromium 中,getHighEntropyValues() 返回一个 Promise,该 Promise 解析为请求的值。BotBrowser 配置文件包含来自源浏览器的所有高熵值,因此 Promise 解析时返回一致的、配置文件定义的数据。

Sec-CH-UA-WoW64 头呢? BotBrowser 包含平台的所有标准 Client Hints 头。WoW64 相关的提示在适用的 Windows 配置文件中会正确设置。

总结

User-Agent 字符串和 Client Hints 是浏览器身份的网络级基础。BotBrowser 通过采集真实浏览器配置的配置文件和提供运行时自定义的 CLI 标志来管理两者。所有信号,从 HTTP 头到 JavaScript API 到 Worker 上下文,都自动保持一致和对齐。

品牌身份控制请参阅浏览器品牌切换。地理身份请参阅时区、地区和语言配置。完整的身份隔离请参阅多账户浏览器隔离

#User-Agent#Client Hints#Identity#Ua-Ch#Privacy

让 BotBrowser 从研究走向生产

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