Soup's Blog

Back

你有没有过这种经历:清了 Cookie、开了隐身窗口、换了台代理的 IP,某个网站却还是能判断出「这个人之前来过」?

这不是玄学。这就是本文要讲的东西——浏览器指纹(Browser Fingerprint)。

先说结论,再说原理:Cookie 是网站发给你的「号牌」,你可以扔掉;而指纹是你「长什么样」,你走到哪儿它都跟着。想真正保护隐私,绕不开它。

一、Cookie 与指纹:号牌和长相的区别#

Cookie 是网站主动写进你浏览器的一小段数据,相当于前台给你的「存包号牌」。你每次来,报上号牌,前台就知道你是谁。但这个号牌你能扔——清了 Cookie、开隐身,号牌就没了,前台认不出你。

浏览器指纹 则完全不同:网站不给你写任何东西,而是现场观察你的浏览器这台机器「长什么样」,把长相拼成一个标识。因为你没换电脑、没换系统、没重装浏览器,「长相」几乎不变。所以:

  • 清 Cookie?没用。指纹不是保存在你那儿的。
  • 开隐身?没用。隐身只隔离了本地存储,没改变你的硬件和浏览器配置。
  • 换 IP / 挂 VPN?还是没用。指纹描述的是「设备本身」,不是「你从哪来」。

换句话说,指纹是无状态的:它不往你的设备写任何东西,因此你无法通过「清除」来抹掉它。这恰恰是它比 Cookie 更难防的原因。

二、为什么「长相」能认人:熵#

单个特征谁都不特殊——「用 Chrome」的人有上亿。但特征组合起来,就几乎唯一了。这个「信息量」的概念,在指纹领域有个专业词叫熵(entropy),单位是 bit。

打个比方:聚会上一屋子人,只看「戴不戴眼镜」分不出谁是谁;但「身高 + 眼镜 + 发型 + 口音 + 手表」组合起来,基本就能锁定某一个人。指纹同理——收集几十个平平无奇的字段,拼起来就变成了你的「数字身份证」。

这个结论有实证。电子前线基金会(EFF)在 2010 年做过一个标志性研究(项目名 Panopticlick,后来的 Cover Your Tracks),结论是:样本里约 84% 的浏览器指纹是独一无二的。后来又有一项统计称,光是 Canvas 一项技术就被超过 30% 的主流网站用于追踪。

三、主要指纹维度:网站到底在看什么#

下面把最常见的维度拆开讲。可以粗略分成三类:「自报家门」的被动信息、「逼你干活」的主动探测、以及**「藏在网络层」的底层指纹**。

1. 自报家门:User-Agent、语言、时区、屏幕#

这些是浏览器主动告诉网站的信息,几乎每个请求都带着:

  • User-Agent:浏览器类型、版本、操作系统。比如 Mozilla/5.0 (Macintosh...) Chrome/xxx。
  • 语言:你浏览器设置的语言列表。
  • 时区:Intl.DateTimeFormat().resolvedOptions().timeZone 能读出你所在时区(如 Asia/Shanghai)。
  • 屏幕:分辨率、可用尺寸、色深、像素比(devicePixelRatio)等。

这类字段单独看没杀伤力,而且很容易伪造(改个 UA 谁都行)。但它们有个重要作用:用来和别的字段「对账」。后面会看到,「对不上账」本身就是最大的破绽。

2. Canvas 指纹:画一张图,读出来的颜色不一样#

这是当前公认熵最高、最可靠的主动探测手段。

原理是:网站让你浏览器在**屏幕外的画布(canvas)**上绘制一段固定的文字和图形,然后用 toDataURL() 把绘制结果转成图片数据,再算一个哈希值。

关键在于:同样一段绘制指令,在不同电脑上画出来的结果会有细微差异。差异来自 GPU 型号、显卡驱动、字体渲染引擎(Windows 的 ClearType、macOS 的 Core Text、Linux 的 FreeType)、抗锯齿算法、子像素渲染、颜色空间……这些任何一个不同,最终像素就不同。

所以两台型号相同的电脑,只要驱动版本或字体稍有差别,Canvas 哈希就可能不同;而同一台电脑多次刷新,哈希却稳定一致。这种「跨设备有差异、同设备稳定」的性质,正是理想指纹该有的样子。

3. WebGL 指纹:直接问出你的显卡型号#

WebGL 是浏览器里的 3D 渲染接口,它比 Canvas「更狠」,因为它能直接报出显卡型号。

通过 WEBGL_debug_renderer_info 扩展,网站能读到像这样的字符串:

ANGLE (Apple, ANGLE Metal Renderer: Apple M2 Pro, Unspecified Version)

这一下就把 GPU 型号交代了。再结合支持的扩展列表、着色器精度、以及「渲染一个 3D 场景读回像素」的结果,WebGL 构成了一个和硬件强绑定的指纹。

顺带一个实用的坑:WebGL 报的显卡要和 User-Agent 说得通——如果 UA 声称是 macOS,但 renderer 返回 NVIDIA GeForce GTX,风控系统立刻知道你在撒谎。这就是「对账」的威力。

4. AudioContext 指纹:连声音处理的小数点都不同#

音频也能做指纹。网站让浏览器用 OfflineAudioContext 在后台静默合成一段固定波形(比如一个 10kHz 的三角波,再过一道 DynamicsCompressor 处理器),然后读取输出的采样数据算哈希。

不同操作系统、CPU 架构、浏览器在浮点运算上有极微小的差异,这些差异会体现在处理后的波形数据里。结果就是:Mac / Windows / Linux、Intel / AMD / Apple Silicon、Chrome / Firefox / Safari,都能被区分出来。而且它静默完成,你根本听不到、也几乎伪造不了。

5. 字体列表:你装了什么字体,一问便知#

浏览器没有「直接列出已装字体」的接口,但网站有办法绕过去:

对某个候选字体,渲染一段测试字符串,量一下它的宽度;再和默认字体(如 monospace、serif)渲染同串的宽度对比。宽度不一样,说明这个字体你装了;一样,说明没装。

你机器上装着哪些字体、哪些没装,和操作系统、装过哪些办公软件、设计软件强相关,因此字体列表是识别力很强的信号。这也是为什么「装了某套特殊字体」会显著增加你被认出的概率。

6. 硬件信息:CPU 核数、内存、触摸点#

浏览器会暴露一批「量化」的硬件参数:

  • navigator.hardwareConcurrency:CPU 逻辑核心数;
  • navigator.deviceMemory:内存容量(大致的档位);
  • navigator.maxTouchPoints:最大触摸点数(能区分触屏设备)。

单看哪个都不独特,但它们的联合分布能帮你把设备缩小到很窄的范围。

7. 网络层指纹:TLS 握手(JA3 / JA4)——JS 摸不到的「底色」#

前面说的都在浏览器页面里、用 JavaScript 就能读到。但有一层指纹藏在网络连接本身,页面脚本碰不到:

浏览器和服务器建 HTTPS 连接时,第一句话叫 Client Hello,里面会报出它支持的 TLS 版本、加密套件、扩展、曲线以及它们的顺序。真实浏览器、Python 的 requests、Go 程序、curl……它们的 Client Hello 长得都不一样。

JA3 是把这些字段拼接后算的哈希,JA4 是它的改进版(能容忍扩展顺序被随机打乱)。这套「TLS 指纹」的强大在于:它不是页面 JS 能改的——你哪怕把 User-Agent 伪造得天衣无缝,只要 TLS 握手暴露了你其实是 Python 脚本,风控一样秒判。

这也解释了为什么「只会改 UA 的伪装」没用:底层对不上账。

8. WebRTC:VPN 之下,泄露真实 IP#

WebRTC 本来是用来做实时音视频的,但它在建立连接时,可能把本机局域网 IP、甚至 VPN 背后的真实公网 IP 暴露出来。

所以它的作用不是「区分两台设备」,而是发现用户在隐藏自己的来源——你挂着 VPN 假装在美国,WebRTC 却报出一个中国 IP,这就露馅了。它更多是「匿名检测」的信号,而不是设备区分信号。

9. 行为指纹:鼠标怎么动、打字多快#

以上都是「这台机器是什么」;还有一类信号是「坐在屏幕前的是不是真人」:

鼠标移动轨迹、滚动速度、键盘敲击节奏、复制粘贴的间隔……这些单独看识别不了设备,但能判断「是不是人、是不是自动化脚本」。反爬系统通常把行为信号和硬件指纹一起用。

四、最关键的原理:交叉校验与「一致性」#

看懂这一节,你就抓住了整个浏览器指纹的精髓。

单个字段,职业选手都能伪造。但问题是:要同时伪造几十个字段,并且让它们彼此「对得上」,极难。这个「对得上」,专业说法叫一致性(coherence)。

举几个「对不上账」就露馅的例子:

  • TLS 指纹显示这是 Go 的标准库,User-Agent 却说自己是 macOS 上的最新版 Chrome → 两者不可能同时为真;
  • UA 说系统是 macOS 13,Sec-CH-UA-Platform-Version 却报 14.7.0 → 有一个在撒谎;
  • UA 报 macOS,WebGL 却返回 NVIDIA 桌面显卡 → 又是矛盾;
  • 时区是 America/New_York,但语言是纯简体中文、IP 是国家数据中心 → 可疑。

反爬虫、风控系统真正做的,不是信某一个字段,而是给几十个字段分别打分、再做交叉一致性判断。这也就是为什么「伪装」比「降低信息量」难得多——你改得越多,越容易留出矛盾。

五、谁在用浏览器指纹#

目的不一,但本质都是「无 Cookie 识别同一台设备」:

  • 反爬 / 反自动化:Cloudflare、Akamai、DataDome 这类服务,用指纹识别 Puppeteer / Selenium 驱动的脚本。
  • 账号风控 / 防关联:Amazon、Facebook、Google、TikTok、PayPal、Stripe 等平台,靠指纹判断「换了 IP 和邮箱的两个账号,是不是同一台设备、同一个人在操作」。多账号防关联、跨境电商风控,是这条技术最现实的战场。
  • 广告归因与追踪:就算你拒绝 Cookie,广告平台仍可能靠指纹做跨站关联。
  • 隐私侵蚀:同一套技术,既能被用来「反欺诈」,也能被用来「追踪你不想被追踪」。

六、怎么保护自己(以及哪些是坑)#

最重要的原则先记住:目标是「降低熵、保持稳定和自洽」,而不是「把所有值都改乱」。

该做的#

  • 用带内置指纹防护的浏览器:Firefox 的「指纹保护」(增强跟踪保护的一部分)会阻止已知指纹脚本、归一化部分值;Tor 浏览器最彻底——它让所有用户看起来尽量一致,你在模糊人群里反而最安全。
  • 减少独特暴露:少装冷门插件、少装特殊字体、保持默认设置。有统计称,超过一半用户的扩展组合是唯一的——每多一个独特插件,就多一分被认出的风险。
  • 保持「对账」一致:系统时区、浏览器语言、IP 出口地区尽量统一。一个「美国 IP + 上海时区」的环境,比普通用户更扎眼。

要警惕的坑#

  • 随机化插件往往是负优化:很多人以为「让 Canvas 每次返回不同值」能防追踪。恰恰相反——真实浏览器的指纹是稳定的,每次都变反而暴露了「这人在刻意对抗」,更容易被标记。好的防护是「看起来像一个平凡、稳定、自洽的真人」,而不是「每次都不一样」。
  • 别迷信单一检测工具的全绿:公开的检测站只能覆盖公开信号;专业反爬服务还握着大量私有信号(TLS、TCP、HTTP/2 帧序、JS 执行时序等),过了公开测试不代表过了它们。

七、自己测一下:主流检测工具#

想知道自己的浏览器「多好认」,可以用这些(大多是本地采集、不泄露):

  • EFF Cover Your Tracks(原 Panopticlick):最经典、最权威,会告诉你「你的指纹在多少浏览器里是唯一的」。
  • BrowserLeaks:老牌综合检测,WebRTC、Canvas、Audio、字体都能看。
  • CreepJS:风格硬核,把指纹熵拆分得非常细,进阶用户友好。
  • amiunique.org:法国学术团队的项目,偏向指纹分布统计。
  • 国内的 chdh.me、CleanIP.io 也提供 Canvas / WebGL / Audio / 字体 + 自动化痕迹的综合检测,中文界面适合快速自检。

提醒:检测工具是「诊断仪」不是「盾牌」,它告诉你暴露了什么,防护还得靠浏览器本身。

八、小结:和上一篇 DoH 连起来看#

上一篇讲的是网络层的隐私——DoH 加密你的 DNS 查询、ECH 加密你访问的域名,让中间人「看不清你在连谁」。

这一篇讲的是设备层的隐私——浏览器指纹让你即使换了 IP、清了 Cookie,平台也能「认出这台机器」。

两者是隐私拼图的两块:网络上藏住「你去哪」,和设备上藏住「你是谁」,缺一不可。一个常见的误区就是只顾挂代理/VPN(换网络身份),却忽略了设备身份的暴露。

最终的建议收敛成一句话:少一点独特,多一点平凡,并且让所有暴露的信息彼此对得上账。


参考来源#

本文主要参考以下优质资料整理(检索并提炼,非逐字转述):

  • Google web.dev —《Fingerprinting》(隐私学习路径官方文档)
  • EFF — Panopticlick / Cover Your Tracks(浏览器指纹唯一性标志性研究)
  • Foil —《Browser fingerprinting techniques》《Device fingerprinting in JavaScript》
  • 阿里云开发者社区 —《未登录也能知道你是谁?浏览器指纹了解一下》
  • 腾讯云开发者社区 —《指纹浏览器的检测到底怎么做?原理代码一次搞懂》
  • ShieldLabs —《10 browser fingerprinting techniques explained》
  • chdh.me / CleanIP.io — 浏览器指纹检测工具(技术说明)
浏览器指纹:不依赖 Cookie,网站凭什么认出你
http://localhost:4321/blog/netsec_blogs/browser-fingerprint
Author Soup Cola
Published at 2026年9月25日