你买了干净的住宅 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 照被标记。
修之前先测。从你的抓取器发一个请求到极豹免费的 JA3/JA4 指纹检测工具,和真实 Chrome 的结果对比。如果 JA3 哈希不同,目标就能把你和真人区分开 —— Cloudflare 也一样。
requests 和 httpx 把 TLS 交给系统的 OpenSSL。你可以怎么改 header、怎么换 User-Agent 都行,但底下的握手还是 OpenSSL 的,不是 Chrome 的。“我抄了浏览器的 header 还是被封”最常见的原因,就是只改了 header、没改握手。你需要一个能模仿浏览器真实 TLS 栈的客户端。
curl_cffi 绑定 curl-impersonate(一个复现真实浏览器 TLS 和 HTTP/2 指纹的 curl 构建)。一个参数,你的握手就像 Chrome:
# pip install curl_cffi
from curl_cffi import requests
# 伪装真实 Chrome 的 TLS + HTTP/2 指纹
r = requests.get(
"https://tls.browserleaks.com/json",
impersonate="chrome131",
)
print(r.json()["ja3_hash"]) # 现在匹配真实 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 挂代理 + stealth。权衡是成本和速度:curl_cffi 这类 HTTP 客户端每请求便宜得多,所以能用就用它,只把最难的目标留给完整浏览器。
curl_cffi(impersonate=)或 tls-client —— 光改 header 不够。TLS 指纹是大多数“IP 干净却仍被封”故事里缺的那一层。修好握手、保留住宅 IP,成功率就上来了。对最难的 WAF,读完整的 2026 Cloudflare 绕过配方。
新用户注册即送5U,首次充值额外加赠,活动期间限时开放。