了解 User-Agent Client Hints(UA-CH)的運作原理:低熵與高熵層級、Accept-CH 協商機制,以及對瀏覽器指紋識別的影響。
User-Agent 字串自 1990 年代初便是 Web 的一部分——這個單一請求標頭會一次性宣告你的瀏覽器、版本、引擎、作業系統與裝置類型。幾十年來,它愈發臃腫:承載著「Mozilla/5.0」這類早已作古的歷史遺留令牌,以及足以充當被動指紋訊號的大量平台細節。User-Agent Client Hints(UA-CH)是 Chromium 的結構化替代方案。它不再預先廣播所有資訊,而採用雙層揭露模型:每次請求預設發送一小組低熵提示,而更豐富的高熵層級只在伺服器明確要求時才釋放。
核心要點
- Chromium 瀏覽器預設在每個 HTTPS 請求中發送三項低熵提示(品牌列表、行動裝置旗標、平台名稱)——無需伺服器主動申請。
- 架構資訊、完整版本號、作業系統版本、裝置型號等高熵細節,需要伺服器先發送
Accept-CH回應標頭才會提供。 - JavaScript 對應介面為
navigator.userAgentData——這是 Chromium 專屬 API,Firefox 與 Safari 回傳undefined。 - Chromium 正在逐步將舊版
User-Agent字串凍結為低細節存根,同時將 UA-CH 擴展為主要的身分標識通道。 - 對於指紋識別與偽裝偵測而言,
navigator.userAgentData的存在本身就能可靠地識別 Chromium——而授權後的高熵值所揭露的瀏覽器身分細節,比舊版 UA 字串更為具體。
為何舊版 User-Agent 需要被取代
最初的 UA 字串是為瀏覽器嗅探而設計的——伺服器讀取它,判斷使用的是哪種渲染引擎,然後發送相應內容。它從未以隱私為出發點。典型的 Chromium UA 字串如下:
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36
這個單一標頭會被動洩露作業系統名稱與版本、CPU 架構、平台類型、瀏覽器品牌以及粗略的版本號——在每次請求中,不需要任何伺服器主動詢問。它還成了相容性陷阱:網站開始根據特定子字串做分支處理,導致瀏覽器無法修改格式,否則就會破壞這些網站的適配邏輯。這既是維護問題,也是隱私問題。UA-CH 兩者兼顧:它將舊版字串凍結為存根,同時提供清晰的版本化 API,讓伺服器只申請它真正需要的內容。
兩個層級:低熵與高熵提示
UA-CH 模型根據資訊對縮小使用者身分範圍的程度,將瀏覽器資訊分為兩個層級。
低熵提示(預設發送)
Chromium 在每個跨來源 HTTPS 請求中附加三個 Sec-CH-UA-* 請求標頭,無需伺服器提示:
| 標頭 | 範例值 | 揭露內容 |
|---|---|---|
Sec-CH-UA | "Chromium";v="124", "Google Chrome";v="124", "Not-A.Brand";v="99" | 瀏覽器品牌列表及主版本號 |
Sec-CH-UA-Mobile | ?0 | 是否為行動裝置(?1)或非行動裝置(?0) |
Sec-CH-UA-Platform | "Windows" | 僅作業系統的高層次名稱 |
這些屬於低熵資訊,因為大量使用者共享相同的值:知道某人用的是 Windows 版 Chrome 124,可以對應數百萬名使用者,而不是寥寥幾人。
高熵提示(需要 Accept-CH)
解析度更高的細節——那些可能精確定位特定裝置版本的資訊——預設關閉,伺服器必須明確申請:
| 標頭 | 範例值 | 揭露內容 |
|---|---|---|
Sec-CH-UA-Arch | "x86" | CPU 架構 |
Sec-CH-UA-Bitness | "64" | 32 位元或 64 位元平台 |
Sec-CH-UA-Full-Version-List | "Google Chrome";v="124.0.6367.60" | 每個品牌的完整版本字串 |
Sec-CH-UA-Model | "Pixel 7" | 裝置型號(主要對行動端有意義) |
Sec-CH-UA-Platform-Version | "10.0.0" | 作業系統版本 |
Accept-CH 協商機制
申請高熵提示的協定流程很直接。首次訪問時,伺服器回傳一個 Accept-CH 回應標頭,列出所需的提示名稱:
HTTP/1.1 200 OK
Accept-CH: Sec-CH-UA-Full-Version-List, Sec-CH-UA-Arch, Sec-CH-UA-Platform-Version
在後續請求(以及頁面重新整理)中,瀏覽器會包含這些提示:
GET /page HTTP/1.1
Sec-CH-UA: "Chromium";v="124", "Google Chrome";v="124", "Not-A.Brand";v="99"
Sec-CH-UA-Mobile: ?0
Sec-CH-UA-Platform: "Windows"
Sec-CH-UA-Full-Version-List: "Chromium";v="124.0.6367.60", "Google Chrome";v="124.0.6367.60", "Not-A.Brand";v="99.0.0.0"
Sec-CH-UA-Arch: "x86"
Sec-CH-UA-Platform-Version: "10.0.0"
首次頁面載入刻意保持資訊稀疏:如果沒有事先的明確申請,伺服器僅能看到三項低熵預設值。
JavaScript API:navigator.userAgentData
相同的資料也可透過 navigator.userAgentData 在用戶端取得。該 API 僅存在於 Chromium 中——Firefox 與 Safari 回傳 undefined——因此它的存在本身就是一個可靠的引擎識別訊號。
低熵資料是同步的:
const uaData = navigator.userAgentData;
console.log(uaData.brands); // [{brand: "Chromium", version: "124"}, ...]
console.log(uaData.mobile); // false
console.log(uaData.platform); // "Windows"
高熵資料是非同步的,需要顯式請求——與 HTTP Accept-CH 模型相對應:
navigator.userAgentData
.getHighEntropyValues(["architecture", "platformVersion", "fullVersionList"])
.then(ua => {
console.log(ua.architecture); // "x86"
console.log(ua.platformVersion); // "10.0.0"
console.log(ua.fullVersionList); // [{brand: "Google Chrome", version: "124.0.6367.60"}, ...]
});
呼叫 getHighEntropyValues() 不會觸發使用者可見的權限提示。它為網站提供了一種可追溯的顯式機制來取得詳細的身分資訊,而非靜默讀取廣播字串。跨來源 iframe 可透過 Permissions-Policy 被阻止取得高熵提示。
UA-CH 與舊版 User-Agent 的比較
| 屬性 | 舊版 User-Agent | User-Agent Client Hints |
|---|---|---|
| 瀏覽器支援 | 所有瀏覽器 | 僅 Chromium |
| 揭露模型 | 所有內容被動廣播 | 低熵預設 + 高熵按需申請 |
| 格式 | 無結構自由文字字串 | 結構化鍵值對 |
| 可偽造性 | 輕而易舉(修改一個字串) | 逐欄位偽造,難以保持一致 |
| 隱私設計意圖 | 無(歷史遺留) | 內建漸進式揭露設計 |
| 發展趨勢 | 逐步凍結為存根 | 持續擴展;Chromium 主要身分通道 |
Chromium 一直在逐步減少舊版 UA 字串中的資訊量。自 Chrome 101 起,次要作業系統版本已凍結為 0.0.0,UA 字串中的瀏覽器次要版本也經過了簡化。發展方向是讓其變成一個僅傳達「這是 Chromium 瀏覽器」含義的存根——所有具體資訊都遷移到 UA-CH。
指紋識別影響
UA-CH 從兩個方向改變了指紋識別格局。
navigator.userAgentData 的存在是可靠的引擎偵測器。 Firefox 與 Safari 不暴露此 API。透過檢查 navigator.userAgentData !== undefined,頁面可以立即識別 Chromium——比解析可隨意偽造的 UA 字串更為可靠。如果偽裝的 UA 聲稱是 Firefox,但 navigator.userAgentData 卻存在並回報 Chromium 品牌,這一矛盾立刻顯而易見。這是偵測 user-agent 偽裝中的核心技術手段之一。
高熵提示可能比舊版 UA 字串更具體。 已凍結的舊版 UA 不再暴露完整的次要瀏覽器版本;Sec-CH-UA-Full-Version-List 則會暴露。結合 Sec-CH-UA-Arch 與 Sec-CH-UA-Platform-Version,請求完整集合的伺服器所獲得的平台指紋,比被動廣播時代更為豐富——但這需要瀏覽器的配合,且僅對明確申請的伺服器有效。
凍結 UA 字串並不等於改善隱私。 減少 UA 字串只是移除了一個被動訊號,對構成瀏覽器指紋的其他眾多訊號毫無影響:canvas 渲染輸出、WebGL 渲染器字串、螢幕參數、音訊處理、已安裝字型。UA-CH 改善的是伺服器端的資訊治理,並未縮小整體指紋暴露面。
UA-CH 由伺服器控制,而非使用者控制。 目前沒有瀏覽器 UI 允許使用者拒絕第一方 JavaScript 發起的特定 getHighEntropyValues() 呼叫。Brave 的指紋隨機化模式確實會覆寫 UA-CH 值,其他基於 Chromium 的瀏覽器則沒有此功能。需要限制資訊揭露的使用者,只能依賴瀏覽器的反指紋模式。
自行測試
開啟瀏覽器開發人員工具的主控台,執行 navigator.userAgentData 查看低熵值,然後執行:
navigator.userAgentData?.getHighEntropyValues(
["architecture", "model", "platformVersion", "fullVersionList"]
)
在 Firefox 或 Safari 中,該 API 回傳 undefined;在 Chromium 中,它會解析出你的實際平台詳情。BrowserInsight 的指紋檢測工具會連同其餘指紋訊號一並展示你的完整 UA-CH 資料,讓你看清所有身分訊號是如何組合在一起的。
常見問題
UA-CH 會完全取代 User-Agent 字串嗎?
暫時不會,對非 Chromium 瀏覽器也不會。Firefox 與 Safari 仍只發送傳統的 User-Agent 標頭。對於 Chromium,UA-CH 是首選通道,舊版 UA 正在凍結中,但兩者在目前版本中共存。需要廣泛相容性的網站仍會將 User-Agent 作為備用方案讀取。
我能偽造 UA-CH 的值嗎?
無法透過一般瀏覽器設定實現。Chrome 的開發人員工具裝置模擬會覆寫 UA 字串,但不會覆寫 navigator.userAgentData,這也是裝置模擬容易被偵測到的原因。Brave 的指紋隨機化模式確實提供 UA-CH 偽造功能,但在 HTTP 標頭和 JavaScript API 兩端保持一致,需要瀏覽器層面的協調修補。
UA-CH 能在 HTTP 下運作嗎?
不能。Accept-CH 協商和 Sec-CH-UA-* 標頭僅適用於 HTTPS(以及 localhost),普通 HTTP 連線不會發送 UA-CH 標頭。
Firefox 支援 UA-CH 嗎?
Firefox 不實作 UA-CH。Mozilla 團隊曾表達顧慮,認為當高熵值被常規請求時,該 API 可能讓指紋識別變得更容易。Firefox 繼續使用舊版 User-Agent 標頭。
結論
User-Agent Client Hints 代表了一次深思熟慮的架構轉變:從一個無論是否有人詢問都會洩露平台細節的單一被動廣播,轉向一個低熵事實預設發送、高熵細節需要申請才釋放的分層系統。對於開發者而言,結構化 API 比自由文字 UA 字串更易於解析和版本管理。對於指紋識別和偵測工作而言,它引入了一個明確的 Chromium 與非 Chromium 區分訊號,同時為有需要的伺服器提供了更豐富的顯式身分標識通道。凍結舊版 UA 字串減少了一個被動向量;取而代之的,是瀏覽器與伺服器之間的主動協商。
延伸閱讀:


