如何识别 Brave 浏览器
最近在访问 Lobste.rs 时(后面用 🦞 代替),网站会禁止 Brave 浏览器的访问。有一点我感到很困惑,因为 Brave 在隐藏用户特征方面做了很多努力,其中包括伪装用户代理信息。这让我产生了一个疑问:🦞 是如何识别出 Brave 的?其实我也在愁统计不到 Brave。
探索
利用前端 JavaScript 识别 Brave
起初,我以为 🦞 是通过前端 JS 进行识别的。因为在禁用 JS 后,我发现可以正常访问 🦞。Brave 浏览器提供了一些独特的 API,比如 Wallet,甚至还提供了一个 isBrave
函数。通过这些 API,很容易在前端检测到用户是否在使用 Brave 浏览器。
console.log(window.braveEthereum); // Brave 独有的 Wallet API
console.log(navigator.Brave.isBrave); // 检测是否为 Brave 浏览器
然而,在进一步分析中,我并未在页面发现任何 JS 代码。尤其是在未登录的情况下,🦞 不会加载任何 JS。表明这并非其识别手段。
基于链接参数移除的推断
在 🦞 相关的 Issue 中,我发现了一种基于链接参数的识别方法。Brave 的隐私保护策略之一是自动移除一些常见的跟踪参数。例如:
/detect-brave?gclid=3&fbclid=2&sub=marine
如果后端检测到 gclid
和 fbclid
等参数被移除,可以推断用户可能使用的是 Brave 浏览器。
但这种方法并不可靠。其他工具(例如 Firefox 安装 ClearURLs 扩展后)也会移除这些参数,导致误判。
通过 Client Hint 的识别
在分析请求头时,我注意到了一组没见过的 Header —— sec-ch-ua
包含 Brave,这是 Client Hint 的一部分,用于替代传统的 User-Agent 字符串。目前也只有 Chromium 系浏览器支持,估计是作为 Privacy Sandbox 的一部分,遭到了 Mozilla 和 Apple 的反对。
Client Hint 的目的是为网站提供更精确的设备信息,例如屏幕宽度也能加到 Header。Client Hint 默认不会发送所有的信息,只有在服务器显式请求后,浏览器才会返回相关信息。但是浏览器和平台的信息默认是会发送的。
Client Hint 默认会提供的信息:
Sec-CH-UA: "Brave";v="131", "Chromium";v="131", "Not_A Brand";v="24"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
我通过 HTTPie 模拟了请求,结果证实 🦞 确实是通过 Sec-CH-UA
识别 Brave 浏览器的。
有趣的是,禁用 JavaScript 后,Brave 不再发送 Client Hint 的头,这也是为什么禁用 JS 后能够成功访问 🦞 的原因。
(伪装成 Chrome,但又没有完全伪装
尝试 Client Hint
之后我尝试用 Client Hint 统计浏览器,发现某些国产浏览器 (比如 UC) User-Agent
显示其正确名字,Sec-CH-UA
却返回一个 Chromium? like Chrome? 如果只用 Sec-CH-UA
的话目前比传统 UA 更不靠谱。
结
2024(确实 2024)年还能看到有网站在跟浏览器玩猫捉老鼠的游戏就挺搞的,最终不过是重复 Mozilla/5.0 的历史(大家都变成 Chrome 就好了,实际上也差不多了)。尽管我也很讨厌 Brave 塞的那些币圈垃圾。
Vivaldi 也是因为收到太多不兼容的报告,被迫默认改为跟 Chrome 一致的 UA。
中途我还发现 Brave 维护了一个长长的清单,禁止 Brave 的网站都会被拉到清单里,对清单里的网站会隐藏自身独特的 API 防止被检测到。