浏览器指纹识别如何工作:参数的全面解析
2025/10/17

浏览器指纹识别是一种通过浏览器和设备的特征和参数组合来识别用户的方法,无需使用cookie或其他存储数据。当您访问一个网站时,一个特殊的脚本会收集有关您的环境的信息(操作系统、浏览器版本、语言设置、时区、屏幕分辨率、字体列表等)并创建一个唯一的标识符,即浏览器指纹。这个标识符比普通的cookie存在时间更长,并帮助网站在用户重复访问时识别您的浏览器,即使用户清除了cookie或在隐身模式下打开网站也是如此。因此,网站可以通过不同的会话和资源跟踪用户的行为,将它们链接到一个个人资料。
浏览器指纹类似于人类的指纹,但在这里的独特性不完全是100%,大约是85–90%,这足以让网站识别一个个人资料。重要的是要了解指纹是一组参数。更改其中的一或两个不会产生显著的伪装效果:独特性仅下降百分几,因此需要全面地处理指纹。

让我们分析一下哪些参数组成了浏览器指纹,每个参数是如何收集的,以及其对独特性的影响程度。
浏览器指纹识别是一种通过浏览器和设备的特征和参数组合来识别用户的方法,无需使用cookie或其他存储数据。当您访问一个网站时,一个特殊的脚本会收集有关您的环境的信息(操作系统、浏览器版本、语言设置、时区、屏幕分辨率、字体列表等)并创建一个唯一的标识符,即浏览器指纹。这个标识符比普通的cookie存在时间更长,并帮助网站在用户重复访问时识别您的浏览器,即使用户清除了cookie或在隐身模式下打开网站也是如此。因此,网站可以通过不同的会话和资源跟踪用户的行为,将它们链接到一个个人资料。
浏览器指纹类似于人类的指纹,但在这里的独特性不完全是100%,大约是85–90%,这足以让网站识别一个个人资料。重要的是要了解指纹是一组参数。更改其中的一或两个不会产生显著的伪装效果:独特性仅下降百分几,因此需要全面地处理指纹。

让我们分析一下哪些参数组成了浏览器指纹,每个参数是如何收集的,以及其对独特性的影响程度。
指纹识别与其他追踪方法
浏览器指纹识别技术作为经典用户追踪方法的限制的回应而出现。
HTTP cookies
识别用户的最常见方法是将唯一标识符存储在浏览器中(在cookie文件中)并在每次访问时读取。缺点是用户可以清除cookie,网站将失去之前发出的ID。此外,在隐身模式下或浏览器阻止第三方cookie时,此方法无效。现代浏览器和扩展提供了更多工具来阻止或自动删除cookie,从而降低这种方法的有效性。另一方面,指纹识别不需要在客户端存储数据,因此即使在禁用cookie和隐身模式下也能工作;只要浏览器提供必要的系统信息即可。

LocalStorage, SessionStorage 及其他网页存储
与cookie类似,这些技术在浏览器中本地存储数据。脚本可以在重复访问时读取它们。然而,用户可以手动清除它们,并且存储按域隔离;此外,SessionStorage仅在一个选项卡/会话中可用。
还有Evercookie,这是一种通过在所有可用存储(HTTP cookie, Flash LSO, Silverlight孤立存储, IndexedDB等)中复制标识符并使用缓存和其他技巧创建“不可删除”cookie的技术。但即便Evercookie也不是万能的:例如,在隐身模式下,这种方法无用,因为数据不会被保存到硬盘。指纹识别不在设备上保存任何东西;每次访问都会重新收集信息,因此用标准清除方法难以阻止。

ETag追踪
虽然不是最常见的方法,但一种有效的使用HTTP缓存进行用户识别的方法。在第一次请求时,服务器返回一个带有唯一ETag
头的资源(例如,单个像素)。浏览器将其存储在缓存中。在对同一URL
的重复请求中,浏览器会自动发送之前接收到的ETag的If-None-Match
。因此,即使cookie已被删除,服务器也可以通过匹配ETag检测到相同的访客。这是一种被动的追踪方法,不需要JavaScript——标识符存储在缓存机制中。ETag追踪难以检测,能够在清除cookie后生存下来(需要清除缓存),甚至可以在没有JS的情况下工作。然而,如果需要,它也可以被对抗(禁用缓存,使用中介代理来清除ETag头)。

CNAME伪装
一种使用DNS CNAME记录将第三方追踪器伪装为第一方域的技术。例如,脚本不是从tracker.thirdparty.com
加载,而是从指向追踪器服务器的子域tracker.mysite.com
加载,浏览器将此类请求视为来自主要资源,因此广告/追踪器屏蔽程序无法检测到第三方域——追踪器的cookie被视为同一站点。CNAME伪装甚至可以绕过浏览器保护,如Safari的智能追踪防护等。在指纹识别的背景下,这种方法很重要,因为它允许第三方脚本收集指纹并设置cookie,仿佛它就是站点自身。实际上,CNAME伪装隐藏了第三方,而指纹识别无需存储的标识符。它们结合起来可以加强追踪(追踪器伪装成网站并在不被阻止的情况下收集最大用户数据,包括指纹)。
指纹识别
浏览器指纹识别并不替代上述方法;通常与它们结合使用。例如,在首次访问时,脚本可能会收集指纹并且尝试设置cookie。如果后来清除了cookie,则可以通过匹配指纹进行重复识别。此外,指纹可以补充其他方法:例如,通过favicon缓存存储的超级cookie可以保留唯一ID,追踪器可以比较浏览器参数进行确认。这些技术结合起来,创建了一个多层次的用户追踪系统。
浏览器指纹组成的参数
指纹由几十个小属性组成,这些属性一起形成一个独特的组合。其中一些通过每个HTTP请求自动发送(被动信号),而其他一些则通过JavaScript和Web API在客户端收集(主动信号)。
被动参数(HTTP头和连接)
IP地址
网络中设备的地址,从每个传入请求中确定。它可以指示地理位置(通过WHOIS或GeoIP提供国家/城市)和与组织/ISP的关系。尽管IP地址通常不是唯一的(许多用户可能在单个ISP的公共地址后面)并且可以动态变化,但它作为基本的网络标识符包含在指纹中。此外,如果WebRTC可用,脚本可以执行STUN请求并获取您的真实IP地址。尽管IP地址本身不是永久性的,但与其他信号结合时,它增加了唯一性的概率。

用户代理
每个浏览器在User-Agent
头中发送的用户代理字符串。它包含有关浏览器、其版本、引擎、操作系统版本、架构和有时设备型号的信息,例如 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36
。分析用户代理可以粗略区分,Chrome在Windows上与Safari在iOS上的区别,换句话说,将识别范围缩小到浏览器和平台。
用户代理唯一性:尽管用户代理是从有限的版本集中形成的,但操作系统和浏览器的组合通常是罕见的。例gaat tocht出,特定操作系统上的较旧浏览器版本将呈现出唯一的用户代理。扩展添加的非标准头也可能出现在指纹中;从中网站可以推断出已安装的插件或框架。总体而言,用户代理很容易被伪装,因此不应单独依赖;它只是指纹的一个方面。

接受头和其他协议特征
每个请求浏览器都会发送一组头:支持格式(Accept
, Accept-Language
, Accept-Encoding
)、推荐人、缓存标志等。这些头的组合也相当有信息性。例如,Accept-Language和Accept-Charset字段的顺序和内容在OS区域之间可能会有所不同。Accept-Encoding: br
的存在表明支持Brotli,并间接表明是一个相对现代的浏览器。浏览器列举头的顺序可以作为浏览器引擎的签名。
HTTP级信号被视为被动的,因为它们是由浏览器自动提供的。即使没有JS,服务器也可以了解设备类型(通过User-Agent)、首选语言(Accept-Language
)、客户端支持的内容类型(例如,Accept
中的WebP支持揭示出销售引擎)等等。所有这些小细节都喂养入指纹模型。

时区
尽管用户的时区可以主动确定(通过JS),也可以通过头近似确定。例如,HTTP中的Date
头或服务器日志中的时间可以与客户端请求时间进行比较(例如,如果If-Modified-Since
可见)。更常见的是时区
通过客户端获取。然而,时间偏移(GMT±X)是指纹的一部分,因为它在各地区之间有所不同,并且会一段时间内对用户保持稳定(除非用户旅行或手动更改设置)。

支持的技术
某些头或连接特征可能表示浏览器的能力。例如,如果用户启用了“请勿追踪”,则存在DNT (Do-Not-Track)
。此时DNT: 1
成为指纹的一部分(悖论是,这个标志可以让你脱颖而出,因为很少有人启用它)。另一个例子:Upgrade-Insecure-Requests: 1
在第一次过渡到HTTPS时由大多数现代浏览器发送;它的缺失可能标识出一个不寻常的客户端。这些微妙的差异很少出现在单独的指纹字段中,但可以共同考虑。
主动参数(JavaScript 和 Web API)
屏幕分辨率和色深
可通过window.screen
对象获取。属性screen.width/height
返回当前屏幕分辨率(有时考虑显示缩放),screen.colorDepth
返回色深(通常为24或32位)。这些参数经常包含在指纹中,因为它们的变化很大:每个人的屏幕大小都有所不同。在台式机上,浏览器窗口很少匹配最大分辨率,但指纹通常会取用户可用的最大分辨率,反映他们的显示器大小。例如,1920×1080×24(全高清、24位色)是一种配置,1366×768×24是另一种配置,等等。每种分辨率与色深结合可以缩小设备组。如果用户更改显示器分辨率或连接新显示器,指纹将会改变。

语言设置
浏览器曝光了几项相关设置:界面/操作系统语言、首选页面语言(s)及日期格式/数字的区域格式。JS可以获取navigator.language
(或navigator.languages
获取列表)——如“ru-RU”或“en-US”的值。这通常匹配服务器在Accept-Language
中接收的内容。区域会影响格式化函数,例如Date.toString()
(月份名称为俄文或英文等),这也可以用于指纹识别。
对唯一性的影响:语言和地区的组合非常多样。例如,一个俄语用户可能的区域可以是ru-RU
,或uk-UA
(如果他们的OS是乌克兰),甚至en-US
(如果界面是英文的)。这些细微差别增加了一些熵位。每年独特的语言组合排列数量在不断增长,但语言本身并不特别唯一:许多人使用流行的区域。然而,结合其他参数,语言有助于区分,比如说,俄文的Chrome/Windows与德文的Chrome/Windows,创造出两种不同的配置文件。

时区(通过JS)
更准确地确定时区的方法是使用JS调用新Date().getTimezoneOffset()
。这返回本地时间偏移UTC的分钟数。例如,GMT+3会产生180分钟。您还可以使用Intl API
获取时区名称。这个参数几乎总是包含在指纹中,因为它对于设备是稳定的,并且在地理上有所变化。两个具有相同参数但不同时区的用户已经会产生不同的指纹。
注意:一些先进的指纹识别器会追踪时区变化:这可以指示相同浏览器更改了上下文(例如,如果用户旅行或更改时钟设置)。然而,当前的偏移值通常用于简单的指纹。

关于平台和CPU的信息
navigator
对象提供了多个与设备平台相关的属性:
navigator.platform
— 按架构指明OS/架构的字符串,例如Win32、Linux x86_64、iPhone等。过去这曾是一个非常有指示性的参数(例如区分32位Windows和64位),但现代浏览器可能返回截短或统一的值以保护隐私。如果参数可用的话,它就包含在指纹中。navigator.hardwareConcurrency
— 设备上的逻辑CPU线程数(核心数)。例如,8(可能对应于启用超线程技术的4个物理核心)。这增加了额外的变化性:移动设备常常有4或8个,台式机有4、8、12、16甚至更多核心。并非所有浏览器都会报告准确的值,但在正常条件下会收集这一参数。异常的线程数(例如6或10)可以立即将设备区分出来。navigator.deviceMemory
— 以千兆字节为单位的近似RAM大小(整数)。Chrome将值舍入为0.25(四分之一)增量。例如,8 GB给出deviceMemory = 8
。此信号并不被所有浏览器支持。存在的情况下,它被纳入:RAM大小很少是整齐的数值,所以变化性减少了重叠。navigator.oscpu
— 包含操作系统的字符串(仅Firefox支持的API)。在Windows上的现代Firefox中,它返回一些类似于Windows NT 10.0; Win64; x64的东西。由于它重复了来自用户代理的信息,该参数很少使用。navigator.webdriver
— 表示浏览器是否由自动化工具驱动(WebDriver)的布尔值。如果true
,网站知道它正在与一个机器人互动,可能会改变行为或将这纳入指纹中。对于指纹识别来说,这更像是一个“唯一性”参数,是一种检测自动化的方法。尽管如此,navigator.webdriver=true
明确地标识出了客户端(常规用户显示为false),因此间接地它是指纹的一部分。

Cookies/Storage 启用状态
脚本可以检查浏览器是否启用了cookie(navigator.cookieEnabled
)。如果用户禁用了它们,这让他们与大多数其他用户区分开来(几乎所有人都保持cookie启用)并增加了唯一性。
浏览器插件列表
navigator.plugins
可以返回安装的NPAPI插件列表:Acrobat Reader、Flash、Silverlight等,包括它们的版本(navigator.plugins[i].name/version
),尽管NPAPI插件已经基本消失(Flash和Java在现代浏览器中被禁用或移除)。在Chrome中navigator.plugins
现在仅包含内建PDF查看器;在Firefox中,类似地,没有任何额外的东西。虽然如此,API依然存在,某些浏览器可能还会返回一些东西。指纹可能包含插件名称及其数量。空列表也是一个信号(例如,Tor模式中的Firefox为空,而普通Firefox可能包含内建的OpenH264插件)。总的来说,插件作为一个因素的作用正在下降;相应的扩展正在取代它们的重要性。

已安装的扩展
理想情况下,网站不应该知道用户安装了哪些扩展,但实际上某些扩展可以间接检测到。通过屏蔽的请求或它们引入的特定DOM元素可以检测到AdBlock或Adblock Plus。网站可以尝试加载被AdBlock过滤的已知URL——如果没有加载,很可能存在一个屏蔽程序。
另一个例子:扩展可以向window
添加特殊对象(例如,React Developer Tools添加__REACT_DEVTOOLS_GLOBAL_HOOK__
),如果脚本发现这样的对象则识别出扩展。成千上万个小检查可以构建一个“快照”浏览器环境的“快照”。有时可以从页面响应时间推断出扩展的大致数量。每个已安装的扩展都可能减慢页面处理。无论如何,检测流行的广告拦截器,密码管理器或小众扩展可以部分地增加配置文件的唯一性。
已安装的字体列表
最容易变的参数之一。系统字体集合取决于操作系统,已安装的应用程序(Microsoft Office添加字体,Adobe添加其自有字体等),以及系统语言(欧洲用户通常没有的中文字体)。网页如何检测您哪些字体?历史上,Flash(EnumerateFonts)被用于此,但在没有它的情况下有纯浏览器端的方法:
通过CSS + JS:创建一个带有字体系列后备列表的隐藏元素。如果第一个字体未安装,文本将在下一个字体下渲染,元素的宽度/高度发生变化。JS可以测量元素尺寸以推测哪个字体被应用。遍历上百个流行字体揭示哪些已存在。这种方法耗时,因此通常采用以下方法。
通过Canvas:在
上绘制特定字体的文本,并比较像素光栅,以此判断是否安装了该字体。这本质上是
指纹识别的一个案例(见下文)。

可能的字体集组合数量巨大,因为很少有人拥有相同的字体列表,尤其是跨不同的操作系统版本。罕见的字体(例如,设计特定的字体)立即使指纹变得unique,这使得字体数据非常有用的指纹识别。字体收集不是瞬间完成的,因此一些脚本会缓存指纹结果。
Canvas 指纹识别
这是使用HTML5的<canvas>
元素以获取独特渲染特征的一个著名指纹识别方法。浏览器在虚拟Canvas上绘制内容(通常是特定字体和颜色的文本,有时是几何形状),然后脚本调用canvas.toDataURL()
,获取渲染内容的位图图像。图像表示为一个base64字符串,被哈希处理以生成Canvas指纹。
为什么它是独特的?系统中微小的差异—字体平滑算法、GPU驱动程序版本、平台(Linux与Windows)—产生微小的变化在最终图像上。通常通过绘制不同形状的文本(字母、特殊符号)以最大化平滑效果。脚本也可以绘制彩色矩形,应用变换或阴影以检测季度函数不同的设备产生不同的图像与相同的绘图代码. Canvas指纹可以在GPU驱动程序更新后或开关集成图形变更后改变。与WebGL结合,它变得极具价值。

WebGL指纹识别
WebGL是用于在浏览器中呈现3D图形的API(提供访问OpenGL/ES功能)。它为指纹识别提供了两种主要类型的数据:
直接GPU标识符
WEBGL_debug_renderer_info
扩展允许脚本从WebGL上下文中检索UNMASKED_VENDOR_WEBGL
和UNMASKED_RENDERER_WEBGL
字符串——这些字符串通常列出GPU的制造商和型号(例如,Intel Inc., Intel Iris Plus Graphics 640,或 NVIDIA Corporation, GeForce GTX 1070)。这些值有效地揭示了用户的显卡型号。大多数浏览器允许在标准模式下(除了Tor)。GPU模型增加了显著的熵:即使两个用户拥有相同的操作系统和浏览器,一个具有Intel HD Graphics,另一个具有RTX 3080的用户将拥有不同的指纹。
WebGL常量和能力
即使没有直接的GPU名称,WebGL上下文持有许多依赖驱动程序和硬件的参数:最大纹理单元,几何大小限制,阴影和抗锯齿支持,以及其他数字常量。脚本可以顺序调用getParameter(...)
读取各种常量的结果。例如,MAX_VERTEX_UNIFORM_VECTORS
可能在一块卡上是4096而在另一个上是1024 等等。结果是一个长数字序列,某种程度上是图形子系统的轮廓。这种轮廓在设备上往往是独特的,即使是在相似的GPU型号之间也有所不同。

此外,可以像Canvas一样使用WebGL:即,通过渲染复杂的3D场景并获取其光栅图像。这种方法可以揭示更微妙的差异(例如在着色器实现中)。在实践中,FingerPrintJS等库通常限制自己读取UNMASKED_RENDERER
(因为它更简单且更可靠),但一些脚本还会散列渲染的3D形状以获得更高的稳定性。WebGL数据大大增加了指纹的独特性,尤其是在移动设备上:例如,以前很难区分iPhone(所有iPhone在Canvas输出上完全一样因为相同的GPU),但现在如果WebGL开启GPU版本可以揭示iPhone型号。如果与Canvas结合,WebGL提供丰富的熵资源。这就是为什么隐私导向的浏览器模式尝试隐藏或欺骗这些数据。
AudioContext 指纹识别
另一项复杂的指纹识别方法是利用Web Audio API得出设备的独特音频指纹。基于同一系统的音频生成和处理略有不同(由于库实现、SIMD指令使用、浮点不准确性等)。在实践中,AudioContext指纹值在浏览器之间显著不同;每个“浏览器+OS+硬件”组合提供其自身的确定性结果(只要浏览器或OS没有重大变化)。添加音频指纹进一步增强识别:即使Canvas和WebGL的输出恰巧相同,音频指纹仍可区分设备。
媒体设备和传感器
在指纹识别过程中,脚本还可以收集有关外部硬件的信息:
通过
navigator.mediaDevices.enumerateDevices()
,它能获得用户的媒体设备列表(摄像头、麦克风)。除非获得许可,否则浏览器通常只返回有限的数据,例如,“两个摄像头和一个麦克风”而不是名称或ID。然而,设备数量本身可以作为一种区分因素。API如电池状态(电池电量)曾经可用并用于指纹识别。电池电量和剩余时间产生了唯一组合。由于这些API可能产生过于精确的标识符(隐私问题),它们现在要么被限制或基于许可。
传感器(方向、运动):某些传感器的存在以及它们的输出格式可能不同(例如,陀螺仪刷新率)。这些是相对独特的信号,但理论上可补充指纹。
总体而言,设备越非标准,通过这些API揭示的越多。如果用户根本没有摄像头或麦克风,这已经将他们与大多数有网络摄像头的笔记本电脑区分开来。
以上所有—不论是主动还是被动的属性—一起组成了一套浏览器和系统特性。在实践中,脚本收集10到30个参数并将其编译到一个结构中(例如,字符串的对象或数组),然后转换为哈希。许多库使用快速的哈希算法,如MurmurHash从大约500字节的属性数据中生成一个紧凑的标识符。结果是一个字符串(例如,a3f6e9b12d4...
)可以存储在服务器上作为设备ID。

防御浏览器指纹识别的措施
现代浏览器实施了各种针对指纹识别的对抗措施。例如,多年来,Tor 浏览器旨在使所有用户看起来一样(相同的用户代理、固定的窗口大小、统一的字体集合、禁用Canvas和AudioContext等)。它甚至警告用户如果他们希望保持匿名不要最大化窗口。
Firefox包含privacy.resistFingerprinting
设置,其同样将值平均化处理。Brave浏览器默认屏蔽第三方追踪并在API中注入噪声。有如CanvasBlocker或Privacy Badger这样的扩展可以选择性地阻止追踪脚本。
然而,没有方法能提供100%的保护—浏览器暴露的参数太多了。为了应对对匿名性的日益增长的需求,反检测浏览器(如Octo Browser、MultiLogin、Dolphin {anty})出现了,它允许用户模拟不同的指纹并为例如,联盟营销目的创建数十个“虚拟”身份。
多年前开始的这场竞赛仍在继续:追踪者开发新技术,浏览器发明新对策。普通用户显然输掉了这场比赛—如果一个人不积极关心隐私,任一网站都可以捕捉他们的数字指纹并将其与来自其他源的数据关联。
指纹由许多组件组成,每个部分都增加了一定的独特性。希望这次的分解可以帮助您理解网站可以如何识别您的浏览器—因为了解技术的工作原理是知道便利性与个人数据保护之间界线的第一步。
指纹识别与其他追踪方法
浏览器指纹识别技术作为经典用户追踪方法的限制的回应而出现。
HTTP cookies
识别用户的最常见方法是将唯一标识符存储在浏览器中(在cookie文件中)并在每次访问时读取。缺点是用户可以清除cookie,网站将失去之前发出的ID。此外,在隐身模式下或浏览器阻止第三方cookie时,此方法无效。现代浏览器和扩展提供了更多工具来阻止或自动删除cookie,从而降低这种方法的有效性。另一方面,指纹识别不需要在客户端存储数据,因此即使在禁用cookie和隐身模式下也能工作;只要浏览器提供必要的系统信息即可。

LocalStorage, SessionStorage 及其他网页存储
与cookie类似,这些技术在浏览器中本地存储数据。脚本可以在重复访问时读取它们。然而,用户可以手动清除它们,并且存储按域隔离;此外,SessionStorage仅在一个选项卡/会话中可用。
还有Evercookie,这是一种通过在所有可用存储(HTTP cookie, Flash LSO, Silverlight孤立存储, IndexedDB等)中复制标识符并使用缓存和其他技巧创建“不可删除”cookie的技术。但即便Evercookie也不是万能的:例如,在隐身模式下,这种方法无用,因为数据不会被保存到硬盘。指纹识别不在设备上保存任何东西;每次访问都会重新收集信息,因此用标准清除方法难以阻止。

ETag追踪
虽然不是最常见的方法,但一种有效的使用HTTP缓存进行用户识别的方法。在第一次请求时,服务器返回一个带有唯一ETag
头的资源(例如,单个像素)。浏览器将其存储在缓存中。在对同一URL
的重复请求中,浏览器会自动发送之前接收到的ETag的If-None-Match
。因此,即使cookie已被删除,服务器也可以通过匹配ETag检测到相同的访客。这是一种被动的追踪方法,不需要JavaScript——标识符存储在缓存机制中。ETag追踪难以检测,能够在清除cookie后生存下来(需要清除缓存),甚至可以在没有JS的情况下工作。然而,如果需要,它也可以被对抗(禁用缓存,使用中介代理来清除ETag头)。

CNAME伪装
一种使用DNS CNAME记录将第三方追踪器伪装为第一方域的技术。例如,脚本不是从tracker.thirdparty.com
加载,而是从指向追踪器服务器的子域tracker.mysite.com
加载,浏览器将此类请求视为来自主要资源,因此广告/追踪器屏蔽程序无法检测到第三方域——追踪器的cookie被视为同一站点。CNAME伪装甚至可以绕过浏览器保护,如Safari的智能追踪防护等。在指纹识别的背景下,这种方法很重要,因为它允许第三方脚本收集指纹并设置cookie,仿佛它就是站点自身。实际上,CNAME伪装隐藏了第三方,而指纹识别无需存储的标识符。它们结合起来可以加强追踪(追踪器伪装成网站并在不被阻止的情况下收集最大用户数据,包括指纹)。
指纹识别
浏览器指纹识别并不替代上述方法;通常与它们结合使用。例如,在首次访问时,脚本可能会收集指纹并且尝试设置cookie。如果后来清除了cookie,则可以通过匹配指纹进行重复识别。此外,指纹可以补充其他方法:例如,通过favicon缓存存储的超级cookie可以保留唯一ID,追踪器可以比较浏览器参数进行确认。这些技术结合起来,创建了一个多层次的用户追踪系统。
浏览器指纹组成的参数
指纹由几十个小属性组成,这些属性一起形成一个独特的组合。其中一些通过每个HTTP请求自动发送(被动信号),而其他一些则通过JavaScript和Web API在客户端收集(主动信号)。
被动参数(HTTP头和连接)
IP地址
网络中设备的地址,从每个传入请求中确定。它可以指示地理位置(通过WHOIS或GeoIP提供国家/城市)和与组织/ISP的关系。尽管IP地址通常不是唯一的(许多用户可能在单个ISP的公共地址后面)并且可以动态变化,但它作为基本的网络标识符包含在指纹中。此外,如果WebRTC可用,脚本可以执行STUN请求并获取您的真实IP地址。尽管IP地址本身不是永久性的,但与其他信号结合时,它增加了唯一性的概率。

用户代理
每个浏览器在User-Agent
头中发送的用户代理字符串。它包含有关浏览器、其版本、引擎、操作系统版本、架构和有时设备型号的信息,例如 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36
。分析用户代理可以粗略区分,Chrome在Windows上与Safari在iOS上的区别,换句话说,将识别范围缩小到浏览器和平台。
用户代理唯一性:尽管用户代理是从有限的版本集中形成的,但操作系统和浏览器的组合通常是罕见的。例gaat tocht出,特定操作系统上的较旧浏览器版本将呈现出唯一的用户代理。扩展添加的非标准头也可能出现在指纹中;从中网站可以推断出已安装的插件或框架。总体而言,用户代理很容易被伪装,因此不应单独依赖;它只是指纹的一个方面。

接受头和其他协议特征
每个请求浏览器都会发送一组头:支持格式(Accept
, Accept-Language
, Accept-Encoding
)、推荐人、缓存标志等。这些头的组合也相当有信息性。例如,Accept-Language和Accept-Charset字段的顺序和内容在OS区域之间可能会有所不同。Accept-Encoding: br
的存在表明支持Brotli,并间接表明是一个相对现代的浏览器。浏览器列举头的顺序可以作为浏览器引擎的签名。
HTTP级信号被视为被动的,因为它们是由浏览器自动提供的。即使没有JS,服务器也可以了解设备类型(通过User-Agent)、首选语言(Accept-Language
)、客户端支持的内容类型(例如,Accept
中的WebP支持揭示出销售引擎)等等。所有这些小细节都喂养入指纹模型。

时区
尽管用户的时区可以主动确定(通过JS),也可以通过头近似确定。例如,HTTP中的Date
头或服务器日志中的时间可以与客户端请求时间进行比较(例如,如果If-Modified-Since
可见)。更常见的是时区
通过客户端获取。然而,时间偏移(GMT±X)是指纹的一部分,因为它在各地区之间有所不同,并且会一段时间内对用户保持稳定(除非用户旅行或手动更改设置)。

支持的技术
某些头或连接特征可能表示浏览器的能力。例如,如果用户启用了“请勿追踪”,则存在DNT (Do-Not-Track)
。此时DNT: 1
成为指纹的一部分(悖论是,这个标志可以让你脱颖而出,因为很少有人启用它)。另一个例子:Upgrade-Insecure-Requests: 1
在第一次过渡到HTTPS时由大多数现代浏览器发送;它的缺失可能标识出一个不寻常的客户端。这些微妙的差异很少出现在单独的指纹字段中,但可以共同考虑。
主动参数(JavaScript 和 Web API)
屏幕分辨率和色深
可通过window.screen
对象获取。属性screen.width/height
返回当前屏幕分辨率(有时考虑显示缩放),screen.colorDepth
返回色深(通常为24或32位)。这些参数经常包含在指纹中,因为它们的变化很大:每个人的屏幕大小都有所不同。在台式机上,浏览器窗口很少匹配最大分辨率,但指纹通常会取用户可用的最大分辨率,反映他们的显示器大小。例如,1920×1080×24(全高清、24位色)是一种配置,1366×768×24是另一种配置,等等。每种分辨率与色深结合可以缩小设备组。如果用户更改显示器分辨率或连接新显示器,指纹将会改变。

语言设置
浏览器曝光了几项相关设置:界面/操作系统语言、首选页面语言(s)及日期格式/数字的区域格式。JS可以获取navigator.language
(或navigator.languages
获取列表)——如“ru-RU”或“en-US”的值。这通常匹配服务器在Accept-Language
中接收的内容。区域会影响格式化函数,例如Date.toString()
(月份名称为俄文或英文等),这也可以用于指纹识别。
对唯一性的影响:语言和地区的组合非常多样。例如,一个俄语用户可能的区域可以是ru-RU
,或uk-UA
(如果他们的OS是乌克兰),甚至en-US
(如果界面是英文的)。这些细微差别增加了一些熵位。每年独特的语言组合排列数量在不断增长,但语言本身并不特别唯一:许多人使用流行的区域。然而,结合其他参数,语言有助于区分,比如说,俄文的Chrome/Windows与德文的Chrome/Windows,创造出两种不同的配置文件。

时区(通过JS)
更准确地确定时区的方法是使用JS调用新Date().getTimezoneOffset()
。这返回本地时间偏移UTC的分钟数。例如,GMT+3会产生180分钟。您还可以使用Intl API
获取时区名称。这个参数几乎总是包含在指纹中,因为它对于设备是稳定的,并且在地理上有所变化。两个具有相同参数但不同时区的用户已经会产生不同的指纹。
注意:一些先进的指纹识别器会追踪时区变化:这可以指示相同浏览器更改了上下文(例如,如果用户旅行或更改时钟设置)。然而,当前的偏移值通常用于简单的指纹。

关于平台和CPU的信息
navigator
对象提供了多个与设备平台相关的属性:
navigator.platform
— 按架构指明OS/架构的字符串,例如Win32、Linux x86_64、iPhone等。过去这曾是一个非常有指示性的参数(例如区分32位Windows和64位),但现代浏览器可能返回截短或统一的值以保护隐私。如果参数可用的话,它就包含在指纹中。navigator.hardwareConcurrency
— 设备上的逻辑CPU线程数(核心数)。例如,8(可能对应于启用超线程技术的4个物理核心)。这增加了额外的变化性:移动设备常常有4或8个,台式机有4、8、12、16甚至更多核心。并非所有浏览器都会报告准确的值,但在正常条件下会收集这一参数。异常的线程数(例如6或10)可以立即将设备区分出来。navigator.deviceMemory
— 以千兆字节为单位的近似RAM大小(整数)。Chrome将值舍入为0.25(四分之一)增量。例如,8 GB给出deviceMemory = 8
。此信号并不被所有浏览器支持。存在的情况下,它被纳入:RAM大小很少是整齐的数值,所以变化性减少了重叠。navigator.oscpu
— 包含操作系统的字符串(仅Firefox支持的API)。在Windows上的现代Firefox中,它返回一些类似于Windows NT 10.0; Win64; x64的东西。由于它重复了来自用户代理的信息,该参数很少使用。navigator.webdriver
— 表示浏览器是否由自动化工具驱动(WebDriver)的布尔值。如果true
,网站知道它正在与一个机器人互动,可能会改变行为或将这纳入指纹中。对于指纹识别来说,这更像是一个“唯一性”参数,是一种检测自动化的方法。尽管如此,navigator.webdriver=true
明确地标识出了客户端(常规用户显示为false),因此间接地它是指纹的一部分。

Cookies/Storage 启用状态
脚本可以检查浏览器是否启用了cookie(navigator.cookieEnabled
)。如果用户禁用了它们,这让他们与大多数其他用户区分开来(几乎所有人都保持cookie启用)并增加了唯一性。
浏览器插件列表
navigator.plugins
可以返回安装的NPAPI插件列表:Acrobat Reader、Flash、Silverlight等,包括它们的版本(navigator.plugins[i].name/version
),尽管NPAPI插件已经基本消失(Flash和Java在现代浏览器中被禁用或移除)。在Chrome中navigator.plugins
现在仅包含内建PDF查看器;在Firefox中,类似地,没有任何额外的东西。虽然如此,API依然存在,某些浏览器可能还会返回一些东西。指纹可能包含插件名称及其数量。空列表也是一个信号(例如,Tor模式中的Firefox为空,而普通Firefox可能包含内建的OpenH264插件)。总的来说,插件作为一个因素的作用正在下降;相应的扩展正在取代它们的重要性。

已安装的扩展
理想情况下,网站不应该知道用户安装了哪些扩展,但实际上某些扩展可以间接检测到。通过屏蔽的请求或它们引入的特定DOM元素可以检测到AdBlock或Adblock Plus。网站可以尝试加载被AdBlock过滤的已知URL——如果没有加载,很可能存在一个屏蔽程序。
另一个例子:扩展可以向window
添加特殊对象(例如,React Developer Tools添加__REACT_DEVTOOLS_GLOBAL_HOOK__
),如果脚本发现这样的对象则识别出扩展。成千上万个小检查可以构建一个“快照”浏览器环境的“快照”。有时可以从页面响应时间推断出扩展的大致数量。每个已安装的扩展都可能减慢页面处理。无论如何,检测流行的广告拦截器,密码管理器或小众扩展可以部分地增加配置文件的唯一性。
已安装的字体列表
最容易变的参数之一。系统字体集合取决于操作系统,已安装的应用程序(Microsoft Office添加字体,Adobe添加其自有字体等),以及系统语言(欧洲用户通常没有的中文字体)。网页如何检测您哪些字体?历史上,Flash(EnumerateFonts)被用于此,但在没有它的情况下有纯浏览器端的方法:
通过CSS + JS:创建一个带有字体系列后备列表的隐藏元素。如果第一个字体未安装,文本将在下一个字体下渲染,元素的宽度/高度发生变化。JS可以测量元素尺寸以推测哪个字体被应用。遍历上百个流行字体揭示哪些已存在。这种方法耗时,因此通常采用以下方法。
通过Canvas:在
上绘制特定字体的文本,并比较像素光栅,以此判断是否安装了该字体。这本质上是
指纹识别的一个案例(见下文)。

可能的字体集组合数量巨大,因为很少有人拥有相同的字体列表,尤其是跨不同的操作系统版本。罕见的字体(例如,设计特定的字体)立即使指纹变得unique,这使得字体数据非常有用的指纹识别。字体收集不是瞬间完成的,因此一些脚本会缓存指纹结果。
Canvas 指纹识别
这是使用HTML5的<canvas>
元素以获取独特渲染特征的一个著名指纹识别方法。浏览器在虚拟Canvas上绘制内容(通常是特定字体和颜色的文本,有时是几何形状),然后脚本调用canvas.toDataURL()
,获取渲染内容的位图图像。图像表示为一个base64字符串,被哈希处理以生成Canvas指纹。
为什么它是独特的?系统中微小的差异—字体平滑算法、GPU驱动程序版本、平台(Linux与Windows)—产生微小的变化在最终图像上。通常通过绘制不同形状的文本(字母、特殊符号)以最大化平滑效果。脚本也可以绘制彩色矩形,应用变换或阴影以检测季度函数不同的设备产生不同的图像与相同的绘图代码. Canvas指纹可以在GPU驱动程序更新后或开关集成图形变更后改变。与WebGL结合,它变得极具价值。

WebGL指纹识别
WebGL是用于在浏览器中呈现3D图形的API(提供访问OpenGL/ES功能)。它为指纹识别提供了两种主要类型的数据:
直接GPU标识符
WEBGL_debug_renderer_info
扩展允许脚本从WebGL上下文中检索UNMASKED_VENDOR_WEBGL
和UNMASKED_RENDERER_WEBGL
字符串——这些字符串通常列出GPU的制造商和型号(例如,Intel Inc., Intel Iris Plus Graphics 640,或 NVIDIA Corporation, GeForce GTX 1070)。这些值有效地揭示了用户的显卡型号。大多数浏览器允许在标准模式下(除了Tor)。GPU模型增加了显著的熵:即使两个用户拥有相同的操作系统和浏览器,一个具有Intel HD Graphics,另一个具有RTX 3080的用户将拥有不同的指纹。
WebGL常量和能力
即使没有直接的GPU名称,WebGL上下文持有许多依赖驱动程序和硬件的参数:最大纹理单元,几何大小限制,阴影和抗锯齿支持,以及其他数字常量。脚本可以顺序调用getParameter(...)
读取各种常量的结果。例如,MAX_VERTEX_UNIFORM_VECTORS
可能在一块卡上是4096而在另一个上是1024 等等。结果是一个长数字序列,某种程度上是图形子系统的轮廓。这种轮廓在设备上往往是独特的,即使是在相似的GPU型号之间也有所不同。

此外,可以像Canvas一样使用WebGL:即,通过渲染复杂的3D场景并获取其光栅图像。这种方法可以揭示更微妙的差异(例如在着色器实现中)。在实践中,FingerPrintJS等库通常限制自己读取UNMASKED_RENDERER
(因为它更简单且更可靠),但一些脚本还会散列渲染的3D形状以获得更高的稳定性。WebGL数据大大增加了指纹的独特性,尤其是在移动设备上:例如,以前很难区分iPhone(所有iPhone在Canvas输出上完全一样因为相同的GPU),但现在如果WebGL开启GPU版本可以揭示iPhone型号。如果与Canvas结合,WebGL提供丰富的熵资源。这就是为什么隐私导向的浏览器模式尝试隐藏或欺骗这些数据。
AudioContext 指纹识别
另一项复杂的指纹识别方法是利用Web Audio API得出设备的独特音频指纹。基于同一系统的音频生成和处理略有不同(由于库实现、SIMD指令使用、浮点不准确性等)。在实践中,AudioContext指纹值在浏览器之间显著不同;每个“浏览器+OS+硬件”组合提供其自身的确定性结果(只要浏览器或OS没有重大变化)。添加音频指纹进一步增强识别:即使Canvas和WebGL的输出恰巧相同,音频指纹仍可区分设备。
媒体设备和传感器
在指纹识别过程中,脚本还可以收集有关外部硬件的信息:
通过
navigator.mediaDevices.enumerateDevices()
,它能获得用户的媒体设备列表(摄像头、麦克风)。除非获得许可,否则浏览器通常只返回有限的数据,例如,“两个摄像头和一个麦克风”而不是名称或ID。然而,设备数量本身可以作为一种区分因素。API如电池状态(电池电量)曾经可用并用于指纹识别。电池电量和剩余时间产生了唯一组合。由于这些API可能产生过于精确的标识符(隐私问题),它们现在要么被限制或基于许可。
传感器(方向、运动):某些传感器的存在以及它们的输出格式可能不同(例如,陀螺仪刷新率)。这些是相对独特的信号,但理论上可补充指纹。
总体而言,设备越非标准,通过这些API揭示的越多。如果用户根本没有摄像头或麦克风,这已经将他们与大多数有网络摄像头的笔记本电脑区分开来。
以上所有—不论是主动还是被动的属性—一起组成了一套浏览器和系统特性。在实践中,脚本收集10到30个参数并将其编译到一个结构中(例如,字符串的对象或数组),然后转换为哈希。许多库使用快速的哈希算法,如MurmurHash从大约500字节的属性数据中生成一个紧凑的标识符。结果是一个字符串(例如,a3f6e9b12d4...
)可以存储在服务器上作为设备ID。

防御浏览器指纹识别的措施
现代浏览器实施了各种针对指纹识别的对抗措施。例如,多年来,Tor 浏览器旨在使所有用户看起来一样(相同的用户代理、固定的窗口大小、统一的字体集合、禁用Canvas和AudioContext等)。它甚至警告用户如果他们希望保持匿名不要最大化窗口。
Firefox包含privacy.resistFingerprinting
设置,其同样将值平均化处理。Brave浏览器默认屏蔽第三方追踪并在API中注入噪声。有如CanvasBlocker或Privacy Badger这样的扩展可以选择性地阻止追踪脚本。
然而,没有方法能提供100%的保护—浏览器暴露的参数太多了。为了应对对匿名性的日益增长的需求,反检测浏览器(如Octo Browser、MultiLogin、Dolphin {anty})出现了,它允许用户模拟不同的指纹并为例如,联盟营销目的创建数十个“虚拟”身份。
多年前开始的这场竞赛仍在继续:追踪者开发新技术,浏览器发明新对策。普通用户显然输掉了这场比赛—如果一个人不积极关心隐私,任一网站都可以捕捉他们的数字指纹并将其与来自其他源的数据关联。
指纹由许多组件组成,每个部分都增加了一定的独特性。希望这次的分解可以帮助您理解网站可以如何识别您的浏览器—因为了解技术的工作原理是知道便利性与个人数据保护之间界线的第一步。
随时获取最新的Octo Browser新闻
通过点击按钮,您同意我们的 隐私政策。
随时获取最新的Octo Browser新闻
通过点击按钮,您同意我们的 隐私政策。
随时获取最新的Octo Browser新闻
通过点击按钮,您同意我们的 隐私政策。