屏幕和窗口指纹:显示属性追踪
屏幕分辨率、色深和窗口尺寸如何创建唯一的指纹信号,以及如何控制显示身份。
简介
你的浏览器显示配置告诉网站很多关于你设备的信息。屏幕分辨率、色深、设备像素比、可用屏幕区域和窗口尺寸都可以通过标准 JavaScript API 访问,无需任何权限。这些值因设备和显示器配置而异,使它们成为浏览器指纹的有用组成部分。1920x1080 的 1x DPI 显示器不同于 2560x1600 的 2x DPI 显示器,也不同于 3840x2160 的 1.5x 显示器。与其他信号结合时,显示属性为追踪指纹贡献了有意义的熵值。本文解释屏幕和窗口指纹追踪的工作原理,以及 BotBrowser 如何通过其配置文件系统提供受控的、一致的显示身份。
隐私影响
显示属性从最早的追踪脚本起就是指纹追踪的一部分。EFF 的 Panopticlick 项目报告称,仅屏幕分辨率就提供约 4.8 比特的熵值,足以区分大约 28 个组。当与色深、设备像素比和可用屏幕区域(揭示任务栏大小和位置)结合时,组合显示指纹可以贡献超过 8 比特的熵值。
高 DPI 显示器、超宽显示器和多显示器设置的普及增加了显示多样性。十年前,大多数桌面用户使用 1920x1080 屏幕。今天,常见分辨率包括 2560x1440、3840x2160、2560x1600(MacBook)、2880x1800 以及各种超宽配置。移动设备因每个型号特定的分辨率和像素比增加了更多变化。
一种特别有效的技术是将屏幕分辨率与窗口尺寸结合。屏幕大小和窗口大小之间的差异揭示了操作系统 UI 边框的信息:任务栏高度、Dock 宽度、窗口装饰。这些边距在 Windows、macOS 和 Linux 之间以及操作系统版本之间不同。screen.height 和 screen.availHeight 之间 40 像素的间隙暗示 Windows 带底部任务栏。25 像素的间隙可能表示 macOS 带隐藏 Dock。
技术背景
屏幕属性
screen 对象提供显示信息:
screen.width/screen.height- 以 CSS 像素为单位的全屏分辨率。screen.availWidth/screen.availHeight- 可供浏览器窗口使用的屏幕区域(减去任务栏、Dock 等)。screen.colorDepth- 以每像素位数为单位的色深。在现代系统上几乎普遍为 24。screen.pixelDepth- 通常等于 colorDepth。
窗口属性
window 对象暴露内外尺寸:
window.innerWidth/window.innerHeight- 视口尺寸,不包括浏览器边框。window.outerWidth/window.outerHeight- 总窗口尺寸,包括浏览器边框(工具栏、标签页、滚动条)。window.screenX/window.screenY- 窗口在屏幕上的位置。
设备像素比
window.devicePixelRatio- 物理像素与 CSS 像素之间的比率。值为 2 意味着每个 CSS 像素映射到 2x2 的物理像素网格(常见于 Retina/HiDPI 显示器)。
CSS 媒体查询
媒体查询提供从 CSS 访问显示特征的途径:
@media (min-resolution: 2dppx) { /* HiDPI 样式 */ }
@media (color-gamut: p3) { /* 宽色域显示 */ }
@media (prefers-color-scheme: dark) { /* 深色模式 */ }
JavaScript 可以通过 window.matchMedia() 查询这些,提供另一种读取显示属性的途径。
为什么这些值会变化
显示属性取决于多个因素:
- 显示器硬件。 物理分辨率、尺寸和能力决定基础值。
- 操作系统显示设置。 缩放设置(100%、125%、150%、200%)影响物理像素和 CSS 像素之间的关系。
- 多显示器配置。 具有不同分辨率和缩放的多个显示器创建唯一配置。
- 浏览器窗口状态。 最大化、窗口化或全屏模式影响内外尺寸。
- 操作系统边框。 任务栏/Dock 的大小和位置影响可用屏幕区域。
这些因素的组合创建了高熵信号。使用 3440x1440 超宽显示器、1.25x 缩放、48 像素 Windows 任务栏的用户有非常独特的显示指纹。
常见保护方案及其局限性
浏览器扩展通常通过覆盖 screen 和 window 对象上的 JavaScript getter 来修改屏幕属性。这有几个问题。CSS 媒体查询可以独立于 JavaScript 读取真实值。visualViewport API 提供另一种视口尺寸读数。覆盖的 getter 可以通过原型检查和时序分析检测。
使用常见分辨率(将显示器设为 1920x1080)减少了唯一性,但不解决窗口尺寸、可用屏幕区域或设备像素比问题。在 HiDPI 显示器上还会牺牲显示质量。
随机化显示值创建物理上不可能的配置。1923 像素的屏幕宽度不对应任何真实显示器。1.37 的设备像素比不对应任何真实显示缩放设置。这些值可检测为合成的。
在虚拟机中运行配合受控的显示设置有帮助,但引入了虚拟机特定的信号。虚拟机显示驱动常报告标识虚拟化平台的特定能力集和参数组合。
Headless 浏览器模式呈现自身的挑战。默认 headless Chromium 使用 800x600 视口和设备像素比 1,这本身就是一个独特的指纹,因为很少有真实用户在该配置下浏览。
BotBrowser 的引擎级方案
BotBrowser 通过其配置文件系统在 Chromium 引擎级别控制所有与显示相关的属性。
完整的显示配置文件
当加载指纹配置文件时,BotBrowser 配置:
- 屏幕尺寸(
screen.width、screen.height、screen.availWidth、screen.availHeight)匹配配置设备。 - 窗口尺寸(
window.innerWidth、window.innerHeight、window.outerWidth、window.outerHeight)具有从配置文件派生的真实操作系统边框边距。 - 设备像素比匹配配置的显示配置。
- 色深和像素深度与配置设备一致。
CSS 媒体查询对齐
BotBrowser 确保 CSS 媒体查询返回与 JavaScript 属性一致的值。matchMedia('(min-width: 1920px)') 与 screen.width 一致。matchMedia('(resolution: 2dppx)') 与 devicePixelRatio 一致。CSS 和 JavaScript 显示查询之间没有差距。
操作系统边框模拟
外内窗口尺寸差异以及屏幕大小与可用屏幕区域之间的差异来自配置文件的目标操作系统。Windows 配置文件包含 Windows 典型的边框和任务栏尺寸。macOS 配置文件包含 macOS 典型的菜单栏和窗口装饰大小。
Headless 模式控制
在 headless 模式下,BotBrowser 应用配置文件的显示配置而非默认的 800x600。这意味着 headless 会话的显示属性与使用相同配置文件的 headed 会话无法区分。
配置和用法
基本显示保护
chrome --bot-profile="/path/to/profile.enc" \
--user-data-dir="$(mktemp -d)"
窗口和屏幕配置
# 使用配置文件的窗口设置(headless 默认)
chrome --bot-profile="/path/to/profile.enc" \
--bot-config-window=profile \
--bot-config-screen=profile
# 指定精确窗口大小
chrome --bot-profile="/path/to/profile.enc" \
--bot-config-window=1920x1080
# 指定精确屏幕大小
chrome --bot-profile="/path/to/profile.enc" \
--bot-config-screen=2560x1440
# 完整 JSON 自定义
chrome --bot-profile="/path/to/profile.enc" \
--bot-config-window='{"innerWidth":1920,"innerHeight":1080,"devicePixelRatio":2}'
# 使用真实系统尺寸(桌面 headed 默认)
chrome --bot-profile="/path/to/profile.enc" \
--bot-config-window=real \
--bot-config-screen=real
颜色方案控制
chrome --bot-profile="/path/to/profile.enc" \
--bot-config-color-scheme=light
Playwright 集成
const { chromium } = require('playwright');
const browser = await chromium.launch({
executablePath: '/path/to/botbrowser/chrome',
args: [
'--bot-profile=/path/to/profile.enc',
'--bot-config-window=profile',
'--bot-config-screen=profile'
]
});
const page = await browser.newPage();
await page.goto('https://example.com');
const screenInfo = await page.evaluate(() => ({
screenWidth: screen.width,
screenHeight: screen.height,
innerWidth: window.innerWidth,
innerHeight: window.innerHeight,
devicePixelRatio: window.devicePixelRatio
}));
console.log(screenInfo);
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-config-window=profile',
'--bot-config-screen=profile'
]
});
const page = await browser.newPage();
await page.goto('https://example.com');
注意 Puppeteer 中的 defaultViewport: null 设置。没有它,Puppeteer 会用自己的默认值覆盖视口,这会与配置文件的显示设置冲突。
验证
屏幕属性检查。 查询 screen.width、screen.height、screen.availWidth、screen.availHeight 和 screen.colorDepth。所有值应匹配配置文件的目标设备。
窗口尺寸检查。 查询 window.innerWidth、window.innerHeight、window.outerWidth、window.outerHeight。内外之间的边距对于配置的操作系统应是真实的。
DPI 检查。 验证 window.devicePixelRatio 匹配配置文件。检查分辨率的 CSS 媒体查询是否一致。
媒体查询一致性。 使用 window.matchMedia() 查询与显示相关的媒体特性,确认它们与 JavaScript 属性值一致。
最佳实践
- 在 Puppeteer 中使用
defaultViewport: null。 这防止 Puppeteer 覆盖配置文件的显示设置。 - 在 headless 模式中使用
--bot-config-window=profile。 这应用配置文件的窗口尺寸而非默认的 headless 视口。 - 将显示配置文件与用例匹配。 如果你的代理 IP 位于移动浏览常见的区域,考虑使用具有适当屏幕尺寸的移动配置文件。
- 不要设置不真实的分辨率。 1920x1080、2560x1440 和 1440x900 等值是常见的。1919x1079 等值不是。
- 考虑设备像素比。 高 DPI 配置文件报告更高的物理分辨率,DPR 为 2 或 3。确保你的配置文件的 DPR 与报告的屏幕大小一致。
常见问题
问:BotBrowser 是否处理多显示器检测? 答:BotBrowser 配置文件描述单个显示配置。配置文件的屏幕值代表报告给 Web 内容的主显示器。多显示器窗口移动追踪默认不暴露给网页。
问:加载配置文件后调整浏览器窗口大小会怎样?
答:window.innerWidth 和 window.innerHeight 会更新以反映实际窗口大小(在使用 --bot-config-window=real 的 headed 模式下)。在 headless 模式或使用 --bot-config-window=profile 时,值保持由配置文件控制。
问:颜色方案设置是否影响渲染?
答:是的。--bot-config-color-scheme=dark 使 CSS 媒体查询和 matchMedia() 中的 prefers-color-scheme: dark 为 true。实现了深色模式的网站会相应渲染。
问:headless 和 headed 模式下屏幕指纹是否相同?
答:使用 --bot-config-window=profile 和 --bot-config-screen=profile 时,是的。没有这些标志时,headed 模式默认使用真实窗口/屏幕尺寸,而 headless 使用配置文件。
问:BotBrowser 是否支持超宽或非标准宽高比? 答:BotBrowser 配置文件可以包含真实硬件上存在的任何屏幕配置。如果配置文件是从超宽显示器的设备采集的,这些尺寸就可用。
问:visualViewport API 如何与 BotBrowser 的保护交互?
答:visualViewport API 返回与受控窗口尺寸一致的值。window.innerWidth 和 visualViewport.width 之间没有差距。
总结
屏幕和窗口属性是最常收集的指纹信号之一,因为它们不需要权限且在不同硬件配置之间差异很大。BotBrowser 在引擎级别控制所有与显示相关的值,包括屏幕尺寸、窗口尺寸、设备像素比、色深和 CSS 媒体查询。通过加载完整的指纹配置文件,所有显示信号与真实设备配置对齐,headless 会话产生与 headed 会话相同的显示指纹。
相关主题请参阅什么是浏览器指纹、CSS 信号一致性、Navigator 属性保护以及确定性浏览器行为。