你從原生 HTTP 換到了真正的瀏覽器。TLS 指紋:貨真價實的 Chrome。IP:住宅。而站台還是知道。在 2026 年,無頭瀏覽器偵測早已遠遠超越 navigator.webdriver — 當前這一代檢查偵測的是自動化協定本身,而大多數「stealth」外掛在修補昨天的訊號的同時,卻大聲地展現著今天的訊號。
本文會盤點站台現在實際上會檢查什麼、大致依它們檢查的順序,以及在每一層真正有幫助的是什麼。它與 JA3/JA4 TLS 指紋(網路層)和 IP 信譽與 ASN(位址層)一起構成這個偵測三部曲 — 而這一篇是瀏覽器層。
navigator.webdriver — 規範要求在自動化下為 true。Playwright/Puppeteer 的 stealth 設定會把它藏起來;Chrome 的 --disable-blink-features=AutomationControlled 原生就能處理。站台仍會檢查它,因為這免費又能抓到天真的機器人。HeadlessChrome/。用新的無頭模式(headless=new)即可修正,它會使用真正的 Chrome 二進位檔路徑。navigator.plugins 為零、沒有 chrome.runtime、outerWidth 為 0×0。舊的無頭模式這些全都過不了;新的無頭模式大多能通過。如果一個目標只檢查第 1 層,搭配 headless=new 的現代 Playwright 就能直接走過去。認真的目標多年前就往前走了。
Playwright 與 Puppeteer 透過 Chrome DevTools Protocol 來驅動 Chrome,而 CDP 會留下頁面 JavaScript 可觀察到的執行期副作用:
// The classic CDP leak: serialization callbacks
const err = new Error();
Object.defineProperty(err, "stack", {
get() {
// This getter fires DURING console serialization -
// which only happens when DevTools/CDP is attached
window.__cdp_detected = true;
},
});
console.debug(err);
這類變體 — console 序列化期間的 getter 副作用、Runtime.evaluate 的時序異常、被修補過的原生函式上 toString() 的行為 — 存在於每一套商用反機器人套件裡。關鍵在於:這偵測的是協定,而不是無頭模式。一個有頭、打過 stealth 修補、看起來完美像人的 Chrome,只要是透過 CDP 驅動的,照樣會失敗。
有幫助的是:
除了痕跡之外,現代系統還會檢查你的瀏覽器故事內部是否一致:
| 檢查項 | 機器人的破綻 |
|---|---|
| Canvas / WebGL 渲染雜湊 | SwiftShader/llvmpipe 軟體渲染 = 伺服器 GPU;或一個被一萬個「不同使用者」共用的雜湊 |
| 字型與編解碼器 | Windows User-Agent 下卻是 Linux 伺服器的字型集合 |
| 時區 × 語系 × IP 地理位置 | Intl 說 UTC,IP 說德州,Accept-Language 說 de-DE |
| 螢幕度量 | 1920×1080 卻沒有工作列、devicePixelRatio 剛好是 1、視窗從未被調整大小 |
| 硬體並行數/記憶體 | 對一個自稱是手機的頁面回報 96 核心 |
| 行為微訊號 | 滑鼠沒有熵值、瞬間填完表單、以固定的 100px 步幅捲動 |
這就是 DIY stealth 的死亡之地:你套用的每個修補都必須與其他每個訊號一致。一個在 Linux 容器上偽造的 Windows UA,會同時和字型、GPU 字串與 TCP 指紋互相矛盾。一致性勝過完美 — 一個誠實的有頭 Linux Chrome,得分會比一個拙劣偽造的「Windows」更好。
如果位址層已經燒掉了,這一切都不重要:一個在資料中心 ASN 上完美無瑕的瀏覽器,仍然是「一個在資料中心裡完美無瑕的瀏覽器」— 而且無頭偵測的門檻是會隨 IP 信譽調整的。同一個瀏覽器從一個被標記的 IP 出去會收到更多 JavaScript 挑戰。住宅出口實際上降低了瀏覽器層需要存活下來的審查強度:
browser = p.chromium.launch(
headless=False, # headed survives more checks
args=["--disable-blink-features=AutomationControlled"],
proxy={
"server": "us.jibaoproxy.com:913",
"username": "USERNAME", "password": "PASSWORD",
},
)
toString() 本身就是一個訊號。少而一致的修補才會贏。新用戶註冊即送 500M免費流量,首次儲值另有贈金。優惠限時供應。