返回知识中心
指纹

getClientRects 指纹:DOMRect 一致性检查

分析 CreepJS 的 DOMRect 检查,区分空几何、文本片段、变换和报告缺失,避免把几何差异直接当成设备身份。

BotBrowser Team

文档中心

想直接进入 指纹 文档吗?

这篇文章属于知识中心的指南库。若你要步骤化配置、参考说明和持续更新,请直接进入对应 docs 分区。

getClientRects 指纹分析的是浏览器布局几何,而不是 Client Hints 请求头。矩形变化可能来自被选中的盒、文本片段或坐标上下文变化。BotBrowser 文档提供默认关闭的 ClientRects 确定性噪声,以及用于复现字体度量的种子;这些控制不能证明所有几何路径一致,也不能证明 CreepJS 会接受结果。有效的 DOMRect 报告需要先区分测量对象、API 与具体一致性规则,再判断原因。

观看视频

这段视频为英语讲解,沿文章同一问题展开:CSSOM View 的四个几何接口返回不同形状,因此片段数量、归约后的矩形和选区的矩形不能被当成一个数值来读。视频展示三种报告状态(缺失、空列表、零尺寸矩形)、包围矩形的三条归约分支,以及受控同源夹具上的两段录制控制台会话。两条原生表达式由人手输入,第三条读数由夹具面板打印。视频不涉及网站收集行为,也不给出第三方判定;几何差异不能识别设备、个人或修改手段。音频为英语。

TL;DR

  • Element.getClientRects() 返回盒片段列表;getBoundingClientRect() 将列表归约为一个矩形,空列表和零尺寸另有分支。列表长度与包围尺寸回答不同问题。
  • Range 几何可以描述选中的文本片段,不能直接等同于元素的完整边框盒。
  • CreepJS 修订 10aa6724cd33a1015db1574211890518cd04f0cc 保存四组几何数组,执行若干特定测试元素的检查,而不是通用设备身份测试。
  • DOMRect 报告缺失、片段列表为空、矩形字段包含零,是不同状态。
  • lied 表示该修订的一致性判断,不能确定谁改了数值、哪个设备生成结果或外部网站会如何决策。

Contents

Element 和 Range 分别产生片段列表或归约后的矩形;报告缺失、空列表与退化矩形是不同状态。

四类几何接口

CSSOM View 根据元素的 CSS 盒定义 Element.getClientRects()。跨多行的行内元素可以产生多个片段,而非一个连续矩形。列表保留片段之间的区别,包括零尺寸片段。没有关联 CSS 盒的元素返回空列表。因此,“ClientRects 值”并不完整:它可能指整个列表、选中的一项、派生并集,或者多个测试元素的摘要。

Element.getBoundingClientRect() 则将几何归约成一个矩形。规范区分空列表、列表内每个矩形都满足宽度或高度为零,以及剩余的并集情况。第一种返回各字段为零的矩形;第二种返回列表首个矩形。否则,并集包含高度或宽度不为零的矩形,这里使用 OR 条件。最后一条不能覆盖前面的例外分支。位置非零但高度为零的矩形,不等同于根本没有片段。

MDN 将元素包围矩形描述为包含内边距与边框、坐标相对于视口的矩形。拿它与 width: 100px 比较时需要考虑盒模型,而不能要求声明宽度等于所有返回宽度。内容宽度和外层边框盒是不同的量。只保存四舍五入宽度的报告,会丢失 API 选择和对应盒模型。

Range.getClientRects() 针对文档中被选中的部分。对应的包围方法归约该范围的列表,同样区分空列表、全零尺寸分支与并集分支。选中的子串不必与容器元素有相同边界:前者描述被选文本,后者可能包含整个盒。文本测量分析 讨论独立的 Canvas measureText() 表面;其 TextMetrics 字段不是 DOMRect 片段列表。

API返回形态保留语义的比较方式
Element.getClientRects()盒片段构成的 DOMRectList相同元素与片段位置
Element.getBoundingClientRect()由包围算法得到的一个 DOMRect相同元素与视口上下文
Range.getClientRects()选定范围的片段列表保留选区边界和文本布局
Range.getBoundingClientRect()范围列表归约出的一个矩形保留范围及空列表、零尺寸分支

矩形接口提供 x、y、width、height、top、right、bottom 和 left。读取程序可以序列化这些字段,但序列化不会让原始对象具有相同含义。MDN 还区分只读列表接口和 JavaScript 数组。将列表转换为数组,只改变容器,不改变产生各项的布局操作。数组摘要仍不能独立解释某个片段为何变化。

固定修订的 CreepJS 比较什么

该修订的公开 DOMRect 模块将八个字段复制到普通对象中,返回四个分别命名的数组:elementClientRects、elementBoundingClientRect、rangeClientRects 和 rangeBoundingClientRect。对于两个列表 API,测试元素的采集读取列表第一项,而不是任意多行页面中的每个矩形。这项源码选择很重要:显示一个分组摘要,不代表所有元素的每个片段都被检查过。

同一模块还有优先选择矩形的辅助函数。它根据此前记录的 API 疑点,在元素列表、元素包围矩形、范围列表和范围包围矩形之间选择。这个函数与四数组采集是分开的。说“CreepJS 始终使用包围矩形”会抹掉分支结构;反过来,函数的替代路径也不表示四个 API 对任意选区都应返回相同矩形。

移动检查先保存测试元素初始 top,添加位移类,读取位移后的值,移除类,再次读取。它比较相对于位移后测量的恢复情况,并不是要求布局变化后矩形仍不变。恢复检查失败与初始位置变化,是不同的比较;仅记录“位置变了”无法区分它们。

字段运算检查比较已采集元素矩形的对边、尺寸和原点字段之间的关系。另一项检查比较两个预期匹配的特定测试元素的左右边界。二者是不同谓词:内部字段关系一致时,两个元素仍可能不同。CreepJS 信号分组分析 说明分组判断为什么必须保留作用范围,而不能变成关于某个人或所有浏览器 API 的结论。

源码定义的检查比较对象单独失败不能证明什么
位移与恢复初始、位移后、恢复后的位置位置差异的原因
矩形字段运算边界、原点和尺寸的关系哪个软件层提供了值
相同测试元素两个特定元素的指定边界任意页面元素都应相等
旋转测试元素带引擎和 DPR 条件的源码预期所有浏览器通用的几何特征
幽灵测试元素记录的八个字段是否全部为零所有不可见元素都必须是零几何

旋转分支依赖该修订的引擎分类,其中一个分支还依赖 devicePixelRatio。预期值属于具体实现的假设,不是标准符合性表。将一个已知摘要复制到报告里,既不能提供底层矩形,也不能证明原始布局被测量过。可支持的结论只是该修订将特定测试元素与有条件的预期比较,而不是不匹配就能识别操作系统。

lied 还可能在这些几何检查前,继承关于四个几何 API 或 String.fromCodePoint 的既有疑点。因此,最终为真不能确定哪个本地谓词最先改变它。模块捕获失败、记录测试未通过并且不返回结果;渲染函数在报告缺失时单独展示阻止状态。这与成功采集到含零数组是不同路径。这里没有声称实际运行过 CreepJS。

会改变比较的布局条件

内容相对于视口移动时,视口坐标会变化。MDN 在解释 getBoundingClientRect() 时明确提到滚动。文档滚动前后的比较已经改变了输入,即使元素 CSS 宽度没有变化。加上滚动偏移可以计算文档坐标,但应明确标记为派生值,而不能悄悄与原始视口坐标比较。

换行会改变片段边界。同一个文本区段在窄列与宽列中可以具有不同的 DOMRectList.length。包围矩形汇总片段,可能包含没有任何一行文本占据的空间。只比较包围范围会掩盖片段变化,只看第一片段又可能漏掉后续所有行。两者都不能证明字体被替换。

CSS 变换会影响几何 API 描述的矩形。因此,旋转测试元素应在相同旋转角度和参考原点下比较,而不是与未旋转 CSS 尺寸比较。包围矩形仍是外部范围,不是可见多边形的轮廓。这就是旋转专用检查需要测试上下文的原因。没有额外几何运算时,测得宽度不能直接当作旋转边的长度。

Range 选区增加了另一项输入:选中的节点或文本偏移。将整个元素改选为一个子串,可以合理地改变范围列表,同时元素自身的盒保持不变。CSSOM View 范围算法对选中文本与元素盒也有不同处理。报告只写 Range.getClientRects() 却不保留选区,就不足以精确比较两次“同一页面”的采集。

字体配置属于布局上下文,但矩形变化并不是一次字体名称查询。字体可用性、替代字体、文本内容、容器宽度与样式,都可能影响指定测试元素。字体测量文档 说明 ClientRects 控制,不提供任意文本、选区和布局的参考 DOMRect。种子解决文档所述噪声的可复现性,而不是所有页面布局变化来源。

CreepJS 幽灵检查也必须绑定具体测试元素。“人眼不可见”可以包含不同渲染状态,不定义唯一 CSS 盒模型。屏幕外的元素可能仍参与布局;没有关联盒则属于另一条 API 路径。将幽灵检查推广成所有不可见元素的通用规则,会把源码具体条件换成更宽泛、缺少支持的断言。

DOMRect 报告状态矩阵

第一项判断是是否取得几何。读取程序异常、空片段列表和零尺寸返回矩形需要不同记录。把所有失败替换成零矩形,会破坏区别,让下游一致性检查看似处理了从未采集的数据。报告应用自行选择的 null 也不是原生 DOMRectList 结果。

观察到的状态有边界的解释后续比较输入
读取程序没有返回报告报告缺失,原因未确定采集阶段及可用错误类别
列表存在且 length === 0该 API 调用没有返回片段元素关联盒或范围选区上下文
矩形宽度或高度为零已有几何,但某维度退化API、位置与另一维度
列表长度变化片段结构不同相同文本、宽度、选区与布局时机
字段运算谓词失败字段不符合该项比较原始字段与谓词名称
只有分组摘要变化某处序列化输入不同先定位数组、测试元素与字段

这些是根据来源构造的判断场景,并非浏览器实测结果。例如,假设先得到空列表,再得到零包围矩形,可以符合规范的空列表归约,不能证明检测器发现了修改。相反,一份声称列表读取成功却不保存列表长度的报告,也不能将该场景与序列化器自行补入的缺失值区分。

第二个假设场景是多行文本在容器变窄后产生更多片段。有用结论是布局输入与片段结构变化,不预测具体宽高,也不识别设备。第三个场景保持元素不变,只改选中的子串:范围结果改变,元素级比较却可能稳定。各场景都保留实际提出的 API 问题。

第四个场景是只有 CreepJS 总评,没有具体原因。最终 lied 不足以区分继承的几何或 String.fromCodePoint 疑点、恢复失败、字段运算失败,以及测试元素的专用预期。读取模块给出的具体诊断原因,比对布尔值猜测原因更有信息量。这不要求采集用户页面全部矩形,也不要求向第三方导出可复用指纹。

有边界的比较记录

最小记录无需保留整页文本或所有几何值,就可以回答解释问题。记录 api、不敏感的测试元素标识、选择类型、适用时的列表长度、采集状态和具名比较规则。解释 CreepJS 专用判断时加上源码修订。底层测量方法标准化,不代表检测规则也成了标准:API 算法与检测器预期属于不同层。

记录字段对解释的影响
api区分 Element/Range 与列表/包围结果
selectionType区分元素选区与文本子串
fragmentCount保留空列表与分片状态
coordinateSpace标明视口坐标或派生转换
layoutContext标明相关宽度、滚动与旋转条件
collectionState区分取得结果、空结果和采集失败
rule 与 sourceRevision将判断绑定到实际谓词和代码

上述字段名是一份建议的支持记录结构,除明确列出的源码数组外,并不是 CreepJS 输出键。若采集在取得列表前失败,不应写 fragmentCount: 0。也不应把缺失判断替换为空字符串,否则看起来像已经执行比较但没有发现问题。数据最小化和正确表示状态,都服务于同一个诊断目标。

BotBrowser 文档中的 --bot-noise-client-rects=true 用于开启确定性噪声,默认关闭。--bot-noise-seed 用于文档所述的可复现字体度量。这些说明都不能证明 Element 与 Range 方法覆盖一致、所有检测器特定运算预期保留、匿名性或服务接受结果。那些结论需要各自证据。文本度量另有 --bot-noise-text-rects=true,不能默认将它替代 ClientRects 控制。

比较报告时,可执行顺序是先确定 API 与状态,再检查选区和布局输入是否匹配,最后检查具名谓词。如果缺少这些输入,剩下的只是原因未明的几何差异。将它归为某种操作系统、设备型号或修改机制,会超出记录支持范围。最小后续动作是复现那个具体测试元素,而不是扩展采集无关身份信号。

ClientRects 信号常见问题

ClientRects 就是 Client Hints 吗?

不是。getClientRects() 是几何方法,Client Hints 通过另一套机制传递浏览器信息。名称相似不代表请求头能证明元素布局,DOMRect 报告也不能确定实际发送了哪些请求头。

摘要变了就知道哪个矩形变了吗?

不知道。分组摘要汇总序列化输入;没有数组名、测试元素与底层字段,就无法定位差异。它可以支持进一步检查该分组,但不能独立确定变化输入及原因。

Element 与 Range 几何必须始终匹配吗?

不必须。元素盒和文本选区可以覆盖不同内容。某个测试元素中成立的关系,不能推广到任意选区、多行文本或变换后的盒。

零矩形能证明采集被阻止吗?

不能。空列表归约可能返回零矩形,退化盒又是另一个状态。CreepJS 报告缺失的展示路径单独存在。解释零之前,应保留调用到底得到列表、矩形还是根本没有报告。

旋转测试元素的预期属于网页标准吗?

不属于。固定源码使用带引擎与 DPR 条件的分支。CSSOM View 定义几何方法,不定义检测器的预期摘要。CreepJS 新修订可以修改分支,而 API 名称不变。

设置种子能保证任何环境结果都相同吗?

不能。文档所述种子针对可复现噪声。文本、布局宽度、选区、变换或坐标上下文不同,仍会改变交给几何 API 的问题。单个设置不能证明跨设备等价或检测结果。

来源

实践结论

有效的 getClientRects 指纹报告需要说明 API、所选对象和具体比较。保留空列表、退化与失败状态,将源码里的 CreepJS 规则和标准几何语义分开。若只剩摘要或布尔值,原因仍未解决。在更改浏览器设置或判断设备身份之前,先核对缺失的 API 或测试元素上下文。

#浏览器指纹识别#字体#隐私

本文属于指南: 什么是浏览器指纹?原理、风险、信号与隐私边界

让 BotBrowser 从研究走向生产

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