Fetch URLs with a browser-matched TLS/JA3 fingerprint (via curl_cffi) through rotating authenticated proxies, with automatic anti-bot block detection and retry.
Project description
tls-impersonate-proxy
Fetch URLs with a real browser's TLS/JA3 fingerprint (via curl_cffi) through rotating authenticated proxies, with automatic anti-bot block detection and retry.
Why your scraper gets blocked before it even sends a request
Most "the proxies don't work" problems aren't an IP problem — they're a TLS problem.
Before a single byte of your HTTP request is parsed, the server sees how your client negotiates TLS: the cipher suites, extensions and curve order. It hashes that into a JA3/JA4 fingerprint. Python requests, httpx, aiohttp, curl and Go's net/http each produce a handshake no real Chrome or Safari ever sends — so you can be on a pristine residential IP, with perfect headers, and still get fingerprinted as a bot on the first packet.
tls-impersonate-proxy fixes the layer that rotating more proxies never touches:
- Browser-matched JA3 — borrows real Chrome / Safari / Edge TLS profiles from
curl_cffi, so the handshake lines up with yourUser-Agent. - Proxy rotation — round-robins a list of authenticated proxies (HTTP / SOCKS5).
- Block detection + retry — a
403/429/503or a Cloudflare / DataDome / PerimeterX / Akamai challenge page triggers a real retry on a fresh exit instead of silently returning garbage.
Install
pip install tls-impersonate-proxy
CLI
# Fetch with a rotating browser fingerprint through a residential proxy
tls-fetch https://example.com -x socks5h://USERNAME:PASSWORD@us.jibaoproxy.com:913
# Pin a specific browser, print status + headers only
tls-fetch https://tls.browserleaks.com/json --impersonate chrome -i
# Rotate across several exits, retry up to 6 times on a block
tls-fetch https://target.site \
-x socks5h://USERNAME:PASSWORD@us.jibaoproxy.com:913 \
-x socks5h://USERNAME:PASSWORD@de.jibaoproxy.com:913 \
--retries 6
Library
from tls_impersonate_proxy import ImpersonateClient, BlockedError
client = ImpersonateClient(
proxies=[
"socks5h://USERNAME:PASSWORD@us.jibaoproxy.com:913",
"socks5h://USERNAME:PASSWORD@de.jibaoproxy.com:913",
],
impersonate=None, # None = rotate chrome/safari/edge fingerprints
max_retries=4,
)
try:
resp = client.get("https://target.site")
print(resp.status_code, len(resp.text))
except BlockedError as e:
print("still blocked:", e)
One-shot helper:
from tls_impersonate_proxy import fetch
html = fetch("https://target.site",
proxies=["socks5h://USERNAME:PASSWORD@us.jibaoproxy.com:913"]).text
The fingerprint has to match the exit
A browser-matched JA3 gets you past the TLS check, but the exit IP still has to read as a real person. A datacenter ASN is scored as automation no matter how perfect the handshake is — the two signals have to agree.
- Verify the JA3 your client actually sends (and the exit ASN) with the free tool: check.jibaoproxy.com
- Residential exits with clean ASNs and sticky sessions: jibaoproxy.com —
$5/GBresidential,$0.8/GBdatacenter,$5free credit on signup.
Further reading
- JA3/TLS fingerprint detection, explained
- Bypassing DataDome & PerimeterX in 2026
- Headless browser detection & CDP leaks
License
MIT — see LICENSE. Use responsibly and respect target sites' terms and robots.txt.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file tls_impersonate_proxy-0.1.0.tar.gz.
File metadata
- Download URL: tls_impersonate_proxy-0.1.0.tar.gz
- Upload date:
- Size: 6.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1a83db17a73ef933f48602bdb7ad4b0fe45fdea49e3d95c273c506fd84f06b2d
|
|
| MD5 |
2a95901ee64967a700f6caa52a828ed7
|
|
| BLAKE2b-256 |
80f24c5f7cea2a6fa29b75f8f83bb87fbbc9274b321e1bf89ecd58eecb733c4f
|
File details
Details for the file tls_impersonate_proxy-0.1.0-py3-none-any.whl.
File metadata
- Download URL: tls_impersonate_proxy-0.1.0-py3-none-any.whl
- Upload date:
- Size: 7.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7a7541515701fd6ffa6b49b32b0a37fd48235914fda4e22b0204265cc53d3c58
|
|
| MD5 |
d7da0e1f3151a92e9f75a49930379cd9
|
|
| BLAKE2b-256 |
1f0f576fc7f2a29128d1f314010e2a0edd69c6b214071fa159af7eeba2d271c6
|