curl_cffi Proxy-Leitfaden: Einrichtung, Authentifizierung, Rotation und Async

curl_cffi bietet Ihnen einen TLS-Handshake, der einem Browser ähnelt. Ein Proxy bietet Ihnen eine saubere Exit-IP. Hier erfahren Sie genau, wie Sie die beiden miteinander verbinden — und warum das https://-Präfix in Ihrem proxies-Dict ErrCode 35 auslöst.

curl_cffi ist das Python-Binding zu einem Fork von curl-impersonate: Es reproduziert die TLS/JA3- und HTTP/2-Fingerabdrücke eines echten Browsers, anstatt sich selbst als urllib3 zu identifizieren. Das behebt eine Achse der Blockierung. Die andere ist die Exit-IP, wo ein curl_cffi Proxy ins Spiel kommt — und wo die Dokumentation dünn wird. Der offizielle Proxy-Abschnitt umfasst etwa fünfzehn Zeilen, und ein GitHub-Issue vom Februar 2023 gehört immer noch zu den Top fünf zu diesem Thema. Dieser Leitfaden deckt die gesamte Oberfläche ab: den proxy-Parameter, das requests-ähnliche Dict und seine echten Schlüsselnamen, proxy_auth, Sitzungen, rotationsbasierte Anfragen, Async, SOCKS5 — und die genauen Fehlermeldungen, die Sie in eine Suchmaschine eingeben werden.

curl_cffi Proxy-Syntax: Bevorzugen Sie proxy= gegenüber dem proxies-Dict

curl_cffi akzeptiert zwei Formen. Die native ist ein einzelner proxy=-String, hinzugefügt in v0.6.0; das proxies=-Dict existiert für die Kompatibilität mit requests, und die Dokumentation empfiehlt den einzelnen Parameter, es sei denn, Sie benötigen wirklich unterschiedliche Proxies pro Schema. Intern werden sie auf dasselbe reduziert — proxy="..." wird zu {"all": "..."} — und beide funktionieren auf den Modul-Helfern, auf Session, auf AsyncSession und auf individuellen Anfragen.

# pip install curl_cffi --upgrade    (Python 3.10+ since v0.14)
import curl_cffi

PROXY = "http://USER:PASS@gate.quantumproxies.io:PORT"

# Native form — one string, applies to every scheme
r = curl_cffi.get(
    "https://tls.browserleaks.com/json",
    impersonate="chrome",
    proxy=PROXY,
    timeout=30,
)
print(r.status_code, r.json()["ja3n_hash"])

# requests-compatible form
r = curl_cffi.get(
    "https://httpbin.org/ip",
    impersonate="chrome",
    proxies={"http": PROXY, "https": PROXY},
    timeout=30,
)
print(r.json())  # {'origin': '<proxy exit IP>'}

Vier Dinge über dieses Dict sind wissenswert, da keines davon aus dem README offensichtlich ist:

Eine Anmerkung zu Imports: Seit v0.10.0 ist das Paket direkt aufrufbar (curl_cffi.get, curl_cffi.Session). Ältere Tutorials verwenden from curl_cffi import requests, was immer noch funktioniert, aber schlecht neben der echten requests-Bibliothek aussieht — und erklärt, warum die Hälfte der Online-Snippets wie ein anderes Projekt aussieht.

Die https://-Falle: ErrCode 35 und WRONG_VERSION_NUMBER

Dieser einzelne Fehler erzeugt mehr curl_cffi Proxy-Fragen als alles andere zusammen. Issue #6 im Projekt-Tracker — am selben Tag im Februar 2023 eröffnet und geschlossen — rangiert immer noch auf Seite eins, weil der Fehler, den er erzeugt, wie ein TLS-Bug aussieht, anstatt wie ein Konfigurationsfehler:

# WRONG: this asks curl to open a TLS connection *to the proxy itself*
proxies = {"https": "https://USER:PASS@gate.quantumproxies.io:PORT"}

# Failed to perform, ErrCode: 35, Reason:
# 'error:100000f7:SSL routines:OPENSSL_internal:WRONG_VERSION_NUMBER'

# RIGHT: plain HTTP CONNECT, then the TLS tunnel runs through to the target
proxies = {"https": "http://USER:PASS@gate.quantumproxies.io:PORT"}

# Or skip the dict entirely
proxy = "http://USER:PASS@gate.quantumproxies.io:PORT"

Der Schlüssel benennt das Protokoll des Ziels; der Wert benennt, wie Sie den Proxy erreichen. Ein normaler HTTPS-over-HTTP-Proxy nimmt einen Klartext-CONNECT an und tunnelt dann Ihren verschlüsselten Datenverkehr unberührt durch — daher beginnt die Proxy-URL mit http://, selbst wenn jede URL, die Sie abrufen, HTTPS ist. HTTPS-over-HTTPS-Proxies existieren, sind aber selten und müssen vom Gateway ausdrücklich unterstützt werden. Requests formuliert denselben Fehler weitaus hilfreicher — Ihr Proxy scheint nur HTTP und nicht HTTPS zu verwenden — weshalb eine identische Konfiguration wie ein curl_cffi-spezifischer Bug aussehen kann. Neuere Versionen warnen und verlinken Issue #6, aber es ist nur eine Warnung: Die Anfrage schlägt trotzdem fehl.

Authentifizierung: URL-Anmeldedaten oder proxy_auth

Authentifizierte Gateways akzeptieren die übliche eingebettete Form, http://USER:PASS@host:port, mit dem üblichen Haken: Ein unescaped @, : oder / im Passwort teilt die URL an der falschen Stelle und erzeugt einen Authentifizierungsfehler, der wie ein toter Proxy aussieht. curl_cffi bietet einen Notausgang, den requests nicht hat — ein proxy_auth-Tupel, das an libcurl als separate Benutzername- und Passwortoptionen übergeben wird, sodass keine Kodierung erforderlich ist.

import curl_cffi
from urllib.parse import quote

# Option A — credentials in the URL, password URL-encoded
pw = quote("p@ss:word", safe="")
r = curl_cffi.get(
    "https://httpbin.org/ip",
    proxy=f"http://USER:{pw}@gate.quantumproxies.io:PORT",
    impersonate="chrome",
    timeout=30,
)

# Option B — keep credentials out of the URL entirely
r = curl_cffi.get(
    "https://httpbin.org/ip",
    proxy="http://gate.quantumproxies.io:PORT",
    proxy_auth=("USER", "PASS"),
    impersonate="chrome",
    timeout=30,
)
print(r.json())

Eine dritte Option beseitigt diese Fehlerklasse vollständig: IP-Whitelisting. Jeder QuantumProxies Residential-Plan ermöglicht es Ihnen, die IP Ihres Servers zu autorisieren, anstatt Benutzer:Pass zu senden, sodass die Proxy-URL zu einem einfachen http://gate.quantumproxies.io:PORT wird — nichts zu kodieren, kein Geheimnis im Quellcode. Wenn die Anmeldedaten selbst abgelehnt werden, deckt unser Leitfaden zu jeder Ursache von 407 Proxy Authentication Required den Rest ab.

Flussdiagramm einer curl_cffi-Anfrage, die durch ein rotierendes Proxy-Gateway zur Zielseite mit einem browserangepassten TLS-Handshake reist
Der Proxy tunnelt den Handshake, anstatt ihn zu beenden, sodass die Browser-Imitation den Sprung überlebt und das Ziel eine saubere Exit-IP sieht.

Sitzungen, Cookies und das Detail der Anmeldeinformationen-Wiederverwendung

Eine Session hält Cookies, Connection-Pooling und Ihre Standardeinstellungen an einem Ort, was Sie für alles mehrstufige wollen. Setzen Sie impersonate und proxy einmal und jede Anfrage erbt sie:

from curl_cffi import Session

with Session(
    impersonate="chrome",
    proxy="http://USER-session-a1b2:PASS@gate.quantumproxies.io:PORT",
    timeout=30,
    retry=3,
) as s:
    s.get("https://httpbin.org/cookies/set/foo/bar")
    r = s.get("https://httpbin.org/cookies")
    print(r.json(), s.cookies.get_dict())

Zwei Verhaltensweisen verdienen eine Erwähnung. Erstens, wann immer ein Proxy konfiguriert ist, schaltet curl_cffi die Option proxy-credential-no-reuse von libcurl ein: Eine neue Verbindung wird erzwungen, wenn sich der Proxy-Benutzername ändert, und der TLS-Sitzungscache wird auf der Proxy-Adresse basierend gespeichert, sodass eine vorherige Exit-IP nicht in eine spätere Anfrage durch eine wiederverwendete Sitzung durchsickern kann. Wenn Sie Sticky-Session-IDs im Benutzernamen kodieren, wie es die meisten rotierenden Gateways tun, erhalten Sie diese Isolation kostenlos. Zweitens, retry (ein int oder eine RetryStrategy von curl_cffi.requests mit Verzögerung, Backoff und Jitter) wird nur bei einem Transportfehler erneut ausgeführt. Es wiederholt nicht einen 403 oder 429, wie es die status_forcelist von urllib3 tut — diese Schleife müssen Sie noch selbst schreiben. Die Kompatibilitätsdokumente listen Wiederholungen als nicht unterstützt auf, was veraltet ist: Der Parameter wurde in v0.15.0 eingeführt.

Richten Sie curl_cffi auf ein rotierendes Residential-Gateway aus

Rotationsbasierte Anfragen und Async

curl_cffi wirbt mit asyncio mit Proxy-Rotation bei jeder Anfrage, und das ist wörtlich: Ein proxy=-Argument bei einem einzelnen Aufruf überschreibt, was die Sitzung hält. Sie benötigen selten eine Proxy-Liste, um es auszunutzen — ein rotierendes Gateway weist bei jeder Verbindung serverseitig einen neuen Exit zu, sodass ein Endpunkt plus Parallelität bereits Rotation ist. Wo Sie Kontrolle wünschen (eine stabile IP pro Worker, pro Konto, pro Warenkorb), setzen Sie ein Sitzungstoken im Benutzernamen und lassen Sie das Gateway diesen Exit fixieren.

import asyncio
from curl_cffi import AsyncSession

GATE = "gate.quantumproxies.io:PORT"
URLS = ["https://httpbin.org/ip"] * 20

async def fetch(session, url, worker):
    # one sticky exit IP per worker; drop the -session- suffix for full rotation
    proxy = f"http://USER-session-{worker}:PASS@{GATE}"
    r = await session.get(url, proxy=proxy, timeout=30)
    return r.status_code, r.json()["origin"]

async def main():
    async with AsyncSession(impersonate="chrome", max_clients=10) as s:
        return await asyncio.gather(
            *(fetch(s, u, i % 5) for i, u in enumerate(URLS))
        )

for status, ip in asyncio.run(main()):
    print(status, ip)

max_clients begrenzt die gleichzeitigen curl-Handles im Pool (standardmäßig 10), sodass es Ihr echtes Parallelitätsregler ist — ein Semaphor auf ein unbegrenztes Gather zu setzen, ist der übliche Fehler. Die gleiche Größenlogik gilt für jeden asynchronen Client, den wir in asynchrones Python-Scraping mit httpx und aiohttp behandelt haben. Ob Sie pro Anfrage rotieren oder eine Sitzung fixieren, hängt davon ab, ob die Seite den Zustand über Anfragen hinweg verfolgt; die Abwägungen sind in Sticky Sessions vs. Rotating Proxies.

Checkliste, die funktionierende curl_cffi Proxy-Konfigurationen mit den fünf Fehlern vergleicht, die sie brechen
Die meisten curl_cffi Proxy-Fehler sind eines von fünf Dingen — und vier davon sind ein einzelnes Zeichen in einem String.

SOCKS5, HTTP/3 und die Sicherheitsschalter

SOCKS benötigt keine zusätzliche Installation — libcurl ist kompiliert, sodass es im Gegensatz zu requests kein [socks]-Extra gibt, an das man denken muss. Verwenden Sie socks5h://USER:PASS@gate.quantumproxies.io:PORT: Das h verschiebt die DNS-Auflösung zum Proxy, was Lecks aus Ihrem eigenen Netzwerk verhindert und geofenced Hostnamen vom Standort des Exits auflöst. curl_cffi erkennt das socks-Präfix und überspringt das HTTP-Tunneling-Flag, da das SOCKS-Protokoll dies selbst handhabt. Jeder Plan hier bietet HTTP- und SOCKS5-Endpunkte auf demselben Gateway an, sodass das Umschalten ein Schemawechsel und keine neue Bestellung ist.

Wann curl_cffi plus ein Proxy ausreicht

Öfter als die Leute erwarten. Wenn das Ziel JSON von einer internen API oder serverseitig gerendertes HTML bereitstellt und das einzige Hindernis eine Fingerabdruckprüfung ist, klärt ein abgestimmter Handshake plus ein Residential-Exit dies zu einem Bruchteil der Kosten und Latenz eines Browsers. Die FAQ des Projekts ist unverblümt über die Grenze: Fingerabdrücke sind ein Faktor unter mehreren, neben IP-Qualität, Anfragerate und JavaScript-Checks, und höhere Schutzstufen benötigen sowohl einen besseren Proxy-Pool als auch echte Browser-Automatisierung. Wenn die Imitation korrekt konfiguriert ist und Sie immer noch blockiert werden, ist die verbleibende Variable fast immer die Exit-IP — diese in fünf Minuten zu isolieren, ist das Thema von curl_cffi vs requests. Wenn Sie lieber keines von beiden ausführen möchten, übernimmt die Scraper API Fingerabdrücke, Proxies und optionale JS-Rendering hinter einem Aufruf.

Häufig gestellte Fragen

Wie verwende ich einen Proxy mit curl_cffi?

Übergeben Sie proxy="http://USER:PASS@host:port" an jede Anfragemethode, Sitzung oder asynchrone Sitzung. Das requests-ähnliche proxies={"http": ..., "https": ...}-Dict funktioniert ebenfalls, aber das Projekt empfiehlt den einzelnen Parameter, es sei denn, Sie benötigen unterschiedliche Proxies pro Schema. Das Übergeben beider führt zu einem TypeError.

Warum wirft curl_cffi ErrCode 35 WRONG_VERSION_NUMBER?

Weil die Proxy-URL mit https:// beginnt. Ein Standard-Proxy erwartet eine Klartext-CONNECT-Anfrage und tunnelt dann Ihr TLS durch; ein https://-Präfix lässt curl versuchen, mit dem Proxy selbst einen TLS-Handshake durchzuführen, der in einfachem HTTP antwortet. Ändern Sie den Wert zu http:// — der https-Schlüssel bezieht sich auf das Ziel, nicht auf den Hop.

Unterstützt curl_cffi SOCKS5-Proxies?

Ja, nativ — libcurl ist gebündelt, sodass es kein optionales Extra zu installieren gibt. Verwenden Sie das socks5h://-Schema, damit Hostnamen vom Proxy und nicht von Ihrer Maschine aufgelöst werden. SOCKS4, SOCKS4a und einfaches socks5:// werden ebenfalls akzeptiert; die Bibliothek überspringt das HTTP-Tunneling für jeden Proxy, dessen Schema mit socks beginnt.

Kann curl_cffi Proxies bei jeder Anfrage rotieren?

Ja. Ein proxy=-Argument bei einem einzelnen Aufruf überschreibt den Sitzungsstandard, auch innerhalb einer AsyncSession, was das README mit asyncio mit rotationsbasierten Anfragen meint. Mit einem rotierenden Gateway benötigen Sie oft keine Logik: Derselbe Endpunkt gibt bei jeder Verbindung eine andere Exit-IP aus.

Kann curl_cffi Cloudflare umgehen?

Manchmal. Es entfernt das TLS- und HTTP/2-Fingerabdruckmerkmal, was für grundlegende Schutzstufen ausreicht. Es kann keine JavaScript-Herausforderungen ausführen, Turnstile lösen oder eine Rechenzentrums-IP reparieren, die bereits von einer Reputationsdatenbank markiert wurde. Behandeln Sie die Imitation als eines von drei Anforderungen, nicht als die Antwort.

Die gesamte Konfiguration ist kleiner als ihr Ruf: ein proxy-String, impersonate einmal auf der Sitzung gesetzt, ein Timeout bei jedem Aufruf, und Anmeldedaten entweder URL-kodiert oder als proxy_auth-Tupel übergeben. Wenn Sie diese richtig machen, ist die verbleibende Variable die IP-Qualität — ein perfekter Chrome-Handshake von einer markierten Rechenzentrumsadresse ist immer noch eine markierte Rechenzentrumsadresse. Unsere Aufschlüsselung von JA3- und JA4-Fingerprinting erklärt, warum die beiden Prüfungen unabhängig sind.

Erhalten Sie Residential-IPs, die zu Ihrer Imitation passen