WebGL 指纹:为什么改了 UA,平台还是能读到你的显卡型号
一、改 UA 为什么对这件事没用先建立一个直觉UAUser-Agent是浏览器自己说的话而 WebGL 是浏览器替你报的硬件参数。前者是一段你随时能改的字符串后者直接来自 GPU 和驱动。所以「改了 UA 就换了身份」这个说法从根上就是错的。UA 只是指纹里权重很低的几十项之一而你真正没改动的是那块物理显卡。WebGL 能读到显卡靠的是一个扩展WEBGL_debug_renderer_info。它开放了两个参数参数返回什么UNMASKED_VENDOR_WEBGLGPU 厂商名UNMASKED_RENDERER_WEBGL完整 GPU 型号 渲染后端 shader 版本这两个参数和 UA 没有任何关系。你在 UA 里写iPhone也好、Pixel也好WebGL 那一栏读出来还是你的真实显卡。二、一条字符串里藏着多少信息拿 Windows 上 Chrome 读到的典型值举例ANGLE (NVIDIA, NVIDIA GeForce RTX 3060 Laptop GPU Direct3D11 vs_5_0 ps_5_0, D3D11)这一条字符串拆开是五层信息片段含义ANGLEWindows 上 Chrome 用的图形翻译层把 OpenGL ES 调用翻译成 Direct3DNVIDIA厂商GeForce RTX 3060 Laptop GPU具体型号 笔记本/桌面形态Direct3D11渲染 API 版本vs_5_0 ps_5_0顶点/片元着色器版本所以同一个显卡换不同的平台字符串会不一样——ANGLE前缀是 Windows 专属macOS 走 Metal 会变成类似ANGLE (Apple, ANGLE Metal Renderer: Apple M3 Pro, ...)Linux 走 Mesa 又是另一种格式。但无论怎么变它都能把一个真实的硬件型号报出来。型号 形态 渲染 API 着色器版本这已经能精确锁定到哪一代、哪个档次。三、关键参数对照表除了型号WebGL 还暴露一组能力参数。这些参数的重要之处在于即使型号字符串被屏蔽它们仍然能读。常用项如下参数说明示例量级VERSIONWebGL 版本字符串WebGL 1.0 / 2.0SHADING_LANGUAGE_VERSION着色语言版本WebGL GLSL ES 1.0MAX_TEXTURE_SIZE最大纹理尺寸16384主流独显MAX_VIEWPORT_DIMS最大视口尺寸16384×16384MAX_RENDERBUFFER_SIZE最大渲染缓冲16384MAX_VERTEX_ATTRIBS最大顶点属性数16MAX_VERTEX_TEXTURE_IMAGE_UNITS顶点纹理单元32MAX_TEXTURE_IMAGE_UNITS片元纹理单元32MAX_VARYING_VECTORS可变向量数30MAX_FRAGMENT_UNIFORM_VECTORS片元常量向量数1024这些数字不是乱写的——它们由 GPU 的硬件规格决定不同厂商、不同代际之间会有可区分的差异。把它们组合起来即使没有型号字符串也已经是一组能用来区分设备的信号。四、被忽略的一点屏蔽了型号还有能力参数这是大多数人没意识到的地方「屏蔽 WebGL 指纹」和「屏蔽显卡型号字符串」是两回事。Brave 的做法是直接屏蔽WEBGL_debug_renderer_info这个扩展拿到的扩展对象是 nullFirefox 开privacy.resistFingerprinting会把型号伪装成通用值。这些手段确实能挡住型号字符串那一层。但能力参数那一层很多情况下仍然可读——MAX_TEXTURE_SIZE、MAX_VIEWPORT_DIMS、扩展列表的长度和内容并不都随型号一起被隐藏。这和第 1 篇讲 Canvas、第 3 篇讲 WebRTC 是同一个道理只要返回一个被改动过的值就存在被还原或被失效的可能真正干净的是什么都不返回。而 WebGL 恰恰是一个你很难让它什么都不返回又保持正常功能的接口。五、动手查一段代码 一张记录表F12 打开控制台粘下面这段代码回车// WebGL 指纹读取脚本// 用法F12 打开控制台 - 粘贴 - 回车// 作用读取显卡型号UNMASKED 系列、能力参数、扩展数量并判断当前渲染环境(function(){use strict;varcanvasdocument.createElement(canvas);varglcanvas.getContext(webgl)||canvas.getContext(experimental-webgl);if(!gl){console.log(%c[结论] 本浏览器拿不到 WebGL 上下文。,color:#c0392b;font-weight:bold);console.log(可能原因浏览器禁用了 WebGL、或当前环境如无 GPU 的虚拟机、关闭了硬件加速不支持。);console.log(注意WebGL 不可用本身也是一个可被识别的特征未必等于“更安全”。);return;}functionp(name){try{returnString(gl.getParameter(gl[name]));}catch(e){return读取失败;}}// 能力参数 —— 这些在 debug 扩展被屏蔽后通常仍然可读varcaps{GL_VERSION:p(VERSION),SHADING_LANGUAGE_VERSION:p(SHADING_LANGUAGE_VERSION),MAX_TEXTURE_SIZE:p(MAX_TEXTURE_SIZE),MAX_VIEWPORT_DIMS:p(MAX_VIEWPORT_DIMS),MAX_RENDERBUFFER_SIZE:p(MAX_RENDERBUFFER_SIZE),MAX_VERTEX_ATTRIBS:p(MAX_VERTEX_ATTRIBS),MAX_VERTEX_TEXTURE_IMAGE_UNITS:p(MAX_VERTEX_TEXTURE_IMAGE_UNITS),MAX_TEXTURE_IMAGE_UNITS:p(MAX_TEXTURE_IMAGE_UNITS),MAX_VARYING_VECTORS:p(MAX_VARYING_VECTORS),MAX_FRAGMENT_UNIFORM_VECTORS:p(MAX_FRAGMENT_UNIFORM_VECTORS)};varextgl.getExtension(WEBGL_debug_renderer_info);varvendor扩展被屏蔽拿不到;varrenderer扩展被屏蔽拿不到;if(ext){vendorString(gl.getParameter(ext.UNMASKED_VENDOR_WEBGL));rendererString(gl.getParameter(ext.UNMASKED_RENDERER_WEBGL));}varextCount0;try{extCount(gl.getSupportedExtensions()||[]).length;}catch(e){}console.log(%c 一、显卡型号UNMASKED 系列,font-weight:bold;font-size:13px);console.log(UNMASKED_VENDOR_WEBGL vendor);console.log(UNMASKED_RENDERER_WEBGLrenderer);console.log(debug 扩展是否可用(ext?可用:被屏蔽Brave / Tor / Safari 会走到这里));console.log(%c 二、能力参数debug 扩展被屏蔽后仍可读,font-weight:bold;font-size:13px);if(console.table){console.table(Object.keys(caps).map(function(k){return{参数:k,值:caps[k]};}));}else{Object.keys(caps).forEach(function(k){console.log(kcaps[k]);});}console.log(支持的扩展数量extCount);console.log(%c 三、结论 ,font-weight:bold;font-size:13px);if(extrenderer.indexOf(SwiftShader)-1){console.log(%c! RENDERER 里出现 SwiftShader说明当前是 CPU 软渲染 —— 常见于虚拟机、关闭硬件加速、或驱动被拉黑的环境。,color:#e67e22);}elseif(ext){console.log(%c× 能读到真实显卡型号。,color:#c0392b);console.log( 改 UA、改语言、改屏幕参数都不会影响这一项 —— 它直接来自 GPU 硬件。);}else{console.log(%c√ debug 扩展被屏蔽拿不到真实显卡型号字符串。,color:#27ae60);console.log( 但要继续看「能力参数」那一组 —— 它们仍可能暴露 GPU 的型号与代际。);}console.log();console.log(提示不同浏览器结果不同Brave 屏蔽 / Firefox RFP 伪装 / Chrome 直出。);console.log(提示请在你实际跑业务的那个浏览器配置里测而不是用一个干净的新配置测。);})();它分三块输出显卡型号UNMASKED 系列、能力参数、结论。结论会区分三种情况——读到真实显卡 / SwiftShader 软渲染 / 扩展被屏蔽。10 组真机取值记录表下面是你要自己填的部分也是这篇能压过竞品软文的地方。把你的每台机器、每个环境跑一遍把UNMASKED_RENDERER_WEBGL那一栏抄下来环境编号浏览器RENDERER 读出值VENDORMAX_TEXTURE_SIZE备注物理机/虚拟机/云桌面01020304050607080910填这张表时注意三件事同一块物理 GPU 上跑的多个环境RENDERER 字符串会高度一致——这不是巧合是它们共用同一块硬件。虚拟机里如果出现Google SwiftShader说明在走 CPU 软渲染没有透传 GPU或硬件加速被关。SwiftShader 本身也是一个可识别的特征。两台看起来一样的机器只要显卡型号或驱动版本不同字符串就会不同——这也是为什么填表比背模板有用。六、各浏览器现在的处置方式浏览器对 WebGL 型号的处理说明Chrome / Edge直出真实值默认无防护WEBGL_debug_renderer_info可读Firefox默认直出开privacy.resistFingerprinting后伪装成通用值FirefoxRFP伪装型号变成通用字符串部分能力参数被掩盖Brave屏蔽扩展 逐站随机化Shields 激活时扩展对象为 null其余参数加噪Safari默认屏蔽该扩展型号不可读Tor Browser安全级别下禁用 WebGLSafer/Safest 级别直接拿不到上下文七、三个还在流传的误解误解一改了 UA 就换了身份。UA 是自报家门显卡是硬件实况。前者改得再彻底后者一个字没变。误解二屏蔽了 renderer 字符串WebGL 就干净了。型号挡住了能力参数、扩展列表还在。这部分依然携带可区分的硬件信息。误解三虚拟机里的 WebGL 都一样都是 SwiftShader。SwiftShader 本身是特征而且走了软渲染这件事恰恰说明你处在某个特殊环境里。一堆环境全部报 SwiftShader反而更容易被归成一类。八、为什么这件事在多店铺场景里重要回到「多店铺环境隔离」的语境结论很直接如果多个店铺环境跑在同一块物理 GPU上那么无论你把 UA、语言、时区、屏幕参数改成什么样它们的UNMASKED_RENDERER_WEBGL字符串和那一组能力参数天然就是一致的——因为硬件没变过。环境隔离如果只做在能改的软件参数这一层显卡这一项就会成为一个稳定的、跨环境不变的锚点。这也是为什么说真正需要被隔离的是那些你改不动的东西而不是那些你能改的东西。九、自查清单每个店铺环境跑一遍第五节的脚本把 RENDERER 值抄进记录表对照同一块物理 GPU 上的多个环境确认它们的取值是否一致虚拟机环境是否出现 SwiftShader是否属于预期内的软渲染是否有环境意外读到真实显卡型号该屏蔽的没屏蔽浏览器更新后重测——驱动、ANGLE 版本都会改变返回值这份清单的作用是帮你判断显卡这一层自己的多个环境之间是什么样的关系。任何涉及环境隔离的具体操作请以相关平台的官方规则和你自己的合规要求为准。你的WEBGL_debug_renderer_info读出来是真实显卡型号还是通用值 / SwiftShader把你跑出来的 RENDERER 那一串贴在评论区看看型号可以打码。相关阅读[第 1 篇] 亚马逊判定账号关联时Canvas 指纹这一项到底在比什么[第 3 篇] 换了 IP 还是被关联WebRTC 泄露本地 IP 的三种触发路径[待发布] 用 BrowserLeaks 给自己做个指纹体检报告逐项解读本文所述为浏览器与图形 API 的客观机制说明用于理解指纹构成不构成任何操作建议。相关平台规则请以官方最新公告为准。

相关新闻

SugarNMSTool:面向工业质检的可配置NMS后处理工具

SugarNMSTool:面向工业质检的可配置NMS后处理工具

简介:SugarNMSTool是一款面向网络管理员与运维工程师的轻量级SNMP设备发现与管理工具,专为识别和监控开启SNMP服务的华为交换机设计,可快速定位网络中符合条件的设备,显著提升日常巡检、故障排查与批量状态采集效率。资源包共8个文…

2026/10/11 1:43:37 阅读更多 →
BDD100K人车检测数据集:YOLOv5-v10开箱即用双格式训练资源

BDD100K人车检测数据集:YOLOv5-v10开箱即用双格式训练资源

简介:本资源是面向深度学习目标检测初学者与进阶实践者的BDD100K人车识别数据集,专为YOLO系列(v5至v10)、Faster R-CNN、SSD等主流模型训练优化设计,解决交通场景下行人、车辆细粒度识别的数据需求。压缩包共2000个文件…

2026/10/11 1:43:37 阅读更多 →
07-软件配置与变更管理

07-软件配置与变更管理

第 7 章 软件配置与变更管理 学习目标 理解配置管理(CM)的目标:可追溯、可复现、可回滚掌握配置项、基线、配置库的概念掌握 Git 分支模型与标签策略理解构建管理与制品管理掌握变更控制流程(CCB)掌握发布管理与回滚预案7.1 配置管理的目标 软件配置管理(Configuration Managem…

2026/10/11 1:42:37 阅读更多 →

最新新闻

Codex封装Skill三步法:从一次性对话到可复用自动化工作流(TaoToken 统一 Key 接入版)

Codex封装Skill三步法:从一次性对话到可复用自动化工作流(TaoToken 统一 Key 接入版)

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 2:36:08 阅读更多 →
langchain 模型 - 聊天模型 (js版):用 TaoToken 统一 Key 跑通 ChatOpenAI 与 ChatMessage

langchain 模型 - 聊天模型 (js版):用 TaoToken 统一 Key 跑通 ChatOpenAI 与 ChatMessage

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 2:36:08 阅读更多 →
GNSS-R海面高度反演:物理模型与机器学习融合的实战解析

GNSS-R海面高度反演:物理模型与机器学习融合的实战解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 2:36:08 阅读更多 →
机器学习赋能边坡安全监测:从位移预测到事前预警的实践指南

机器学习赋能边坡安全监测:从位移预测到事前预警的实践指南

简介:一份聚焦机器学习赋能边坡安全的前沿学术资源,面向岩土工程、地质灾害与智能防灾领域的研究人员和工程师。内容系统梳理随机森林、XGBoost、GRU等主流模型在边坡稳定性评估与滑坡预测中的应用,并结合三峡库区等实际案例,展示…

2026/10/11 2:36:08 阅读更多 →
PCIe Gen3到Gen5信号调理IC选型:Redriver/Retimer

PCIe Gen3到Gen5信号调理IC选型:Redriver/Retimer

机箱里明明只有几十厘米的链路,PCIe信号却在背板上衰减到接收端几乎认不出原来的样子。这是我第一次做高速链路调试时遇到的场景。后来给链路上加了一颗TI德州仪器的信号调理芯片,眼图从模糊一团变成明明白白的两层,才真正意识到PCIe、SAS、S…

2026/10/11 2:36:08 阅读更多 →
Java 后端不做 Agent?Spring AI + MCP 多工具编排实战,纯 Java 也能落地 TaoToken 统一 Key 通道

Java 后端不做 Agent?Spring AI + MCP 多工具编排实战,纯 Java 也能落地 TaoToken 统一 Key 通道

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 2:35:08 阅读更多 →

日新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 5:23:50 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 21:32:20 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 10:38:42 阅读更多 →