FingerprintJS 是開源函式庫,跟付費版 Fingerprint 產品不同;本文說明它蒐集哪些訊號、準確度如何,以及與 CreepJS 的差異。
搜尋「fingerprintjs」,結果常把兩個不同的東西混在一起。一個是開源 JavaScript 函式庫,任何網頁都能免費引入:它完全在訪客的瀏覽器裡執行,回傳一個 visitorId 字串。另一個是 Fingerprint,同一家公司販售的付費商業識別服務,多了伺服器端處理,宣稱的準確度也高得多。兩者名稱相同、同屬一個 GitHub 組織,做法也大致相同——把大量瀏覽器訊號合成一個識別碼——除此之外沒有太多共通點。本文談的是前者:這支開源函式庫實際讀取哪些訊號、如何把它們變成 visitorId、實際準確度如何,以及它跟本站介紹過的其他指紋測試工具相比處在什麼位置。
核心要點
- 免費、採用 MIT 授權的 FingerprintJS 函式庫,跟付費產品 Fingerprint 出自同一家公司,但不是同一個東西。函式庫完全在用戶端執行,它自己的 README 也寫明,準確度比商業版「低得多」。
- 這支函式庫讀取約 40 項瀏覽器訊號——canvas 繪圖、已安裝字型、音訊處理、WebGL 渲染器資訊、螢幕與硬體屬性、時區與語言、顯示偏好等——再雜湊成一個
visitorId。 visitorId回答的是「這是不是上次那個瀏覽器?」,屬於穩定性的問題;CreepJS 問的是「這個瀏覽器有沒有謊報自己?」,Cover Your Tracks 問的是「這個組合有多罕見?」,三者並不相同。- 由於不依賴 cookie 或本機儲存空間,這種指紋在無痕模式下、清除瀏覽資料之後仍然不變;但底層訊號一旦改變——例如瀏覽器或顯示卡驅動程式更新,或是瀏覽器刻意隨機化指紋特徵——它也會跟著變。
- README 沒有提供開源函式庫的準確度百分比,本文也不提供。看到有人替它引用具體數字時,請持保留態度。
同名的兩個「FingerprintJS」
這種混淆源自專案本身的歷史。FingerprintJS Inc. 一開始做的就是這支開源函式庫,後來以同一個構想推出商業產品,如今公司以 Fingerprint 為名營運。開源函式庫仍持續維護,npm install @fingerprintjs/fingerprintjs 裝到的就是它——但公司大部分的行銷內容,以及許多第三方談論「FingerprintJS」的文章,描述的其實是付費產品才有、免費函式庫並不具備的能力。
評估兩者時,真正重要的差異有三點:
- 執行位置。 開源函式庫在訪客瀏覽器內完成所有運算,把
visitorId交給網頁。商業產品還會在廠商的伺服器上處理每一次請求,能用到網頁腳本自己拿不到的訊號(例如連線的 IP 位址),並跟過去的造訪紀錄比對。 - 費用。 函式庫以 MIT 授權免費提供;商業產品是按用量計費的付費 API。
- 各自的說法。 README 明白寫著:因為指紋是在瀏覽器內產生的,函式庫的準確度比商業版低得多。廠商之所以替付費產品宣傳高得多的準確度,靠的正是那層伺服器端處理。
如果你搜尋「fingerprintjs」是想找一個能自架的免費函式庫,開源專案就是它。如果你是在替企業評估防詐騙或反機器人方案,你真正在看的是商業產品——兩者不該被當成「同一個工具換了品牌」來比較。
開源函式庫實際讀取了什麼
撇開品牌不談,這支函式庫用的技術跟本站其他文章介紹過的屬於同一類:一組固定的用戶端訊號,蒐集後雜湊成單一數值。它的原始碼把每項訊號定義為一個「熵來源」(entropy source),目前版本約有 40 個。依類型整理如下:
- Canvas 繪圖。 也就是Canvas 指紋檢測:網站如何識別你的裝置介紹的隱藏繪圖技術:同樣的文字與圖形,會因 GPU、驅動程式與字型渲染不同而出現細微的像素差異,不需要 cookie 就能得到穩定的雜湊值。
- WebGL。 基本的 WebGL 參數,例如回報的廠商(vendor)與渲染器(renderer)字串,以及支援的 WebGL 擴充功能清單。
- 音訊。 透過 Web Audio API 處理一小段訊號(機制見音訊指紋:AudioContext 如何識別你的裝置),同時讀取音訊堆疊回報的基礎延遲。差異來自音訊實作與硬體,而不是使用者能調整的任何設定。
- 字型。 安裝了哪些字型,以及預設字型家族實際的渲染結果,兩者都會隨作業系統、語言套件與已安裝軟體而不同。
- 螢幕與硬體。 螢幕解析度與色彩深度、作業系統在可用螢幕區域周圍占用的空間(例如工作列或 Dock)、CPU 核心數(
hardwareConcurrency)、裝置記憶體的概略值,以及是否支援觸控。 - 地區設定。 時區、偏好語言,以及日期時間格式所採用的地區設定。
- 平台與瀏覽器。 回報的平台與 CPU 架構、瀏覽器廠商、已安裝的外掛程式、是否啟用內建 PDF 檢視器,以及 Apple Pay 是否可用等少數引擎特有的檢查。
- 偏好與環境。 色域、強制色彩或反轉色彩、對比與減少動態效果偏好、HDR 支援等 CSS 媒體特性;cookie 與各種儲存 API 是否可用;似乎啟用了哪些內容封鎖工具;以及
Math函式在浮點運算上的細微差異。
這些訊號沒有一項是 FingerprintJS 獨有的——瀏覽器指紋技術完全指南:如何保護你的數位隱私以更概括的角度介紹過這些底層技術。這支函式庫的價值在於封裝:一支持續維護的腳本,把整組訊號蒐集齊全並轉成一個字串,網站就不必自己撰寫蒐集邏輯。
從訊號到 visitorId
呼叫函式庫的 get() 方法會回傳四樣東西:visitorId;代表函式庫對這個識別碼有多少把握的 confidence(信賴度)分數;蒐集到的原始 components;以及指紋演算法的 version。visitorId 本身是把所有訊號序列化成一個字串後,再以 128 位元雜湊(函式庫中的 x64hash128 函式,MurmurHash3 的一種變體)算出的結果。只要任何一項訊號改變,雜湊值就會完全不同——不存在「差不多一樣」的 visitorId。
老實說,它到底有多準
README 裡有兩個說法值得分開看。第一,指紋不依賴 cookie 或本機儲存空間,所以「在無痕/私密模式下,甚至清除瀏覽器資料之後,仍然保持不變」。這正是網站採用指紋識別的根本原因:清掉 cookie 也重設不了它。
第二,README 表示,由於 FingerprintJS 是在瀏覽器內產生指紋,準確度比商業版低得多。它沒有公布具體百分比,本文也不會提供。
為什麼會比較低?從 visitorId 的產生方式可以直接推出兩個結構性原因——以下是我們的分析,並非該專案的說法:
- 飄移。 雜湊涵蓋所有訊號,任何一項改變都會產生新的
visitorId。瀏覽器更新可能改變 canvas 上的文字渲染;顯示卡驅動程式更新可能改變 canvas 輸出或 WebGL 渲染器字串;新安裝一套字型會改變字型清單;具備反指紋保護、會刻意在 canvas 或音訊輸出中加入雜訊的瀏覽器,在不同工作階段或不同網站之間可能回傳不同的值。訊號改變了的回訪者,看起來就像全新的訪客。 - 碰撞。 反過來的問題:型號、作業系統版本與瀏覽器版本都相同的裝置——例如一批設定完全一致的公司筆電,或兩支執行同一 iOS 版本的同型號 iPhone——可能暴露幾乎相同的訊號,算出同一個
visitorId,讓不同的人看起來像同一位訪客。
純瀏覽器腳本無法自行修正這兩類錯誤。伺服器端系統則能參考更多證據,例如造訪來自哪個網路、過去的造訪紀錄——這正是商業產品要補上的缺口。
FingerprintJS 在各家測試工具中的定位
FingerprintJS 的 visitorId 只回答一個特定問題:這是不是之前來過的那個瀏覽器?這是穩定性的問題。值得說清楚它跟本站介紹過的其他工具有何不同,因為同一個瀏覽器換一個問題來問,就可能得到三種聽起來截然不同的結論:
- CreepJS 問的是「這個瀏覽器有沒有誠實描述自己?」——一種一致性檢查,交叉比對可信與不可信的訊號來源,找出內部矛盾。以 CreepJS 的標準看來毫無破綻的瀏覽器,仍然可能產生一個高度穩定、極易被追蹤的
visitorId。 - Cover Your Tracks 問的是「這組訊號組合有多罕見?」——用資訊理論回答的唯一性問題,跟訊號是否一致、在不同工作階段之間是否穩定都無關。
- FingerprintJS 兩個都不問。它問的是:同一組訊號用同樣方式雜湊,能不能再次得到同一個識別碼——這是可重現性的問題,既說明不了這個組合有多常見,也判斷不了哪項訊號是否被動過手腳。
指紋測試工具為何對你眾說紛紜整理過這個模式:唯一性、一致性與身分穩定性是三種不同的量測,卻常被籠統地叫做「分數」或「ID」;為其中一種打造的工具,本來就沒打算回答另外兩種。如果你拿 visitorId 這類結果去對照 CreepJS 的信任分數或 Cover Your Tracks 的匿名度數字,發現兜不起來,這很正常——它們回答的根本不是同一個問題。BrowserLeaks 詳解:每項測試到底檢測什麼洩露則補上這類工具的第四種形態:把每個檢測面分開回報、完全不合併成單一數字的測試套件。
檢查你自己的訊號
BrowserInsight 的指紋檢測呈現了這支函式庫讀取的許多同類訊號——canvas、WebGL、音訊、字型、螢幕與 navigator 屬性——逐項列出,並搭配一致性檢查,在訊號互相矛盾時提出標示。它不會再算出一個跟它較勁的 visitorId,而是把指紋函式庫會拿去雜湊的原始訊號攤在你眼前,讓你看清是哪幾項讓你的瀏覽器顯得與眾不同。想親眼看到飄移:先執行一次檢測,接著更新瀏覽器,或開啟瀏覽器內建的防指紋功能(如果有的話),再執行一次——有變動的 canvas、WebGL 或字型數值,正是會讓 FingerprintJS 產生新 visitorId 的那類變化。
常見問題
開源版 FingerprintJS 函式庫,跟 Fingerprint 產品是同一個東西嗎?
不是。兩者出自同一家公司,也都採用雜湊式做法,但開源函式庫完全在用戶端執行,它的 README 也寫明準確度比商業版低得多;付費的 Fingerprint 產品則多了免費函式庫沒有的伺服器端處理。
開源函式庫可以用在商業網站上嗎?
這支函式庫以 MIT 授權發布,這種授權允許商業使用。確切條款請以儲存庫中的授權檔案為準。
FingerprintJS 會蒐集或儲存關於我的資料嗎?
開源函式庫本身只是一支在你瀏覽器裡執行、回傳 visitorId 的腳本;這個識別碼之後會不會被儲存、存在哪裡,完全取決於部署它的網站,而不是函式庫本身。請查看特定網站的隱私權政策,不要自行假設指紋腳本的輸出會怎麼被處理。
為什麼我的 visitorId 每次造訪都不一樣?
因為它是函式庫讀取的所有訊號的雜湊值,任何一項改變都會得到不同的 ID。常見原因包括瀏覽器更新、顯示卡驅動程式更新、新安裝的字型,以及會隨機化 canvas 或音訊輸出的反指紋功能。相反地,開啟無痕視窗或清除 cookie 照理不會改變它——README 說這兩種情況下指紋都保持不變。
FingerprintJS 比 CreepJS 或 Cover Your Tracks 更準嗎?
這個比較本身不太成立,因為這三個工具衡量的不是同一件事。FingerprintJS 問同一位訪客能不能兩次產生同一個識別碼;CreepJS 問瀏覽器的訊號內部是否一致;Cover Your Tracks 問這個組合有多罕見。「更準」只有在兩個工具想回答同一個問題時才有意義。


