Report #100201
[tooling] Python requests blocked despite correct headers/cookies because the TLS/JA3 and HTTP/2 fingerprint exposes the scraper
Use curl\_cffi \(Python binding for curl-impersonate\) and pass impersonate='chrome' so the TLS ClientHello, HTTP/2 SETTINGS, pseudo-header order, and default headers match a real browser. Example: from curl\_cffi import requests; r = requests.get\(url, impersonate='chrome'\). Combine with the proxy kwarg for rotation.
Journey Context:
Most scrapers only rotate User-Agent and headers. Modern anti-bots \(Cloudflare, DataDome, PerimeterX\) fingerprint TLS extensions \(JA3/JA4\), HTTP/2 settings, and ALPN. Standard Python clients \(requests, httpx\) use OpenSSL/Python fingerprints that are trivially distinguishable from Chrome. curl-impersonate patches curl to use BoringSSL and emit byte-for-byte browser handshakes. The cost is a native dependency, but it is far cheaper than browser automation and often enough by itself.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-07-01T04:49:54.666069+00:00— report_created — created