curl_cffi 为什么是当前的最优解
Python 爬虫的 TLS 指纹伪装方案演进:requests(无伪装)→ pyhttpx/tls-client(半吊子)→ curl_cffi(完整方案)。curl_cffi 胜出的原因:
- 基于 curl-impersonate,TLS 指纹逐字节级复刻(不只是 JA3,整个 ClientHello 的字节序都对)
- HTTP/2 指纹同步模拟(SETTINGS 帧、优先级、窗口更新全对齐浏览器)
- API 兼容 requests,迁移成本几乎为零
pip install curl_cffi基础用法:和 requests 几乎一样
from curl_cffi import requests
# 最简:指定模拟的浏览器
resp = requests.get('https://target.com', impersonate='chrome120')
# session 复用(cookie 自动管理)
session = requests.Session(impersonate='chrome120')
session.get('https://target.com/') # 拿 cookie
resp = session.post('https://target.com/api', json={...})
# 代理
resp = requests.get(url, impersonate='chrome120',
proxies={'http': 'http://127.0.0.1:7890',
'https': 'http://127.0.0.1:7890'})指纹版本的选择策略
# 查看当前版本支持的所有指纹
from curl_cffi import requests
# 文档或源码里的 BrowserType 列表:
# chrome99/100/101/104/107/110/116/119/120/123/124...
# safari15_3/15_5/17_0/17_2_ios...
# edge99/101...选择原则:
- 和 ua 严格匹配:ua 写 Chrome 120,impersonate 就 chrome120
- 别用太旧的版本:风控会统计"真实用户群体的版本分布",Chrome 99 在 2026 年的真实占比接近 0,用老指纹反而扎眼
- 移动端场景用 safari_ios 指纹:模拟手机流量时选
safari17_2_ios这类,配移动端 ua
精髓一:指纹验证与对拍
怎么确认伪装生效了?对拍:
# 你的脚本
r1 = requests.get('https://tls.peet.ws/api/all', impersonate='chrome120').json()
print(r1['tls']['ja3'], r1['http2']['akamai_fingerprint'])
# 真实 Chrome 访问同一地址(Console 里 fetch 或抓包)
# 对比 ja3 和 akamai_fingerprint 两个字段,一致 = 伪装成功tls.peet.ws 返回完整的 TLS/H2 指纹信息,是指纹伪装的标定工具。
精髓二:和浏览器自动化的分工
curl_cffi 不是万能的,认清边界:
| 场景 | 方案 |
|---|---|
| 接口有签名但无 JS 挑战 | curl_cffi + 签名算法 |
| Cloudflare 基础防护(只查指纹) | curl_cffi 直接过 |
| Cloudflare 5 秒盾/Turnstile | 浏览器自动化(指纹+JS 挑战+行为) |
| 需要登录态的复杂流程 | 浏览器拿 cookie → curl_cffi 带 cookie 跑批量 |
混合架构是常态:浏览器负责"过挑战拿凭证",curl_cffi 负责"带凭证跑批量"——速度和通过率兼得。
精髓三:工程化的三个细节
- 超时和重试:curl_cffi 的默认超时较长,批量任务显式设置
timeout=10,配合指数退避重试 - 连接池:Session 复用连接(HTTP/2 多路复用),高频请求别每次新建 Session——既慢又增加指纹暴露面
- 异常指纹漂移:curl_cffi 大版本升级时指纹实现可能微调,升级后重新对拍一次(CI 里加个指纹断言测试最稳)
总结
- curl_cffi 是当前 Python TLS 指纹伪装的最优解,指纹+H2 双模拟
- impersonate 版本与 ua 严格匹配,别用过时指纹
- tls.peet.ws 对拍验证伪装效果
- 混合架构:浏览器过挑战拿凭证,curl_cffi 带凭证跑批量
交流微信:run1255