UserAgent解析器
从用户代理字符串检测浏览器和操作系统。
概述
User-Agent 字符串是浏览器对自己的描述,也是 HTTP 里最不值得信任的字段之一——一部分 原因是客户端会刻意说谎,另一部分原因是三十年的兼容性权宜之计,已经让每一个字符串都 同时声称自己是好几个浏览器。
这个工具会报告浏览器与它的版本、操作系统与它的版本、一个设备类型,以及这个字符串 是否把自己声明成了自动化程序。
使用方法
- 粘贴一个 User-Agent 字符串。页面加载时会自动填入你自己的。
- 读出浏览器、操作系统、设备和机器人判定结果。
为什么判定顺序就是问题的全部
看一个 Microsoft Edge 的字符串:
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36
(KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0
它同时声称自己是 Mozilla、AppleWebKit、Chrome、Safari 和 Edge。一个先去检查
Chrome 的解析器会把它报成 Chrome——而世上有相当大一批分析统计数据是错的,原因就
精确地落在这一点上。
规则是:先检查最具体的标记。Edg/ 先于 Chrome/,OPR/ 先于 Chrome/,
SamsungBrowser/ 先于 Chrome/,而 Chrome/ 先于 Safari——因为 Chromium 也声称
Safari,而 Safari 不会声称 Chrome。
版本号同样必须取自那个具体的标记。Edge 120 里的 Chrome/120.0.0.0 是 Chromium 的
版本,不是 Edge 的版本,两者是会分叉的。
字符串的解剖
一旦你知道几乎每个标记都是出于历史原因而不是描述目的存在的,读 UA 就容易多了。
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36
(KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36
Mozilla/5.0—— 每个浏览器都这么声称。1990 年代服务器会先检查有没有 「Mozilla」再决定是否发送框架页,于是所有人都开始这么声称,而后再也没人能停下来。- 括号里的那一段 —— 平台细节。OS 名称与版本、CPU 架构,在移动端还有设备型号。 这正是浏览器现在正在截短的部分。
AppleWebKit/537.36 (KHTML, like Gecko)—— 自 2013 年起,整个 Chromium 都把 它冻结在 537.36。它是一个常量,不是版本。KHTML, like Gecko又声称与另外两个引擎 同源。Chrome/120.0.0.0—— Chromium 的主版本号。次要部分是刻意置零的。Safari/537.36—— 与 WebKit 标记一致。它存在的目的是让那些检查 Safari 的代码 继续能跑。
真正有用的信息集中在其中一两个标记里,其余全都是兼容性沉积下来的东西。凡是把这个 字符串当成一份描述、而不是当成层层叠加的一堆「声称」来处理的解析器,最终一定会判错。
设备类型的判定
设备类型是从标记推断出来的,而其中两个要紧的信号都反直觉:
- iPad 会发送
Mobile。 iPad 的 UA 里包含Mobile/15E148,所以检查Mobi会 匹配上它。必须先检查iPad,否则所有平板都会被报成手机。 - Android 平板不带
Mobile。 Google 的约定是手机上出现Mobile标记、平板上 不出现。于是一个 Android 平板就是「有Android而没有Mobile」——一个否定式 判断,很容易被漏掉。
本工具会在检查手机标记之前,先检查 iPad、Tablet 以及「Android 且无 Mobile」,
因此平板会被归类为平板。
任何解析器都修不好的是桌面模式的 iPad。自 iPadOS 13 起,iPad 上的 Safari 默认发送
macOS 的字符串;唯一可靠的区分手段是 navigator.maxTouchPoints,而它不在 UA 里。
如果平板识别对你的应用很重要,就在客户端读取触点数,而不是去解析字符串。
这个字符串正在被刻意缩短
浏览器正在主动减少 UA 暴露的内容,因为帮助分析统计的那些细节,同样能用来做指纹。
Chrome 已经把次版本号冻结为 0.0.0,并且精简了 OS 版本。Safari 多年来一直报告一个
固定的 OS 版本。navigator.platform 已被废弃。替代方案是 User-Agent Client Hints
(Sec-CH-UA、Sec-CH-UA-Platform、Sec-CH-UA-Mobile),它默认只发送一小组值,
更多信息需要服务器主动索取。
实际后果是:UA 解析器会随时间推移变得越来越不准,而这是有意为之的。把「浏览器主版本 号」和「OS 系族」当作持久可用的信号,把任何更精确的东西当作总有一天会不再送达的额外 赠品。浏览器指纹 工具展示的正是这轮精简想要保护的其他 那些属性。
示例
- 分析统计里 Chrome 占比高得不合理。 检查你的解析器是不是把
Chrome放在了Edg之前。仅这一个顺序 bug 就会在浏览器之间挪动好几个百分点的流量。 - 一张没有复现步骤的支持工单。 从报告者 UA 里取出的 OS 和浏览器版本,通常就足以 把范围缩小。
- 从日志里过滤机器人。 自报身份的那些很好办;但要明确说清这个数字是下界,不是 实际计数。
- 审查一个老的浏览器版本门禁。 基于 UA 写的版本比较本来就已经不可靠,而且每一轮 精简都会让它更糟。把它换成特性检查。
说明
带下划线的版本号——macOS 和 iOS 会报 10_15_7——会被规范化成点号。这个格式差异在 UA
里纯属外观,不携带任何含义。
Unknown 表示没有任何模式匹配上,而对来自小众浏览器、嵌入式 WebView、HTTP 客户端库、
或者一个产出了自相矛盾组合的伪装扩展的字符串来说,这是一个真实的答案。
机器人检查会寻找 bot、crawl、spider、slurp、curl、wget、python 和
headless。它描述的是客户端愿意承认什么,不是一项安全控制。凡是真正要紧的场景,都
应当在服务端用速率限制和挑战来强制执行,因为 UA 只是客户端自己挑选的一个字符串。
隐私政策 说明了本站的 API 是怎么做的。