Jede Python-HTTP-Bibliothek akzeptiert einen Proxy als URL der Form scheme://user:pass@host:port; was sich unterscheidet, ist der Parametername, ob er pro Client oder pro Request gesetzt wird und wie SOCKS5 und DNS behandelt werden. Die folgenden Codebeispiele sind exakt der Code, der mit aktuellen Versionen von requests, httpx und aiohttp funktioniert – jedes wurde vor der Veröffentlichung dieses Artikels durch einen authentifizierenden Proxy ausgeführt – gefolgt von den drei Dingen, die für die meisten Fragen à la „Mein Proxy funktioniert nicht in Python“ verantwortlich sind: falsche Parameternamen aus alten Tutorials, fehlende SOCKS-Erweiterungen und ein TLS-Fingerabdruck, der das Skript unabhängig von der IP verrät.
Die Proxy-URL
http://user:pass@proxy.example.com:8080 # HTTP-Proxy, verwendet für http://- und https://-Ziele
socks5://user:pass@proxy.example.com:1080 # SOCKS5, DNS lokal aufgelöst
socks5h://user:pass@proxy.example.com:1080 # SOCKS5, DNS vom Proxy aufgelöst (diese Variante verwenden)
Zwei Punkte, die oft zu Verwirrung führen. Erstens: Ein HTTP-Proxy verarbeitet auch HTTPS-Ziele – der Client sendet CONNECT und tunnelt TLS durch den Proxy – daher benötigen Sie fast nie ein https://-Proxy-Schema; das würde TLS zum Proxy selbst bedeuten, was nur wenige Anbieter unterstützen. Zweitens: Wenn Ihr Benutzername Rotationsparameter enthält (user-country-de-session-abc123) oder Ihr Passwort @, : oder / enthält, müssen Sie diese URL-encoden (urllib.parse.quote(pw, safe='')), sonst wird die URL falsch geparst.
requests
import requests
PROXY = "http://user:pass@proxy.example.com:8080"
proxies = {"http": PROXY, "https": PROXY}
# pro Request
r = requests.get("https://api.ipify.org?format=json", proxies=proxies, timeout=20)
print(r.json())
# pro Session (verwendet Verbindungen wieder; der übliche Weg)
s = requests.Session()
s.proxies.update(proxies)
r = s.get("https://api.ipify.org?format=json", timeout=20)
Das Dictionary ist nach dem Ziel-Schema benannt: Requests an http://-URLs verwenden den Eintrag "http", Requests an https://-URLs den Eintrag "https". Setzen Sie beide auf denselben Proxy, es sei denn, Sie haben einen Grund, das nicht zu tun. Übergeben Sie immer ein timeout; ein hängender Proxy lässt Ihr Skript sonst endlos hängen.
SOCKS5 erfordert die Zusatzinstallation: pip install "requests[socks]". Dann proxies = {"http": "socks5h://…", "https": "socks5h://…"}. Ohne die Zusatzinstallation erhalten Sie InvalidSchema: Missing dependencies for SOCKS support.
Umgebungsvariablen: requests berücksichtigt standardmäßig HTTP_PROXY / HTTPS_PROXY / NO_PROXY (trust_env=True). Wenn ein Proxy unerwartet verwendet wird, obwohl Sie keinen gesetzt haben, oder nicht verwendet wird, obwohl Sie einen gesetzt haben, überprüfen Sie die Umgebung.
httpx
import httpx
PROXY = "http://user:pass@proxy.example.com:8080"
# synchron
with httpx.Client(proxy=PROXY, timeout=20) as client:
r = client.get("https://api.ipify.org?format=json")
print(r.json())
# asynchron
import asyncio
async def main():
async with httpx.AsyncClient(proxy=PROXY, timeout=20) as client:
r = await client.get("https://api.ipify.org?format=json")
print(r.json())
asyncio.run(main())
Der Parameter heißt proxy= (Singular). Ältere Tutorials zeigen proxies={"http://": …, "https://": …}; dieses Schlüsselwort wurde in httpx 0.26 als veraltet markiert und in 0.28 entfernt; die Übergabe führt jetzt zu TypeError: Client.__init__() got an unexpected keyword argument 'proxies'. Wenn Sie unterschiedliche Proxys für verschiedene Ziele benötigen, verwenden Sie mounts:
mounts = {
"https://api.example.com": httpx.HTTPTransport(proxy="http://user:pass@dc-proxy:8080"),
"all://": httpx.HTTPTransport(proxy="http://user:pass@resi-proxy:8080"),
}
client = httpx.Client(mounts=mounts)
SOCKS5: pip install "httpx[socks]", dann proxy="socks5://…". httpx löst Hostnamen standardmäßig über den SOCKS-Proxy auf. HTTP/2: pip install "httpx[http2]" und httpx.Client(http2=True, …) – relevant, weil ein Browser hinter einem Proxy ohnehin HTTP/2 verwendet (siehe HTTP/2 und HTTP/3 durch Proxys).
aiohttp
import aiohttp, asyncio
PROXY = "http://user:pass@proxy.example.com:8080"
async def main():
async with aiohttp.ClientSession() as session:
async with session.get("https://api.ipify.org?format=json",
proxy=PROXY,
timeout=aiohttp.ClientTimeout(total=20)) as r:
print(await r.json())
asyncio.run(main())
Der Proxy wird pro Request übergeben (oder einmalig über einen benutzerdefinierten Connector gesetzt). Die Anmeldedaten stehen in der URL; die separate Form proxy_auth=aiohttp.BasicAuth(...) funktioniert in 3.x noch, ist aber seit 3.14 als veraltet markiert und soll in 4.0 entfernt werden, daher bevorzugen Sie die URL-Form. aiohttp liest nicht die Umgebungsvariablen HTTP_PROXY, es sei denn, Sie erstellen die Session mit trust_env=True. Natives aiohttp spricht nur HTTP-Proxys; für SOCKS verwenden Sie das Paket aiohttp-socks und dessen ProxyConnector.
Rotierende Proxys: das Session-ID-Muster
Mit einem Backconnect-Gateway (siehe wie Rotations-Gateways funktionieren) rotieren Sie in Python selten selbst – Sie rotieren, indem Sie den Benutzernamen ändern. Eine neue Session-ID bedeutet eine neue Ausgangs-IP; eine wiederverwendete behält sie bei:
import secrets, requests
def proxy_for(session_id: str, country: str = "de") -> dict:
user = f"customer-country-{country}-session-{session_id}" # anbieterspezifisches Format
url = f"http://{user}:PASSWORD@gate.provider.com:7777"
return {"http": url, "https": url}
# sticky: gleiche IP für einen mehrstufigen Ablauf
sid = secrets.token_hex(4)
s = requests.Session(); s.proxies.update(proxy_for(sid))
s.get("https://shop.example/login"); s.post("https://shop.example/cart", data=...)
# rotierend: neue IP pro Element
for url in urls:
requests.get(url, proxies=proxy_for(secrets.token_hex(4)), timeout=20)
Rotieren Sie auch bei Fehlern: Fangen Sie 403/429 und ein CAPTCHA-Marker ab und wiederholen Sie mit einer frischen Session-ID und einem frischen Cookie-Jar – dieselbe IP mit denselben Cookies ist derselbe Besucher.
Der Fehler, den kein Proxy behebt: TLS-Fingerabdruck
Alle drei Bibliotheken stellen TLS-Verbindungen über Pythons ssl-Modul (OpenSSL) her. Anti-Bot-Systeme erkennen diesen Handshake und wissen, dass es kein Browser ist, egal wie Sie den User-Agent setzen. Hinter einer perfekten Residential-IP wird das Skript trotzdem als Skript identifiziert – der Mechanismus wird in TLS-Fingerprinting erklärt erläutert. Für geschützte Ziele wechseln Sie zu einem impersonierenden Client; curl_cffi behält eine requests-ähnliche API:
# pip install curl_cffi
from curl_cffi import requests as cffi_requests
r = cffi_requests.get("https://protected.example/",
impersonate="chrome", # reproduziert Chromes TLS- und HTTP/2-Fingerabdruck
proxies={"https": "http://user:pass@proxy.example.com:8080"},
timeout=20)
Halten Sie dann den Rest der Geschichte konsistent – einen Chrome-User-Agent, passende sec-ch-ua-Client-Hints, Accept-Language plausibel für das Land des Proxys. Für Websites, die zusätzlich JavaScript-Herausforderungen erfordern, reicht kein HTTP-Client; verwenden Sie einen echten Browser wie in Proxys in Playwright, Puppeteer und Selenium.
Fehler und ihre Bedeutung
| Sie sehen | Es bedeutet | Behebung |
|---|---|---|
ProxyError … 407 Proxy Authentication Required | Falsche Anmeldedaten oder Ihre IP ist nicht whitelisted | Benutzer/Passwort prüfen (lange Rotationsstrings!), Sonderzeichen URL-encoden, Whitelist überprüfen |
InvalidSchema: Missing dependencies for SOCKS support | requests ohne SOCKS-Erweiterung | pip install "requests[socks]" |
TypeError: … unexpected keyword argument 'proxies' | httpx ≥ 0.28 mit entferntem Parameter | Verwenden Sie proxy= oder mounts= |
ProxyError … Cannot connect to proxy / ConnectTimeout | Falscher Host/Port, Proxy down oder Firewall | Mit curl -x verifizieren; anderes Protokoll versuchen |
| Echte IP von einem IP-Echo-Endpunkt zurückgegeben | Proxy nicht angewendet (falscher Dict-Key, Umgebungsvariable überschreibt, fehlender Per-Request-Parameter bei aiohttp) | session.proxies ausgeben; trust_env prüfen; proxy= beim Request übergeben |
SSLError nur durch den Proxy | Proxy fängt TLS ab (MITM) oder falsches Schema | http://-Schema für den Proxy verwenden; Anbieter fragen, ob er TLS terminiert |
| 403/CAPTCHA auf geschützten Websites, IP sieht gut aus | TLS/HTTP-Fingerabdruck identifiziert Python | curl_cffi mit impersonate oder ein echter Browser |
| Funktioniert eine Weile, dann 429 | Pro-IP-Rate-Limit erreicht | Session-ID rotieren; langsamer machen; Rotationsanleitung beachten |
Eine minimale, korrekte Vorlage
import requests, secrets
from urllib.parse import quote
GATE, PORT = "gate.provider.com", 7777
USER_BASE, PASS = "customer-country-de", quote("p@ss:word", safe="")
def make_session() -> requests.Session:
sid = secrets.token_hex(4)
url = f"http://{USER_BASE}-session-{sid}:{PASS}@{GATE}:{PORT}"
s = requests.Session()
s.proxies.update({"http": url, "https": url})
s.headers.update({"User-Agent": "python-requests"}) # ehrlicher UA für tolerante Ziele
return s
s = make_session()
r = s.get("https://api.ipify.org?format=json", timeout=20)
r.raise_for_status()
print(r.json())
Verifizieren Sie, dass sich die IP ändert, und bauen Sie darauf auf. Für einen vollständigen Pre-Flight (Leaks, Header, Blocklisten) siehe So testen Sie einen Proxy; für die Wahl zwischen Datacenter- und Residential-Proxys für ein bestimmtes Ziel siehe den Vergleich der Proxy-Typen.
Häufig gestellte Fragen
Wie verwende ich einen Proxy mit Python requests?
Übergeben Sie proxies={"http": url, "https": url} an den Request oder setzen Sie es auf einer Session, wobei url die Form http://user:pass@host:port hat. Fügen Sie timeout= hinzu. Für SOCKS5 installieren Sie requests[socks] und verwenden Sie socks5h://.
Warum meldet httpx „unexpected keyword argument proxies“?
Weil proxies= in httpx 0.28 entfernt wurde. Verwenden Sie proxy="http://…" für einen einzelnen Proxy oder mounts= für zielspezifische Proxys.
Wie setze ich einen Proxy in aiohttp?
Übergeben Sie proxy="http://user:pass@host:port" bei jedem Request (session.get(url, proxy=…)). Der Parameter proxy_auth= ist veraltet; setzen Sie die Anmeldedaten in die URL. Verwenden Sie aiohttp-socks für SOCKS.
Wie rotiere ich Proxys in Python?
Mit einem Backconnect-Anbieter ändern Sie die Session-ID im Proxy-Benutzernamen pro Request oder pro Ablauf – keine IP-Liste nötig. Rotieren Sie bei 403/429 und kombinieren Sie jede neue IP mit einem frischen Cookie-Jar.
Warum wird mein Skript blockiert, während mein Browser auf demselben Proxy nicht blockiert wird?
TLS- und HTTP/2-Fingerprinting: Das ssl-Modul von Python sieht nicht wie ein Browser aus. Verwenden Sie curl_cffi mit impersonate= oder automatisieren Sie einen echten Browser.
Sollte ich socks5 oder socks5h verwenden?
socks5h. Das h lässt den Proxy Hostnamen auflösen, verhindert DNS-Leaks und ermöglicht den Zugriff auf Hosts, die nur der Proxy auflösen kann.