curl_cffi proxy
A curl_cffi proxy is a curl_cffi session that tunnels every HTTP and HTTPS call through an upstream gateway while impersonating a real browser TLS and HTTP/2 fingerprint. Pass the Aethyn URL on proxy or proxies, set impersonate="chrome", and the request exits from a household IP with a Chrome-shaped handshake instead of Python's.
Why a residential curl_cffi proxy
Python requests can send a Chrome User-Agent and still fail the handshake. Anti-bot systems hash the TLS Client Hello (JA3/JA4) and HTTP/2 SETTINGS; stock OpenSSL from requests or httpx does not match Chrome. curl_cffi is a Python binding for curl-impersonate: impersonate="chrome" aligns cipher order, extensions, and HTTP/2 frames with a current Chrome profile, and injects matching default headers unless you turn them off. That is the TLS layer. It is not a browser. It does not run JavaScript, hydrate a Shopping grid, or clear a JS challenge. Pair it with a residential exit so the ASN is a household ISP rather than AWS. Aethyn encodes country, optional Elite city or ISP, and sticky lifetime on the username. Omit a session id to rotate per request. Add -session-<id>-lifetime-<minutes> (1–1440, default 30) when a cookie must stay on the IP that earned it. HTTP CONNECT on port 2099 (Premium) or 5499 (Elite) covers HTTPS. SOCKS5 is 1099 / 3499 on the same pool. Python 3.10+.
Setup steps
- 1Install curl_cffi (Python 3.10+): pip install curl_cffi --upgrade.
- 2Grab your Aethyn username (aethyn-XXXXX) and password from the dashboard.
- 3Pass the proxy URL and impersonate="chrome" on the request or Session.
- 4Add targeting suffixes (-country-, optional -city- on Elite, -session-, -lifetime-) to the username.
Code
from curl_cffi import requests
proxy = "http://aethyn-XXXXX:PASSWORD@proxy.aethyn.io:2099"
proxies = {"http": proxy, "https": proxy}
r = requests.get(
"https://httpbin.org/ip",
proxies=proxies,
impersonate="chrome",
timeout=30,
)
print(r.json()) # fresh residential exit; Chrome-shaped TLSfrom curl_cffi import requests
# Same rotating-pool IP for ~30 minutes while a cookie lives
user = "aethyn-XXXXX-country-us-session-cffi1-lifetime-30"
proxy = f"http://{user}:PASSWORD@proxy.aethyn.io:5499"
proxies = {"http": proxy, "https": proxy}
with requests.Session() as s:
r = s.get(
"https://httpbin.org/ip",
proxies=proxies,
impersonate="chrome",
timeout=30,
)
print(r.json())from curl_cffi import requests
proxy = "socks5h://aethyn-XXXXX:PASSWORD@proxy.aethyn.io:1099"
proxies = {"http": proxy, "https": proxy}
r = requests.get(
"https://httpbin.org/ip",
proxies=proxies,
impersonate="chrome",
timeout=30,
)
print(r.json()) # socks5h = DNS at the proxy, no local leakfrom curl_cffi import requests
CHALLENGE = ("unusual traffic", "sorry/index", "verify you are human")
CONSENT = ("before you continue", "consent.google.com")
proxy = "http://aethyn-XXXXX-country-us:PASSWORD@proxy.aethyn.io:2099"
proxies = {"http": proxy, "https": proxy}
with requests.Session() as s:
r = s.get(
"https://example.com",
proxies=proxies,
impersonate="chrome",
timeout=30,
)
low = r.text.lower()
if r.status_code != 200:
status = "http_error"
elif any(m in low for m in CHALLENGE):
status = "challenge"
elif any(m in low for m in CONSENT):
status = "consent"
else:
status = "ok"
# Persist extracted fields only when status == "ok"
print(r.status_code, status)Replace aethyn-XXXXX and PASSWORD with your dashboard credentials. See the full targeting reference and protocol/port list.
Troubleshooting
The failures that look like “curl_cffi is broken” are usually a Python JA3 you did not impersonate, a 407, a header/TLS mismatch, or a 200 that is still a challenge page. If you omit impersonate, curl_cffi is just another HTTP client — add impersonate="chrome" (rolling alias; pin chrome131 only to freeze a basket — profiles change as the library updates). A 407 means the username or password is wrong, or a targeting suffix landed on the password side of the URL. If you override User-Agent or Sec-CH-UA while impersonating, keep them in lockstep with the TLS profile or use default_headers=False and own the whole set. HTTP 200 with unusual-traffic, /sorry/, or Before you continue is not success — classify the body before you store it. If curl_cffi and requests fail identically through a clean residential exit but Playwright returns the grid, you need JavaScript, not more IPs. See the vs-Playwright protocol. Timeouts belong on every call; residential hops are slower than a local CDN fetch.
Tips
- Always pass impersonate="chrome" (or a pinned chromeNNN). Without it, curl_cffi still ships a library TLS fingerprint.
- Use a Session() so cookies survive. Sticky -session- on the username is the exit IP, not the cookie jar.
- Prefer socks5h:// over socks5:// so DNS resolves at the proxy.
- HTTP 200 is not success. Classify challenge and consent HTML before you insert a row.
- When the page hydrates in JavaScript, switch to Playwright — same Aethyn username, different client.
- AsyncSession works the same way under asyncio; impersonate and proxy still belong on every call.