User-Agent 和 Client Hints (UA-CH):完整控制指南
User-Agent 字符串、Client Hints 头和 navigator.userAgentData 如何协同工作,以及如何在引擎级别一致地管理它们。
简介
User-Agent 字符串几十年来一直是浏览器身份识别的基石。但现代浏览器身份系统更加复杂。Client Hints (UA-CH) 通过 HTTP 头和 JavaScript API 提供关于浏览器的结构化数据。Sec-CH-UA 头、navigator.userAgentData 和 getHighEntropyValues() 都以标准化格式暴露品牌、平台、版本和设备信息。当这些值与传统的 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.userAgent和navigator.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:设备是否为移动端。例如:?0Sec-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 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 令牌
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 令牌。
一致性要求
对于可信的浏览器身份,以下各项都必须对齐:
User-Agent头与navigator.userAgent匹配Sec-CH-UA中的品牌令牌与navigator.userAgentData.brands匹配Sec-CH-UA-Platform中的平台与navigator.userAgentData.platform匹配- UA 字符串中的主版本号与
Sec-CH-UA品牌令牌中的版本匹配 Sec-CH-UA-Full-Version-List中的完整版本与getHighEntropyValues().fullVersionList匹配- 平台版本对于声称的操作系统是合理的(例如 Windows 11 报告
"15.0.0"或更高) - 架构和位数匹配平台(例如 Windows 为
x86/64,M 系列 Mac 为arm/64) - 所有值在主线程、Worker 和 HTTP 头中相同
常见方案及其局限性
框架级 UA 覆盖
Playwright 和 Puppeteer 提供 UA 覆盖选项:
// Playwright
const context = await browser.newContext({
userAgent: 'Custom UA String'
});
// Puppeteer
await page.setUserAgent('Custom UA String');
这些改变了 navigator.userAgent 和 User-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-Agent和Sec-CH-UA-*头 - 主线程 JavaScript:
navigator.userAgent、navigator.userAgentData - Web Worker:Worker 上下文中的
navigator.userAgent和navigator.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 后,验证对齐情况:
- 检查
navigator.userAgent包含正确的浏览器名称和版本 - 验证
navigator.userAgentData.brands包含正确的品牌令牌 - 确认
Sec-CH-UA头与 JavaScript 报告的品牌匹配 - 测试
getHighEntropyValues()获取正确的平台、架构和版本信息 - 验证 Web Worker 上下文中的一致性
常见检查要点:
- Windows 11 对 Windows 10:
Sec-CH-UA-Platform-Version从"15.0.0"开始表示 Windows 11。较低值表示 Windows 10。该值必须与 User-Agent 的 Windows 版本字符串匹配。 - 品牌令牌排序:每个品牌有特定的顺序。检查 GREASE 令牌、Chromium 令牌和品牌令牌是否以正确的顺序出现。
- 版本号对齐:UA 字符串中的主版本号应与
Sec-CH-UA品牌令牌中的主版本号匹配。
最佳实践
-
优先使用配置文件而非手动配置。 配置文件从真实浏览器中采集完整、一致的 UA/Client Hints 配置。手动配置需要仔细的版本对齐。
-
不要使用 Playwright/Puppeteer 的 UA 覆盖。 这些框架级覆盖只改变 UA 字符串,不改变 Client Hints。使用 BotBrowser 配置文件时,你不需要它们。
-
保持版本真实。 使用最近的、当前的浏览器版本。过时的版本不常见,会引起注意。
-
对齐品牌特定版本。 使用
--bot-config-browser-brand=edge时,将--bot-config-brand-full-version设置为对应 Chromium 主版本的真实 Edge 版本。 -
使用指纹验证工具进行测试。 每次配置更改后验证所有 UA 和 Client Hints 信号是否对齐。
-
定期更新配置文件。 浏览器版本变化频繁。使用与大多数用户版本匹配的当前配置文件。
常见问题
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 上下文,都自动保持一致和对齐。
品牌身份控制请参阅浏览器品牌切换。地理身份请参阅时区、地区和语言配置。完整的身份隔离请参阅多账户浏览器隔离。