跨平台浏览器 Profile:每台宿主上的同一个身份
为什么浏览器身份应由 profile 而不是宿主操作系统决定,以及如何验证它在 Windows、macOS 和 Linux 宿主上保持一致。
BotBrowser Team
跨平台比较只有在目标身份、profile 修订、启动参数和宿主记录被一起保留时才有可比性。BotBrowser 将 profile 用作身份来源;它并不保证每台宿主或每个站点都有相同行为。
TL;DR
在宿主之间比较固定记录,隔离已经变化的版本或参数,并把差异作为发布决策,而不是 profile 保证。
内容
- User-Agent 字符串不等于身份
- profile 必须保持一致的信号族
- 宿主、目标与文档记录的支持矩阵
- 比较宿主并调查差异
- 跨平台 profile 与 Per-Context 运行
- BotBrowser 能做什么,边界在哪里
- 结论
User-Agent 字符串不等于身份
浏览器身份不只是一个请求头。网站可以读取平台名称、浏览器品牌和版本、已安装字体、图形行为、屏幕尺寸、语言列表、时区和媒体能力,并且可以把这些值相互比对。一个浏览器如果声明 Windows 的 User-Agent,而字体、屏幕和图形行为却来自 Linux 服务器,呈现出的就是一幅混杂的画面。这种混杂对依赖 profile 的人来说是隐私风险,对团队来说则是支持问题,因为团队必须解释为什么同一个工作流在两台机器上表现不同。BotBrowser 可以让所选配置的身份取值在不同宿主操作系统之间保持一致,但不能改变站点或服务器如何对待这个身份。
这种需求很实际。一个团队可能同时使用 Linux 服务器做规模化运行、macOS 工作站做开发、Windows 桌面承担桌面工作流,以及用 Android 目标身份验证移动流量。支持人员需要在不搭建硬件实验室的情况下复现客户案例,QA 在批准发布之前需要一个稳定的基线。如果浏览器身份跟随宿主,这些角色看到的结果就会略有不同;如果它跟随 profile,他们就可以放心地比较结果。
User-Agent Client Hints 让这一点更清楚。MDN 把 User-Agent Client Hints API 描述为通过请求头、响应头和 JavaScript 接口暴露浏览器与平台信息的方式:默认只发送一小组值,更详细的值只有在服务器请求时才会返回。这些值需要与 User-Agent 字符串一致,彼此一致,也要与 profile 的其余部分一致。只改字符串而让结构化的值保持宿主默认,恰恰会造成一致的身份应当避免的那种不匹配。
这就是 profile 应当成为身份来源的原因。profile 是一个文件,记录了整套身份的取值,因此宿主操作系统不再是浏览器被问到的每个问题的默认答案。BotBrowser 的跨平台 Profile 文档这样描述该模型:身份相关的表面来自 profile 数据,包括 User-Agent、屏幕、字体、GPU 和语言栈,同时宿主差异受到约束,使 profile 仍是主要来源。
一个具体的例子可以说明这意味着什么。假设一个 Windows 目标 profile 运行在 Linux 服务器上。平台名称、结构化的品牌值、字体集合、屏幕指标和 GPU 描述都应当描述一台 Windows 桌面,即使底层机器是 Linux 服务器。工作流到达页面时,表现也应当与真实的 Windows 目标一致。只要有一个信号族仍然反映 Linux 宿主,身份就只被部分应用,而这正是跨宿主比较应当揭示的缺口。
profile 必须保持一致的信号族
比较宿主前,记录 userAgent、platform、brands、screen.width、screen.height、devicePixelRatio、languages、locale 和 timeZone。
按信号族而不是单个属性来思考会更方便。对于所选的目标平台,profile 需要让下列信号族彼此保持一致:
- 平台与浏览器品牌:User-Agent 字符串、结构化的 Client Hints 值以及请求头中声明的品牌,应当指向同一个平台和同一个浏览器版本。
- 屏幕与设备指标:分辨率、色深、像素比和触控支持应当符合目标的设备类别,无论是桌面显示器还是 Android 手机。
- 字体与文本渲染:已安装的字体集合和文本排版方式应当跟随目标平台,适用时也包括东亚文本。
- 图形行为:GPU 描述以及 canvas 和 WebGL 的渲染行为应当保持在 profile 所描述的设备类别之内。
- 语言、区域与时间:语言列表、区域格式和时区应当彼此一致,并与工作流要代表的地区一致。
- 媒体与存储能力:编解码器、内存类别和类似的能力值对目标设备来说应当是合理的。
| 信号族 | 比较宿主前记录 | 出现以下情况即视为不一致 |
|---|---|---|
| 浏览器身份 | userAgent、platform、brands | 各字段声明的目标互不相同 |
| 显示 | screen.width、screen.height、devicePixelRatio | 某个值描述的是另一类设备 |
| 区域设置 | languages、locale、timeZone | 各值指向互不兼容的地区 |
这份清单是一张该比较什么的地图。每个信号族都可以在较高层面上审阅,看页面是否按预期工作,以及代表性宿主上的值是否与团队批准的基线一致。要发现 Windows 目标 profile 报告了 Linux 平台,或者 Android 目标 profile 仍显示桌面屏幕,并不需要逐个读取每一个底层值。
MDN 关于 User-Agent Client Hints 的指南说明了为什么第一个信号族需要小心。默认会发送一小组值,例如浏览器品牌、移动标记和平台名称。更详细的值,例如平台版本、架构和设备型号,只有在服务器请求时才会返回。一致的 profile 需要对默认值和被请求的值给出前后一致的答案,这样网站收到的答案就不取决于它先问了哪个问题。
字体值得单独一提,因为在 profile 接管之前,它们直接来自宿主。字体一致性文章解释了为什么字体行为必须跟随目标平台,而 CJK 字体渲染文档描述了东亚排版的一致性,适用于中文、日文或韩文文本在不同宿主上显示不同的情况。
宿主、目标与文档记录的支持矩阵
两个术语有助于把规划理清。宿主是运行浏览器的机器和操作系统。目标是 profile 所描述的平台。在由 profile 驱动的模型中,两者可以有意不同:Windows 目标 profile 可以在开发期间运行于 macOS 笔记本,在生产环境运行于 Linux 服务器。
选择目标是产品决策,而不是宿主决策。先确定工作流要代表哪个平台,选取匹配的 profile,再按成本和便利性选择宿主。文档列出了受支持的组合,每种 profile 目标在每类宿主上都受支持。
| Profile 目标 | Windows 宿主 | macOS 宿主 | Linux 宿主(ENT Tier1) |
|---|---|---|---|
| Windows profile | 支持 | 支持 | 支持 |
| macOS profile | 支持 | 支持 | 支持 |
| Android profile | 支持 | 支持 | 支持 |
其他前提条件是每台宿主上都安装了 BotBrowser,并且有 .enc 或 .json 格式的 profile 文件。Linux 和 Ubuntu 宿主需要 ENT Tier1。Android Emulation 文档把 Android 目标 profile 描述为 PRO 许可的能力,而 Android profile 测试文章展示了 Android 目标 profile 如何从桌面或服务器宿主运行。
文档中的场景沿用常规的交付路径。团队可以在 macOS 上开发、在 Linux 上部署:把一个 profile 文件放在源码管理或密钥存储中,不做修改直接部署。CI 任务可以在 Windows、macOS 和 Linux 运行器上运行同一个 profile 并比较关键输出。一组机器可以在云宿主之间迁移,而无需重新生成身份 profile。在每种情况下,启动命令中只有可执行文件路径会变化,profile 文件和启动参数保持不变。
把 profile 文件当作带版本的发布产物。把它放在源码管理或密钥存储中,为每次修订分配标识符,并在每次有宿主运行它时记录该标识符。Profile 管理文档介绍了 profile 的生命周期和版本管理。当所有宿主都从同一个位置读取同一个文件时,结果出现差异就说明问题在宿主或启动参数上,而不是某份遗留的 profile 副本。
比较宿主并调查差异
比较行包含 hostOs、botBrowserVersion、profileRevision、launchFlags、displayMode 和 result;只有 profileRevision 与 launchFlags 都相同,Windows 11、macOS 15 和 Ubuntu 24.04 的结果才可比较。
只有在有证据支撑时,一致性的说法才有用。证据来自授权测试期间一次简单的受控比较:保持输入不变,只更换宿主,并记录发生了什么。
- 固定输入。在测试记录中写下 BotBrowser 版本、profile 文件和启动参数。
- 选择代表性宿主。至少使用一台 Windows 宿主、一台 macOS 宿主和一台与生产环境相似的 Linux 宿主,包括其显示和图形配置。
- 运行一个能代表真实工作的授权工作流,从启动一直到预期的页面状态。
- 将高层信号族和页面行为与发布基线比较:平台值、屏幕值、语言与时间值、字体和渲染。
- 把截图、笔记和批准的决定放在一起保存,以便下一个版本可以与这一次比较。
用平实的语言记录你看到的内容。“工作流到达了预期的页面状态,截图与基线一致,平台、屏幕和语言值与 profile 相符”是一个可用的结果。“看起来没问题”则不是。如果工作流对启动或渲染条件敏感,就多运行几次,并保留每一次的结果。
不同角色读同一份比较有不同的原因。QA 负责人想知道候选版本是否符合已批准的基线。支持工程师想在手头的宿主上复现客户案例。隐私审阅者想确认工作流呈现的身份是 profile 所描述的身份,而不是机器带来的副作用。只要在第一次运行之前写下输入,一份共享的记录就可以服务这三类人。
Linux 宿主需要一次明确的就绪检查。Headless Server Setup 文档描述了 Linux 基线,Linux 渲染后端指南解释了渲染后端的选择如何影响图形行为和部署成本。把显示和渲染配置当作发布的前提条件,而不是上线之后才发现的细节。
同样的方法也适用于 CI 任务。文档建议在 Windows、macOS 和 Linux 运行器上运行该 profile,并比较平台值、语言、屏幕值和渲染结果等关键输出。比较只做到这个层面。某个高层信号族要么与基线一致,要么不一致,出现不一致就是发布前需要调查的理由。关于验收记录、上线责任和运行成本的更完整讨论,请阅读部署前如何评估跨平台浏览器一致性。
两台宿主结果不一致时,第一个问题是什么发生了变化。针对不同宿主输出不同的排查建议是:核对 BotBrowser 版本、profile 文件和启动参数是否相同。这三项输入能解释大多数差异,而且核对成本很低。
- 版本漂移:某台宿主运行了不同的 BotBrowser 版本。
- Profile 漂移:使用了不同的 profile 文件,或同一文件的旧副本。
- 参数漂移:开发机器和 CI 运行器的启动参数不同。
- 渲染后端:无头模式下可能出现与 GPU 相关的差异,文档指向 Headless Server Setup 指南和 GPU 模式设置。
- 字体与文本渲染:东亚文本在不同宿主上可能不同,并且有专门的指南。
- 不受支持的宿主:没有 ENT Tier1 的 Linux 宿主不在文档记录的支持矩阵之内。
把每一项当作假设,一次只改一个变量,然后重新运行同一个工作流。宿主之间出现差异,绝不是身份一致的证据;它记录的是一个仍需要有人负责的差异。同样,某台宿主上的一致结果不会自动延续到新的宿主镜像、新的 profile 包或新的浏览器版本,所以其中任何一项变化时都要重新比较。
提前决定何时停下来。出现意外的页面状态、渲染结果妨碍工作、无人能复现结果,或宿主缺少文档要求的前提条件,都是暂停上线并回到上一个已批准基线的理由。把不清楚的结果标记为无定论,而不是算作通过,并为下一次检查指定负责人和日期。当生产决策取决于答案时,明确的不确定性比虚假的信心更有用。
支持工程师可以把同样的提问顺序用于客户报告:版本、profile、参数、渲染后端,最后是宿主。每次都按同一顺序排查,结果才具有可比性,排查也更短。
地区需要单独说明。profile 提供平台身份,而区域工作流的时区、区域设置和语言可以通过启动参数显式设置,使它们彼此一致,并与 profile 一致。把这些值与其他输入一起写入测试记录,这样以后的运行就从同一个区域基线开始。日期、时间和时区在不同环境中的表现,可参阅日期时间格式化与时区可移植性。
跨平台 profile 与 Per-Context 运行
在第一个页面前,将 profileRevision、locale、timeZone 及例如 retailer-de-desktop 的标签关联到上下文,以便在另一台宿主上找到它。
需要大量身份的团队常常会问,是不是必须为每个身份启动一个浏览器。Per-Context Fingerprint 文档描述了另一种做法:在同一个浏览器实例内,为每个浏览器上下文分配独立的指纹组合,这样可以降低开销并保持账号分离。Per-Context Fingerprint 是 ENT Tier3 能力。
这两个思路解决的是同一问题的不同部分。跨平台 profile 让身份绑定到 profile 而不是宿主。Per-Context 运行让一个浏览器实例可以容纳多个这样的身份,每个身份有自己的 profile、语言和时间值以及屏幕指标。根据文档,在上下文内创建的 worker 会继承该上下文的身份。
文档还指出,决定身份的参数必须在上下文中创建第一个页面或 worker 之前设置,因为第一个页面或 worker 会固定该上下文的身份。请据此规划操作顺序,并用与单个 profile 相同的跨宿主比较来验证每个上下文。容量取决于宿主、工作负载和套餐,所以请在你打算运行的宿主上自行测量。
Per-Context 运行不会改变验证的习惯。在每类宿主上验证一组有代表性的上下文,记录每个上下文使用了哪个 profile,并比较相同的高层信号族。如果某个上下文在桌面宿主上使用 Android 目标 profile,就用 Android 的检查项而不是桌面的检查项来审阅。按上下文保存记录,也更容易判断差异属于某一个身份,还是属于整台宿主。
BotBrowser 能做什么,边界在哪里
BotBrowser 可以把所选 profile 作为 User-Agent、屏幕、字体、GPU 和语言栈的来源,因此同一个 profile 文件能够在受支持的 Windows、macOS 和 Linux 宿主上运行,团队也可以在相同版本和启动参数下比较这些宿主的结果。这样,负责批准发布的人有一个共享基线可以审阅,而不是每台机器各有一个结果。BotBrowser 不能保证每台宿主和每个网站得到相同的结果,不能替代在代表性宿主上的验证,也不控制网站如何解读浏览器信号。Linux 宿主还需要 ENT Tier1。
编写上线计划时请以这条边界为准。写明你验证了哪些宿主和目标、使用了哪个版本、profile 和参数,以及审阅了哪些结果。把这个范围之外的一切都描述为未测试。对下一位操作者来说,一份简短而准确的验收记录比一个笼统的承诺更有用。
当来源发生变化时,请重新审视计划。支持矩阵、Per-Context 要求和 Client Hints 指南都由各自的维护方更新,所以在修改上线文档中关于宿主支持或身份的表述之前,请先重新核对下面列出的来源。
结论
为每台参与比较的宿主保留一个 profile 修订和启动记录。版本、参数集合、线路、区域设置或显示模式不同都会改变比较输入;在做发布决定前记录这种变化。
公开来源
本文属于指南: Web 平台能力面:一致性复核地图