指纹

什么是浏览器指纹识别?完整指南

关于浏览器指纹识别你需要知道的一切:工作原理、收集哪些信号、隐私风险以及如何保护自己。

文档中心

想直接看维护中的产品文档?

这篇文章对应的主题已经有文档中心页面。需要规范流程、当前参数和长期参考时,优先看 docs。

简介

浏览器指纹识别是一种通过收集浏览器和设备配置信息来识别用户的追踪技术。与 Cookie 不同(Cookie 在你的计算机上存储明确的标识符),指纹识别通过读取已经存在的属性来工作:你的屏幕分辨率、GPU 型号、已安装字体、音频处理特征、JavaScript 引擎行为等数十项信息。这些属性组合后形成一个"指纹",通常对你的特定设备和浏览器配置来说是独一无二的。指纹识别不需要存储、不需要权限,任何用户同意机制都无法阻止。它在隐私浏览会话中持续存在,在 Cookie 删除后仍然有效,且跨不同网站工作。本文提供了浏览器指纹识别的全面概述:工作原理、收集什么信号、为什么传统防御失败,以及 BotBrowser 如何在浏览器引擎级别提供保护。

隐私影响

浏览器指纹识别已从学术好奇心发展为主流追踪技术。多项大规模研究记录了其普遍性和有效性。

普林斯顿大学的 Web 透明度项目(2016)爬取了排名前 100 万的网站,发现 5.5% 包含指纹识别脚本。到 2020 年,后续研究显示这个数字已增长到 10% 以上。最常见的指纹识别库针对 Canvas、WebGL、音频和字体信号。

EFF 的 Panopticlick/Cover Your Tracks 项目测试了超过 200,000 种浏览器配置,发现 83.6% 可以被唯一识别。即使在采取了隐私预防措施(阻止 Cookie、使用 VPN)的用户中,大多数仍然可以通过指纹识别单独追踪。

AmIUnique,来自 INRIA 的指纹识别研究项目,发现其数据集中的中位浏览器可以与 99.1% 的其他浏览器区分。只有 0.9% 的浏览器与至少一个其他浏览器共享相同的指纹。

商业指纹识别行业规模可观。多家公司向广告商、欺诈检测服务和分析平台销售指纹识别即服务产品。这些服务将数十个信号组合成一个跨会话和网站持续存在的单一标识符。

对于个人用户,浏览器指纹识别意味着清除 Cookie、使用隐身模式或切换网络都无法防止追踪。你设备的属性组合在整个网络上跟随你。

技术背景:指纹信号类别

浏览器指纹识别从多个类别收集信号。每个类别为整体指纹贡献熵(识别信息的比特数)。以下图表显示了主要信号类别及其大约的熵贡献。

浏览器指纹信号类别 浏览器 指纹 Navigator UA、平台、核心、内存 Canvas 2D 渲染、文本绘制 WebGL / WebGPU GPU 身份、渲染 音频 AudioContext、OfflineAudio 字体 已安装字体、文本指标 屏幕/窗口 分辨率、DPI、尺寸 CSS 信号 媒体查询、偏好 时间/性能 performance.now()、导航时间 引擎内部 栈深度、数学精度 网络 WebRTC、连接信息

navigator 对象是任何指纹识别脚本的第一站。它暴露了:

  • 用户代理字符串,包含浏览器名称、版本和操作系统详情
  • 平台,标识操作系统("Win32"、"MacIntel"、"Linux x86_64")
  • 硬件并发数,揭示 CPU 核心数
  • 设备内存,暴露 RAM 等级(仅 Chromium)
  • 语言,显示区域偏好
  • User Agent Client Hints,提供结构化的浏览器和平台数据

这些属性普遍可用,不需要权限,组合后可以识别数千种独特配置。详见 Navigator 属性保护

Canvas 和 2D 渲染

HTML5 Canvas API 在绘制文本、形状和图像时产生设备特定的输出。像素级渲染取决于 GPU、字体渲染引擎、抗锯齿实现和颜色管理。脚本绘制特定场景,读回像素数据并哈希它。结果在设备间变化但对给定设备是稳定的。Canvas 指纹识别是 Cookie 之后部署最广泛的追踪技术。详见 Canvas 指纹识别

WebGL 和 WebGPU

WebGL 通过渲染器字符串、能力参数和渲染输出暴露 GPU 身份。WebGPU 添加了结构化的适配器信息、特性集和详细的能力限制。这些 GPU API 一起提供了可用的最高熵指纹信号之一。详见 WebGL 指纹保护WebGPU 指纹保护

音频处理

Web Audio API 在通过振荡器、压缩器和分析器处理音频时产生平台特定的输出。不播放声音,不需要权限。输出取决于音频硬件、操作系统音频栈和浏览器引擎。详见音频指纹保护

字体

字体枚举揭示了哪些字体已安装,文本指标(字形宽度、边界框)因平台渲染引擎而异。已安装字体和文本指标的组合提供 8-10+ 比特的熵。详见字体指纹保护

屏幕和窗口

屏幕分辨率、色深、设备像素比、可用屏幕区域和窗口尺寸在硬件和操作系统配置间变化。内/外窗口尺寸和屏幕/可用屏幕尺寸之间的边距揭示操作系统的 UI 外壳。详见屏幕和窗口保护

CSS 媒体特性

CSS 媒体查询暴露显示能力、用户偏好(深色模式、减少动画)、指针类型和色域。这些值可以通过条件 CSS 资源加载在无 JavaScript 的情况下提取。详见 CSS 信号一致性

性能和时间

performance.now() 分辨率、导航时间、资源时间和执行速度因硬件和浏览器而异。时间信号难以控制,因为它们源自实际执行行为。详见性能时间指纹识别

引擎内部

JavaScript 栈深度(最大递归深度)在浏览器、平台和执行上下文间变化。这种低级信号反映了无法从 JavaScript 更改的引擎实现细节。详见栈深度控制

常见保护方法及其局限性

VPN

VPN 更改你的 IP 地址但对浏览器指纹识别完全没有影响。上述列出的每个指纹信号都由浏览器在本地生成。无论你通过 VPN 还是直接连接,你的指纹都是相同的。

隐身/隐私浏览

隐私浏览清除 Cookie 和本地存储,但不修改任何指纹信号。你的 Canvas 输出、WebGL 渲染器、音频处理、字体列表和屏幕分辨率在隐私模式下完全相同。

浏览器扩展

声称保护指纹的扩展在 JavaScript 级别操作。它们拦截 API 调用并修改返回值。这种方法有根本性的局限:

  • 覆盖不完整。 扩展必须挂钩每个相关 API。遗漏一个(如 OffscreenCanvas、AudioWorklet、CSS 媒体查询)会产生漏洞。
  • 可检测的修改。 JavaScript 属性覆盖可以通过原型检查、时间分析和交叉验证被检测到。
  • CSS 盲点。 扩展无法修改 CSS 媒体查询评估,它在渲染引擎级别操作。
  • 不一致。 更改一个值而不调整相关值会产生可检测的异常。报告 macOS 用户代理而 Canvas 渲染显示 Windows 风格文本抗锯齿是不一致的。

随机化

随机化指纹值(每次页面加载新的 Canvas 哈希、每次不同的音频指纹)创建了本身就是追踪信号的不稳定性。合法设备产生稳定的指纹。不稳定的指纹识别出积极试图防止追踪的用户。

Tor 浏览器

Tor 浏览器采取了最有原则的方法:标准化所有用户的所有指纹值。每个 Tor 浏览器报告相同的屏幕分辨率、字体列表、Canvas 输出和用户代理。局限在于 "Tor 浏览器" 本身成为身份。标准化的指纹将你识别为 Tor 用户,这是一个非常小的群体。

BotBrowser 的引擎级方法

BotBrowser 采取了根本不同的方法:通过完整的设备配置文件在 Chromium 渲染引擎级别控制指纹信号。而不是阻止、随机化或拦截单个信号,BotBrowser 配置浏览器引擎,使其表现得好像在配置文件的设备上运行。

完整设备配置文件

BotBrowser 配置文件描述了整个设备:操作系统、浏览器版本、GPU、音频硬件、屏幕配置、已安装字体、CPU、内存等。加载后,配置文件同时配置每个引擎子系统。所有信号都一致,因为它们都来自相同的配置文件。

引擎级控制

BotBrowser 在源代码级别修改 Chromium。Canvas 渲染、WebGL 参数、音频处理、字体枚举、navigator 属性、屏幕尺寸和时间行为都在内部控制。这意味着:

  • 没有 JavaScript 可见的属性覆盖
  • 没有可检测的原型修改
  • CSS 和 JavaScript API 返回相同的值
  • Worker 上下文和主线程一致
  • iframe 接收一致的值

跨平台操作

在 Linux 上运行时,你可以加载 Windows 配置文件。在 macOS 上运行时,你可以加载 Android 配置文件。引擎级控制足够深入,可以无论主机操作系统如何都产生平台特定的渲染行为。加载 Windows 配置文件时,Canvas 文本在 Linux 机器上以 Windows 风格抗锯齿渲染。

确定性噪声

--bot-noise-seed 标志提供确定性变化。每个种子产生独特、稳定的指纹。相同的配置文件和种子始终产生相同的指纹,跨会话、跨机器、跨操作系统。不同种子产生不同指纹。这给你明确的身份控制:相同种子等于相同身份,不同种子等于不同身份。

全面信号覆盖

BotBrowser 覆盖所有主要指纹类别:

信号类别保护机制
Navigator 属性所有属性的配置文件驱动值
Canvas 2D引擎级渲染控制 + 噪声
WebGLGPU 身份、参数和渲染
WebGPU适配器信息、特性、限制和渲染
音频音频处理管线控制 + 噪声
字体受控的字体列表和文本指标
屏幕/窗口配置文件驱动的尺寸和边距
CSS 媒体特性引擎级媒体评估
性能时间确定性性能的时间种子
栈深度引擎级递归限制控制
网络信息配置文件驱动的连接属性

配置和使用

基本用法

最简单的配置是加载配置文件:

chrome --bot-profile="/path/to/profile.enc" \
       --user-data-dir="$(mktemp -d)"

这个单一标志激活所有信号类别的保护。

完全确定性配置

chrome --bot-profile="/path/to/profile.enc" \
       --bot-noise-seed=42 \
       --bot-time-seed=42 \
       --bot-stack-seed=profile \
       --user-data-dir="$(mktemp -d)"

带代理和自动检测区域设置

chrome --bot-profile="/path/to/profile.enc" \
       --proxy-server=http://user:pass@proxy.example.com:8080 \
       --bot-config-timezone=auto \
       --bot-config-locale=auto \
       --bot-config-languages=auto \
       --bot-noise-seed=42 \
       --user-data-dir="$(mktemp -d)"

Playwright 集成

const { chromium } = require('playwright');

const browser = await chromium.launch({
  executablePath: '/path/to/botbrowser/chrome',
  args: [
    '--bot-profile=/path/to/profile.enc',
    '--bot-noise-seed=42',
    '--bot-time-seed=42',
    '--bot-stack-seed=profile'
  ]
});

const page = await browser.newPage();
await page.goto('https://example.com');

// 所有指纹信号现在由配置文件控制
const info = await page.evaluate(() => ({
  userAgent: navigator.userAgent,
  platform: navigator.platform,
  cores: navigator.hardwareConcurrency,
  screenWidth: screen.width,
  colorDepth: screen.colorDepth,
  devicePixelRatio: window.devicePixelRatio
}));
console.log(info);

Puppeteer 集成

const puppeteer = require('puppeteer');

const browser = await puppeteer.launch({
  executablePath: '/path/to/botbrowser/chrome',
  defaultViewport: null,
  args: [
    '--bot-profile=/path/to/profile.enc',
    '--bot-noise-seed=42',
    '--bot-time-seed=42',
    '--bot-stack-seed=profile'
  ]
});

const page = await browser.newPage();
await page.goto('https://example.com');

多配置文件目录

自动跨实例的配置文件轮换:

chrome --bot-profile-dir="/path/to/profiles/" \
       --bot-noise-seed=42 \
       --user-data-dir="$(mktemp -d)"

BotBrowser 在每次启动时从目录中随机选择配置文件。

验证

指纹一致性。 使用相同的配置文件和种子在两个独立会话中访问指纹测试网站(BrowserLeaks、CreepJS、AmIUnique)。报告的指纹应完全相同。

跨机器测试。 在两台不同的机器上运行相同的配置文件和种子。指纹应匹配。

信号类别验证。 单独检查每个主要信号类别:

  • Navigator 属性匹配配置文件
  • Canvas 哈希跨会话稳定
  • WebGL 渲染器匹配配置文件的 GPU
  • 音频指纹使用相同种子时稳定
  • 字体列表匹配配置文件的操作系统
  • 屏幕尺寸匹配配置文件

Headless/headed 一致性。 使用 --bot-config-window=profile 在 headless 和 headed 模式下运行相同测试。指纹应完全相同。

最佳实践

  • 始终使用配置文件。 不使用 --bot-profile 运行 BotBrowser 不提供指纹保护。配置文件是基础。
  • 使用 --bot-noise-seed 获得稳定身份。 没有种子,渲染噪声在会话间变化。种子确保可复现性。
  • 在 Puppeteer 中使用 defaultViewport: null 这防止 Puppeteer 覆盖配置文件显示设置。
  • 让 BotBrowser 自动检测区域设置。 --bot-config-timezone=auto--bot-config-locale=auto--bot-config-languages=auto 从代理 IP 派生区域设置以获得地理一致性。
  • 保持配置文件更新。 浏览器用户代理和能力随每个版本变化。使用 BotBrowser 配置文件仓库中的最新配置文件。
  • 不要手动覆盖单个属性。 配置文件确保内部一致性。覆盖一个属性而不调整其他属性会产生可检测的不匹配。
  • 与适当的代理结合。 指纹保护解决设备身份。网络身份(IP 地址、地理位置)需要代理。

常见问题

Q: 浏览器指纹识别和 Cookie 有什么区别? A: Cookie 是存储在你设备上的明确标识符。你可以看到、阻止和删除它们。指纹识别读取已经存在的属性(屏幕大小、GPU 型号等),不存储任何东西。你无法"清除"指纹,因为没有什么可以清除的。

Q: 指纹识别可以跨不同网站追踪我吗? A: 可以。如果两个网站使用相同的指纹识别库,或者相同的第三方追踪脚本嵌入在两个网站上,你的指纹可以在它们之间匹配。即使没有 Cookie 也是如此。

Q: 我的浏览器指纹有多独特? A: 根据研究,超过 80% 的浏览器具有独特的指纹。屏幕分辨率、GPU、字体、音频处理和其他信号的组合足以区分大多数用户。

Q: BotBrowser 会阻止指纹识别脚本吗? A: 不会。BotBrowser 不阻止任何脚本。相反,它控制脚本看到的内容。当指纹识别脚本收集你的 Canvas 哈希、WebGL 渲染器和音频指纹时,它获得的是来自加载配置文件的值,而不是来自你实际硬件的值。

Q: 我可以用 BotBrowser 进行正常浏览吗? A: 可以。BotBrowser 是一个完整的 Chromium 浏览器。所有 Web 功能(包括扩展、开发者工具和媒体播放)正常工作。指纹保护在后台透明运行。

Q: 我可以创建多少个独特身份? A: 每个配置文件和噪声种子的组合创建一个独特身份。通过多个配置文件和从 1 到 4,294,967,295 的种子,可能的独特身份数量实际上是无限的。

Q: 浏览器指纹识别合法吗? A: 合法性因管辖权而异。欧盟的 GDPR 和 ePrivacy 指令将指纹识别视为需要同意的追踪形式。在实践中,执行有限,大多数指纹识别发生在没有明确用户同意的情况下。BotBrowser 让你能够控制浏览器透露的信息。

Q: BotBrowser 可以与 Selenium 一起使用吗? A: BotBrowser 可以与任何能够使用自定义参数启动 Chromium 的自动化框架一起使用,包括 Selenium、Playwright 和 Puppeteer。

总结

浏览器指纹识别是一种普遍的追踪技术,通过设备和浏览器配置识别用户。它不使用 Cookie、不需要权限、用户不知情的情况下运行。VPN、隐身模式和浏览器扩展等传统保护只解决了问题的一部分,或引入了可检测的不一致。

BotBrowser 通过在 Chromium 引擎级别控制所有信号类别提供全面的指纹保护。完整的设备配置文件确保每个 API 面,从 navigator 属性到 Canvas 渲染到音频处理,都返回来自单一一致设备身份的值。--bot-noise-seed 标志使指纹确定性和可复现。结果是一个无论底层实际硬件如何都呈现一致、真实设备身份的浏览器。

有关特定指纹类别的详细覆盖,请参阅:

#浏览器指纹识别#Privacy#Protection#Tracking

让 BotBrowser 从研究走向生产

先用这些指南理解模型,再进入跨平台验证、隔离上下文和面向规模化的浏览器部署。