WebGL 不僅用於炫酷的網頁特效,還能透過 GPU 渲染差異精準追蹤用戶。深入了解 WebGL 指紋如何提取顯示卡與驅動資訊,以及有哪些有效的防範手段。
WebGL 指紋透過查詢你的顯示卡硬體、並觀察它算繪 3D 場景的具體方式來辨識裝置。由於顯示卡型號、驅動程式版本與作業系統的每一種組合都會產生略有差異的輸出、並回報略有不同的能力參數,網站無需任何授權、Cookie 或本機儲存,就能讀取你的 GPU 廠商與算繪器字串、列舉支援的擴充功能與數值上限,並把算繪出的影像雜湊成一個穩定的識別碼。這使得 WebGL 成為現代瀏覽器指紋中資訊熵最高的訊號之一。
WebGL 是什麼,為何會暴露硬體身份
WebGL 是一套 JavaScript API,讓網頁能夠低階地存取 GPU,實現硬體加速的二維與三維圖形算繪。它本質上是瀏覽器對 OpenGL ES 的繫結,這意味著當你呼叫 WebGL 時,請求會穿過瀏覽器、穿過圖形驅動程式,一路抵達機器內部那塊實體顯示卡。
正是這種深層存取讓它成為指紋蒐集的富礦。為了高效繪圖,WebGL 必須暴露硬體的能力——支援多大的材質、有哪些可選特性、著色器如何對浮點數取整。同時它產生的輸出也因硬體而異:同一段繪製指令,在 NVIDIA 顯示卡、Apple GPU 與 Intel 內顯上會得到略有差別的像素,因為它們對點陣化、反鋸齒與浮點運算的實作各不相同。
WebGL 訊號大致分為兩類:宣告型中介資料(顯示卡自我回報的字串與數值)以及算繪輸出(實際繪製場景時產生的像素)。兩者共同補充了 Canvas 指紋偵測所探測的二維算繪路徑,也一起匯入我們在瀏覽器指紋完整指南中描述的整體圖像。
高資訊量的資料點
顯示卡廠商與算繪器字串
WebGL 中辨識度最高的單項訊號,是未遮罩的廠商與算繪器字串。預設情況下標準的 VENDOR 與 RENDERER 參數只回傳通用值,但 WEBGL_debug_renderer_info 擴充功能會暴露真實的硬體身份——例如 Google Inc. (NVIDIA) 以及 ANGLE (NVIDIA, NVIDIA GeForce RTX 3070 Direct3D11 vs_5_0 ps_5_0, D3D11) 這樣的字串。
這條字串往往會透露你的 GPU 型號、算繪後端(Direct3D、Metal、或經由 ANGLE 的 OpenGL),有時還包括驅動程式資訊。僅憑它就能把你縮小到一小撮使用者之中,因為精確的「GPU+後端」組合遠比人們想像的更稀有。
支援的擴充功能清單
WebGL 自帶一組核心特性,外加數十個可選擴充功能。getSupportedExtensions() 回傳的清單——以及它的排列順序——取決於顯示卡、驅動程式與瀏覽器版本。兩台顯示卡型號相同的裝置,若驅動程式或瀏覽器組建不同,這裡仍可能出現差異,從而再增加一層區分度。
數值參數與著色器精度
WebGL 暴露了一長串反映硬體能力的數值上限:MAX_TEXTURE_SIZE、MAX_VIEWPORT_DIMS、MAX_RENDERBUFFER_SIZE、鋸齒線寬與點尺寸範圍,以及頂點和片段著色器可用的最大 uniform 向量數。著色器精度——透過 getShaderPrecisionFormat() 查詢高/中/低精度的浮點與整數格式——進一步增加了細緻度,因為精度行為與晶片本身緊密相關。
以算繪為基礎的雜湊
最強大的技術與 Canvas 指紋如出一轍,只是改由 GPU 驅動。指令碼會算繪一個刻意設計得很「刁鑽」的場景——漸層、光照、透明度、曲面幾何——用 readPixels() 把像素讀回並做雜湊。不同 GPU 與驅動程式在浮點取整、反鋸齒與材質過濾上的差異,會產生一個在硬體家族之間各不相同、但對同一裝置保持穩定的雜湊。由於它捕捉的是行為而非僅僅是宣告值,要令人信服地偽造它要難得多。
程式碼層面的實際觀察
下面的程式碼片段蒐集了指紋指令碼會採集的核心 WebGL 訊號。你可以透過 BrowserInsight 的指紋偵測工具查看自己瀏覽器的等效即時結果。
function getWebGLFingerprint() {
const canvas = document.createElement('canvas');
const gl =
canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
if (!gl) return { supported: false };
// 1. 透過 debug 擴充功能讀取未遮罩的 GPU 廠商與算繪器
const debugInfo = gl.getExtension('WEBGL_debug_renderer_info');
const vendor = debugInfo
? gl.getParameter(debugInfo.UNMASKED_VENDOR_WEBGL)
: gl.getParameter(gl.VENDOR);
const renderer = debugInfo
? gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL)
: gl.getParameter(gl.RENDERER);
// 2. 數值能力上限
const params = {
maxTextureSize: gl.getParameter(gl.MAX_TEXTURE_SIZE),
maxViewportDims: gl.getParameter(gl.MAX_VIEWPORT_DIMS),
maxRenderbufferSize: gl.getParameter(gl.MAX_RENDERBUFFER_SIZE),
aliasedLineWidth: gl.getParameter(gl.ALIASED_LINE_WIDTH_RANGE),
};
// 3. 片段高精度浮點格式的著色器精度
const precision = gl.getShaderPrecisionFormat(
gl.FRAGMENT_SHADER,
gl.HIGH_FLOAT
);
// 4. 支援的擴充功能清單(存在與否、順序都有資訊量)
const extensions = gl.getSupportedExtensions();
return {
supported: true,
vendor,
renderer,
params,
precision: { rangeMin: precision.rangeMin, prec: precision.precision },
extensions,
};
}
以算繪為基礎的雜湊則更進一步:它編譯一個著色器,繪製一個帶光照的漸層圖形,呼叫 gl.readPixels() 把結果讀入一個型別化陣列,再把該陣列送入雜湊函式。得到的值對你的裝置保持恆定,卻在不同硬體之間各不相同。
WebGL 增加了多少資訊熵
資訊熵衡量一個訊號能把「你是誰」縮小到何種程度。WebGL 對追蹤者格外有價值,恰恰因為它攜帶的資訊熵很高且十分穩定:你的顯示卡不會在兩次頁面載入之間改變,大多數使用者也從不更新驅動程式。廠商/算繪器字串、擴充功能清單、數值上限與算繪雜湊之間存在部分相關——它們都源自同一塊硬體——但每一項都捕捉到了別項遺漏的細節。
實際上 WebGL 極少單獨使用。它會與 Canvas、音訊、字型、螢幕尺寸以及數十種其他屬性組合在一起。下表對比了主要的 WebGL 訊號類型,以及各自被偽造的難易程度。
| WebGL 訊號 | 暴露的內容 | 穩定性 | 偽造難度 |
|---|---|---|---|
| 廠商/算繪器字串 | GPU 型號+算繪後端 | 極高 | 易於覆寫,但會破壞一致性 |
| 支援的擴充功能清單 | 驅動程式+瀏覽器特性集 | 高 | 中等——清單須保持自洽 |
| 數值參數 | 硬體能力上限 | 極高 | 中等——各值相互關聯 |
| 著色器精度 | 浮點運算行為 | 高 | 難——與真實晶片繫結 |
| 算繪像素雜湊 | 真實的 GPU 算繪行為 | 高 | 極難——須偽造真實輸出 |
由於中介資料必須與算繪輸出彼此吻合,粗糙的偽造往往反而增加唯一性:一台回報 Intel 算繪器字串、卻產出 NVIDIA 風格像素的裝置,比一台老老實實如實上報的裝置更顯眼。
網站如何使用 WebGL 指紋
正當用途很常見。反詐騙與反機器人系統會把 WebGL 指紋作為眾多訊號之一,用來發現自動化流量、無頭瀏覽器,以及硬體突然變更的帳戶。分析與安全團隊用它來標記可疑工作階段。無頭與虛擬化環境常常暴露出標誌性的算繪器字串(例如 SwiftShader 或 llvmpipe 這類軟體點陣化器),這正是機器人偵測如此倚重 WebGL 的原因。
同樣的能力也被用於跨站廣告與追蹤,因為一個以硬體為基礎的穩定 ID 能在清除 Cookie 與無痕視窗中存活下來。正是這種雙重用途,使得無論你關注的是安全還是隱私,理解 WebGL 指紋都很重要。
防禦手段及其取捨
沒有完美的防禦——每種方案都會以犧牲功能、效能或「融入人群」的能力為代價。主要思路如下:
Tor 瀏覽器
Tor 瀏覽器走的是標準化路線:它出廠時設定統一,使所有使用者呈現相同的指紋,並在允許 WebGL 之前先彈出視窗詢問。目標不是隱藏你的顯示卡,而是讓每個使用者看起來都一模一樣,這是最強的隱私模型——代價是速度下降以及部分 3D 內容失效。
Brave 與 Farbling
Brave 會對可指紋化的輸出(包括 WebGL 讀回結果)加入微小、確定性、且「依工作階段+依站點」變化的隨機擾動(稱為「farbling」)。每個站點看到的值都略有不同,且雜訊會重新洗牌,因此難以建構穩定的跨站 ID,而大多數頁面仍能正常運作。
完全停用 WebGL
透過開關或 webgl.disabled 徹底關閉 WebGL,會完全移除這一採集面。它有效但很「粗暴」:WebGL 的缺席本身就有幾分不尋常,還會讓地圖、遊戲與視覺化工具失效。
數值偽造——以及它為何會適得其反
覆寫算繪器字串或注入雜訊的擴充功能可能有幫助,但確有風險。若偽造的中介資料與算繪像素或數值上限相互矛盾,成熟的偵測器會察覺到這種不一致,於是你反而變得更易辨識,而非更難。最安全的偽造應當一致、且為眾多使用者所共用;缺乏協同、各使用者自行其是的隨機化,常常事與願違。
務實的結論是:選擇一個被許多人共用的防禦方案(Tor 的統一性、Brave 的 farbling),而不是一套讓你變得獨一無二的客製化設定。想了解自己目前的處境,請執行 BrowserInsight 的指紋偵測工具,查看你的 WebGL 算繪器、擴充功能與雜湊。
WebGL 也並非 GPU 指紋採集的終點。更新的 WebGPU API 將適配器廠商、架構和裝置字串作為一等屬性直接揭露——無需任何偵錯擴充功能——構成了更豐富的採集面,而大多數隱私工具尚未涵蓋到它。
常見問題
網站能讀取我確切的顯示卡型號嗎?
在大多數瀏覽器中可以。WEBGL_debug_renderer_info 擴充功能會暴露一條未遮罩的算繪器字串,常常點出你的 GPU 型號與算繪後端。一些隱私瀏覽器會限制或隨機化它,但在預設的 Chrome 或 Edge 設定下,它無需任何授權彈窗即可被讀取。
隱私/無痕模式下 WebGL 指紋仍然有效嗎?
是的。無痕瀏覽會清除 Cookie 與歷史記錄,但不會改變你的硬體。WebGL 訊號——廠商、算繪器、擴充功能、數值上限與算繪雜湊——在一般視窗與無痕視窗中保持一致,因此能在兩者之間重新辨識你。
停用 WebGL 足以阻止指紋追蹤嗎?
它移除了 WebGL 這一採集面,但並未消除整體的指紋追蹤。Canvas、音訊、字型、螢幕等其他訊號依舊適用,而 WebGL 的顯眼缺席本身也可能成為一種區分特徵。停用它是一層防護,而非完整方案。
WebGL 指紋與 Canvas 指紋有何不同?
Canvas 指紋探測的是二維算繪路徑,而 WebGL 探測的是由 GPU 驅動的三維路徑,並額外暴露顯式的硬體中介資料(廠商、算繪器、能力上限)。兩者相關但不同,這正是追蹤者會同時採集二者以提高信賴度的原因。


