全站 UI 革新正在进行中,网页可能不稳定或者存在问题。如硬刷新 (Ctrl + Shift + R) 后仍存在问题,可等待后续更新或向我发送反馈。

User-Agent Client Hints API 是一个实验性的 Web API,从 MDN 的文档看来,它提供了十分精简的 UA 标识,在移动端的区分上,使用一个简单的 Boolean 值。看起来 Google 的工程师确实办了件好事,但 Apple 和 Mozilla 的工程师不这么想。这一从 Chromium 90 起就得到支持的 Web API,至今仍不被 WebKit 和 Gecko 引擎接受,它已在 Limited Avaliability 阶段停滞近五年,未来也不知道什么时候能落地。

缘由

这两天重构主站,为了适配 swup,顺带着重构了整个 js。在给 UAreader 页面的 js 翻新的时候,VSCode 对navigator接口的几个 UA 属性都画了删除线,这表明新的 Web 标准已经不推荐使用这些属性,并且未来会逐步弃用它们。

被画了删除线 这几个属性都被划去

所以,我的第一反应是,赶紧找个替代。

新的 API

我确实找到了一个看起来像是它们后继者的一个 API,也就是User-Agent Client Hints API用户代理客户端提示 API」。它提供了一个NavigatorUAData接口,可以返回实例对象navigator.userAgentData的三个只读属性:brandsmobileplatform,分别返回浏览器品牌、是否为移动端(布尔值)以及当前设备的操作系统。看起来还不错。

但是当我检查兼容性的时候,我发现这个 API 目前正处于Limited Avaliability 阶段。也就是说,目前最新版本的三大浏览器引擎里还有没支持这个 API 的。这完全不能用嘛!然而兼容性差本身并不是问题的关键。兼容性表格显示,目前(现在是 3 月 8 号)只有使用 Chromium 项目的浏览器对这一 API 提供了支持,而支持的起始版本居然是Chromium 90。作为对比,现在的 Chromium 大版本号已经来到 146。

虽然向来 WebKit 和 Gecko 跟进新标准落后于使用 Blink 引擎的 Chromium,但是从 21 年 4 月到现在将近五年时间,其他两家一直不跟进肯定是不正常的。所以,我打算水一篇文章满足一下自己的好奇心,解答一下为什么 Safari 和 Firefox 对这项新 API 如此抗拒。

同时,终结一下网站没有内容产出的历史。

UA 隐私问题引发的争端

UA 隐私问题现状

在摆出三方观点之前,我们有必要了解一下工程师们为什么要在 UA 问题上死磕。

我的电脑上 Edge 的 UA 我的电脑上 Edge 的 UA

通过 UA 识别工具,可以看到 UA 实际上由五部分组成:

其中一部分 对应图里 含义
兼容性令牌 Mozilla/5.0 Netscape 网景公司 Mozilla Suite 1.0 的 UA,早期浏览器彼此强兼的产物。如果想了解推荐去搜搜看
(平台信息) (Windows NT 10.0; Win64; x64) 操作系统内核、CPU 架构、位宽
引擎信息 AppleWebKit/537.36 渲染引擎版本
(兼容性标记) (KHTML, like Gecko) KHTML 致敬老祖,like Gecko 通常被认为是历史遗留问题
浏览器标识/版本 Chrome/146.0.0.0 Safari/537.36 Edg/146.0.0.0 浏览器版本

可以看出来现在的 UA 里面包含的信息确实太过详细:CPU 架构这类信息,网站明明没必要知道;像Mozilla/5.0这种兼容性标记,更是完全没用;Windows 上的 Edge 既没用 Gecko 引擎,也不是 WebKit 浏览器,但 UA 里还是莫名其妙地出现like GeckoAppleWebKit等等标记,确实有够乱的。

这么明摆着的问题,负责开发浏览器引擎的工程师们很早就意识到了。在 2019 年 9 月 19 日,W3C Privacy Interest Group(万维网联盟隐私利益小组,简称 PING)组会上就已讨论到 User-Agent 问题。会议记录中名为 Nick 的研究员(他其实是 Nick Doty,PING 的联合主席。值得注意的是,当时他并不在本次会议的与会者名单上)说:

I like the idea of talking about listing the highest priorities an going down the list. On that 2018 paper: font enumeration, user agent strings, canvas. Not sure we want to do something on canvas, hope we make progress on fonts. User Agent strings has some entropy and it seems to be getting worse. Can we freeze them? Use client-hints to make user agent details opt-in? Would be good to have the list and start picking off pieces.

译文:我喜欢先列出最优先事项再依次解决它们。(此处 an 疑似 and 错写)那份 2018 年的报告(列出了)字体枚举、用户代理字符串和 canvas 画布(的问题)。我不确定我们是不是应该整整 canvas,(不过我)希望在字体问题上搞点成果。(事实上)UA 字符串现在已经有点复杂了,而且似乎在变得越来越复杂。我们能冻结它们吗?利用客户端提示让 UA 字符串的详细信息变为可选项?最好能(把我们要做的)列成清单,然后一个个解决。

Nick 提到了熵(entropy)的问题。熵是用来衡量复杂度的单位,熵越高复杂度越高。能够理解,Nick 的意思是,User-Agent 越是复杂和详尽,用户设备的唯一性越是凸显,用户越容易被唯一的设备标识符(用户指纹)追踪。所以,必须对 UA 字符串动刀。这就是「UA Reduction」,它的目标是从 UA 中移除过分详细和历史遗留的那部分信息,泛化用户指纹,从而降低用户在互联网中被标记的风险,并以此倒逼网站为所有平台上的用户提供尽可能相同的浏览体验。

然而这之后各引擎的意见出现了分歧。分歧的产生并不是因为有谁不认为 UA 存在重大的隐私风险,而是他们的隐私理念各不相同。在不同的隐私理念和其他因素的影响下,三大浏览器引擎的「UA Reduction」行动走出了不同的路径。

他们为什么要打架?

Google 的工程师在这一会议上就已表示「我们正在开始在 Chrome 中实现」,而他们的方案就是 User-Agent Client Hints API(后面也简称 UA-CH)。他们认为,应该在早期通过 flags 逐步推广 UA-CH,随着时间推移,足够多的人使用新的 API 之后,削减 UA 的不必要信息(熵)。也就是说,Google 方面认为,应该通过逐步推广新的 UA-CH 来取代旧的 UA API,从而渐进式地完成 UA Reduction。这么做看起来似乎没啥问题,但却拿到了 Mozilla 的「neutral」(中立票)和 WebKit 相关 issue 的「block」(阻塞)。

那么,UA-CH 为什么没令另外两家满意?看看 Google 做了啥。

在第二章节提到,UA-CH 可以返回浏览器品牌、是否移动端和设备操作系统的名字(不包括版本号,比如 Windows)三个只读属性。然而这三个属性并不是 UA-CH 能拿到的全部,通过getHighEntropyValues()方法,网页能够请求跟 UA Reduction 实施之前的原 UA 差不多详细的所有高熵信息,包括处理器平台架构及其位数、浏览器详细版本(比如 Chrome/146.0.3856.59。这甚至比现在使用的 UA 更为详细,因为从 Chromium 101 开始,UA 里的浏览器版本号已经默认把小版本的数字全部置 0)、移动设备型号,甚至包括当前 Windows 是否正在使用 WoW64。而网站为了拿到这些高熵信息,所付出的代价仅是一个 Promise 请求。网站甚至不需要像以前一样对着正则匹配提取 UA,现在拿到的对象属性直接给一一对应好了,比以前都要省事。

用户隐私换体验?

看到这里我是真气笑了,Mozilla 给出去一个中立还是脾气太好了,可以说,UA Reduction 到 Google 这里已经直接变成助推隐私信息利益化演进的手段。Google 的行径彻底背离 UA Reduction 行动的初衷,将原本利用 UA 信息标记用户指纹的灰色行径以推出新 API 的方式洗白,毫无疑问,这是 Google 正在利用自己既当裁判员又当选手的身份对自家 Google Ads 业务的变相支持。这就是 Apple 和 Mozilla 拒绝在其引擎中实现 UA-CH 近五年的原因。

然而,WebKit 和 Gecko 面临一个残酷的现实:网站兼容性。

根据 StatCounter 的数据,截止 2026 年 2 月,仅 Chrome 的市场份额就已高达 68.98%,若计算其他使用 Chromium 开源项目的浏览器,保守估计 Chromium 浏览器的市场份额已在 78% 以上,处于无可置辩的绝对领导地位。借助 UA-CH 和 Privacy Sandbox,Google Ads 实现了比之前更省事且精准的用户指纹追踪,令广告投放商们爽爽赚米,于是使用 UA-CH 的网站越来越多。在压倒性的市场优势地位支配下,Apple 率先做出了妥协。

2025 年 8 月 16 日,WebKit 开源项目的 Pull Request #48790 被关闭,标志着 WebKit 正式将 UA-CH 合并进 WebKit 主分支,兴许今年秋季便可随着正式版 Safari 发布而得到正式支持。当然,WebKit 对 UA-CH 抵触依旧。负责 WebKit 开发的工程师 Cole Carley 和 Brent Fulgham 说:

Cole Carley: This patch populates the userAgentData data structure to be used for quirking. ...Sensitive information is denied such as model and formFactors.

Cole Carley:这个补丁用于填补 userAgentData 数据结构体来解决兼容性问题。...诸如设备型号和尺寸之类的敏感信息是不被允许(获取)的。

Brent Fulgham: ...We should file a follow-up Bugzilla to make sure that this API respects the user's ability to change the User Agent (e.g., in the Safari Developer menu). If someone changes the UA for loading a site, this API should report the same things.

Brent Fulgham:...我们应该在 Bugzilla 上提交一个后续意见,确保这个 API(UA-CH) 尊重用户自由更改 UA 的能力(比如在 Safari 开发者选项里改)。用户怎么改的,UA-CH 就应该怎么显示。

很显然 Apple 的工程师很支持在 Safari 上伪造高熵 UA。这点我举双手双脚赞成。

另一边,也已经有人在 Bugzilla 提出支持 UA-CH 的要求,不过目前来看 Mozilla 的动作还是不太明显。

标准不一致,我们用什么?

是啊,用什么?

一句话总结,现在没得用。站在个人开发者的立场,我认为这个 API 对我们的影响微乎其微。

首先,做个人网站最看重的是跨平台、跨引擎的一致体验。这是我在早期就引入 Autoprefixer 的主要原因之一,也是绝大多数开发者在个人博客搭建时使用成熟网页框架的考量。UA-CH 的兼容性令人堪忧,理论上非欧盟经济区的苹果设备都不能保证与 Chromium 浏览器上一致的浏览体验,更不要说 Firefox。我的观点是,既然不能保证跨平台一致性体验,那么必须慎用。

其次,如果建博客的没有引入 Google 广告或者没有视奸用户的爱好,那么 UA-CH 的用处是不明显的。我之前说过,站在个人开发者的立场,最看重的是跨平台、跨引擎的一致体验。仅就个人网站而言,既然是一致体验,那刻意的去拿 UA 有什么用呢?可能有人会说,需要 UA 区分移动端和桌面端来分别做 UI 和交互适配,但这其实是一个伪需求。移动端和桌面端适配本质上是大小屏(宽窄屏)适配,而这是可以通过媒体查询和容器查询轻松完成的。总不能说我拿到一个 tablet(比如 Matepad Pro 13.2''),tablet 在 UA-CH 里是 mobile 设备,然后我拿着移动端的 UA 给这个超大的平板硬上移动端的 UI,这很明显是不合适的。包括现在新形态的设备在变多,像 2in1、fold 这类设备,可能在使用过程中就会发生形态和 UA 变化,那这个时候依赖 UA 的交互看起来是不够灵活的。(看起来还是媒体查询更厉害啊)

再次,旧 API 还能用。制定 Web 标准的人对兼容性的追求可谓病态,否则Mozilla/5.0之流也不会一直留在旧 UA 里。现在的 UA 实际上处于一个青黄不接的状态,旧的 API 正在等待或已经弃用,新的 API 迟迟不落地。在这种情况下,旧的 API 绝不可能被一删了之。我的观点是,就算旧 API 要从 Web 标准里移除,那也得是 UA-CH 拿到 Baseline Widely available 徽章之后的事情了。

可能有的网站跟我一样做了一个专门测 UA 的网页工具,那其实没什么可以说的了,只要记得写一个if (navigator.userAgentData)做一个 fallback 就问题不大。

不统一的标准还能叫标准吗?

修订历史