⌘K 切换工具
NETWORK · HTTP

UserAgent解析器

从用户代理字符串检测浏览器和操作系统。

local
user-agent-parser
§01 关于此工具

概述

User-Agent 字符串是浏览器对自己的描述,也是 HTTP 里最不值得信任的字段之一——一部分 原因是客户端会刻意说谎,另一部分原因是三十年的兼容性权宜之计,已经让每一个字符串都 同时声称自己是好几个浏览器。

这个工具会报告浏览器与它的版本、操作系统与它的版本、一个设备类型,以及这个字符串 是否把自己声明成了自动化程序。

使用方法

  1. 粘贴一个 User-Agent 字符串。页面加载时会自动填入你自己的。
  2. 读出浏览器、操作系统、设备和机器人判定结果。

为什么判定顺序就是问题的全部

看一个 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」——一个否定式 判断,很容易被漏掉。

本工具会在检查手机标记之前,先检查 iPadTablet 以及「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-UASec-CH-UA-PlatformSec-CH-UA-Mobile),它默认只发送一小组值, 更多信息需要服务器主动索取。

实际后果是:UA 解析器会随时间推移变得越来越不准,而这是有意为之的。把「浏览器主版本 号」和「OS 系族」当作持久可用的信号,把任何更精确的东西当作总有一天会不再送达的额外 赠品。浏览器指纹 工具展示的正是这轮精简想要保护的其他 那些属性。

示例

  • 分析统计里 Chrome 占比高得不合理。 检查你的解析器是不是把 Chrome 放在了 Edg 之前。仅这一个顺序 bug 就会在浏览器之间挪动好几个百分点的流量。
  • 一张没有复现步骤的支持工单。 从报告者 UA 里取出的 OS 和浏览器版本,通常就足以 把范围缩小。
  • 从日志里过滤机器人。 自报身份的那些很好办;但要明确说清这个数字是下界,不是 实际计数。
  • 审查一个老的浏览器版本门禁。 基于 UA 写的版本比较本来就已经不可靠,而且每一轮 精简都会让它更糟。把它换成特性检查。

说明

带下划线的版本号——macOS 和 iOS 会报 10_15_7——会被规范化成点号。这个格式差异在 UA 里纯属外观,不携带任何含义。

Unknown 表示没有任何模式匹配上,而对来自小众浏览器、嵌入式 WebView、HTTP 客户端库、 或者一个产出了自相矛盾组合的伪装扩展的字符串来说,这是一个真实的答案。

机器人检查会寻找 botcrawlspiderslurpcurlwgetpythonheadless。它描述的是客户端愿意承认什么,不是一项安全控制。凡是真正要紧的场景,都 应当在服务端用速率限制和挑战来强制执行,因为 UA 只是客户端自己挑选的一个字符串。 隐私政策 说明了本站的 API 是怎么做的。

FAQ
字符串会被发送到什么地方吗?
不会。判定就是页面内的正则匹配。没有任何东西离开你的浏览器,页面加载完成后离线也能用。
为什么我的 Chrome UA 里还写着 Safari 和 Mozilla?
历史兼容包袱。每个浏览器都声称自己是 Mozilla/5.0,基于 Chromium 的浏览器为了 WebKit 时代的特性探测而声称 Safari,而 Edge、Opera 和三星浏览器又在这之上再声称 Chrome。这个字符串是一叠层层堆起来的兼容性谎言——所以解析顺序比正则本身更要紧。
为什么现代 iPad 被报成 macOS?
因为它发出来的就是这个。自 iPadOS 13 起,iPad 上的 Safari 默认请求桌面版站点,它的 UA 与 Mac 无法区分。真正的破绽是 maxTouchPoints,而它根本不在 UA 里——所以任何 UA 解析器都不可能把这件事判对。
生产环境里能用它做特性探测吗?
不行。要探测特性,不要探测浏览器——写 `if ('share' in navigator)`,而不是比较版本号。UA 解析适用于分析统计、支持工单分流和日志分析,也就是你在描述流量、而不是在决定行为的场合。
机器人标记有多可靠?
它只能抓住诚实的机器人,别的一个都抓不到。Googlebot、curl 和 python-requests 都会自报身份。一个想混进来的爬虫会一字不差地照抄真实浏览器的字符串,任何基于 UA 的检查都永远看不见它。