你買了乾淨的住宅 IP,輪換得完美無缺,第一個請求卻還是吃到 403。問題不在 IP — 出賣你的是你的 TLS 交握。TLS 指紋辨識讓伺服器在讀取你 HTTP 請求的任何一個位元組之前,就能識別出用戶端函式庫。本文解釋 JA3/JA4,說明為何 Python 的 requests 輕易就被偵測出來,並提供以 curl_cffi 與 tls-client 模擬真實瀏覽器的可用程式碼。
任何用戶端開啟 HTTPS 連線時,都會送出一個 ClientHello,宣告它的 TLS 版本、加密套件、擴充功能、橢圓曲線,以及這些項目的排列順序。那個排序對建立它的函式庫來說相當獨特。把它雜湊起來,你就得到一個 JA3 指紋(或更新、更穩健的 JA4)。
Chrome 產生一種指紋。Firefox 產生另一種。Python 的 requests(建立在 urllib3 與 OpenSSL 之上)產生的指紋大喊著「自動化」— 而且在數百萬個機器人之間完全一模一樣。反機器人系統會保留這些指紋的封鎖清單。無論你的 IP 多麼住宅級,一個已知的機器人 JA3 都會被標記。
修正任何東西之前,先量測它。從你的爬蟲送一個請求到 JIBAO 免費的 JA3/JA4 指紋檢測工具,並與真實 Chrome 顯示的結果比較。如果 JA3 雜湊不同,目標站台就能把你和真人區分開來 — Cloudflare 也一樣。
requests 與 httpx 把 TLS 交給系統的 OpenSSL。你可以整天更改標頭甚至 User-Agent,但底下的交握仍然是 OpenSSL 的,不是 Chrome 的。只偽造標頭而不偽造交握,正是「我複製了瀏覽器的標頭,它還是封鎖我」最常見的原因。你需要一個會模仿瀏覽器實際 TLS 堆疊的用戶端。
curl_cffi 綁定到 curl-impersonate,那是一個能重現真實瀏覽器 TLS 與 HTTP/2 指紋的 curl 編譯版本。一個參數,你的交握就看起來像 Chrome:
# pip install curl_cffi
from curl_cffi import requests
# impersonate a real Chrome TLS + HTTP/2 fingerprint
r = requests.get(
"https://tls.browserleaks.com/json",
impersonate="chrome131",
)
print(r.json()["ja3_hash"]) # now matches real Chrome
它的 API 與 requests 一致,所以遷移現有的爬蟲大多只是改一行 import。支援的目標包含近期的 Chrome、Edge、Safari 與 Firefox 編譯版本 — 挑一個並持續更新,因為瀏覽器更新時指紋會輪替。
指紋比對與 IP 輪換是互補的,不是二選一。兩者都用:一個瀏覽器等級的交握,透過一個乾淨的住宅 IP,才是真正能通過的組合:
from curl_cffi import requests
PROXY = "socks5h://USERNAME:[email protected]:10001"
r = requests.get(
"https://example.com/protected",
impersonate="chrome131",
proxies={"http": PROXY, "https": PROXY},
timeout=30,
)
print(r.status_code)
tls-client(一個包裝 Go uTLS 實作的 Python 封裝)是另一個紮實的選擇,附帶大量具名設定檔的函式庫:
# pip install tls-client
import tls_client
session = tls_client.Session(
client_identifier="chrome_120",
random_tls_extension_order=True,
)
session.proxies = {
"http": "socks5h://USERNAME:[email protected]:10001",
"https": "socks5h://USERNAME:[email protected]:10001",
}
r = session.get("https://example.com/protected")
print(r.status_code)
random_tls_extension_order=True 會打亂擴充功能的順序,以避免產生靜態、可重複利用的指紋 — 對那些長期追蹤 JA3 完全比對的系統很有幫助。
有些目標會檢查 JavaScript 執行訊號(canvas、WebGL、事件時序),那是任何 HTTP 用戶端都無法重現的。在那種情況下,改用驅動真實瀏覽器的方式 — 參見 搭配 Playwright 與 Puppeteer 使用代理並加上隱身。代價是成本與速度:像 curl_cffi 這類 HTTP 用戶端每個請求便宜得多,所以在它們夠用的地方就用它們,把完整瀏覽器留給最難的目標。
curl_cffi(impersonate=)或 tls-client — 光靠標頭是不夠的。在多數「IP 乾淨卻仍被封鎖」的故事裡,TLS 指紋辨識是缺漏的那一層。修正交握、保留住宅 IP,成功率就會躍升。要對付最難纏的 WAF 並掌握完整堆疊,請閱讀 2026 Cloudflare 繞過配方。
新用戶註冊即送 500M免費流量,首次儲值另有贈金。優惠限時供應。