HTTPX-Proxys einrichten: Anmeldung, Umgebung und Timeouts
HTTPX-Proxy mit proxy= setzen, Anmeldung vom Ziel trennen, HTTPS über CONNECT führen und Timeouts sowie Umgebungsvariablen sauber prüfen.
Dieser Text ist für Python-Entwickler, die HTTPX 0.28.1 über einen HTTP-Proxy schicken und den Weg prüfen wollen. Die Beispiele nutzen Dummy-Zugangsdaten. Top Proxy verkauft keine IPs und verteilt keine freien Schlüssel. Ein 200er im Browser auf Meine IP beweist nicht die Route dieses Clients.
01HTTPX-Proxy mit proxy= setzen
Die installierte Bibliothek nimmt proxy= an httpx.get und an httpx.Client. HTTP-Proxys in HTTPX (abgerufen am 14. Oktober 2026) sagt klar: die Proxy-URL kommt beim Client oder bei den Top-Level-Helfern. Eine Zeichenkette oder ein httpx.Proxy reicht für einen Hop. HTTPX 0.28.0 hat das ältere Argument proxies= entfernt. Dieser Text bleibt bei 0.28.1 und proxy=.
Das URL-Schema des Proxys und das URL-Schema des Ziels sind zwei Knöpfe. proxy="http://127.0.0.1:PORT" schickt HTTP und HTTPS über denselben Hop. Ein HTTPS-Ziel braucht deshalb kein https:// vor dem Proxy.
Die Zahlen unten stammen aus einem kontrollierten Loopback-Lauf am 14. Oktober 2026 mit Python 3.14.6, HTTPX 0.28.1, httpcore 1.0.9 und OpenSSL 3.6.3. Das ist Methodik. Es ist kein Paket auf dieser Seite und kein öffentlicher Download. Die Ports aus diesem Lauf sind danach weg. Nutzen Sie einen Proxy und einen Origin, die bei Ihnen noch laufen, plus die CA, die zu diesem Origin gehört.
- Die importierte Version pinnen. Dieser Text hat HTTPX 0.28.1 gelesen, nicht die Online-Doku als Runtime.
- Einen
Clientmitproxy=bauen.trust_env=Falseisoliert implizite Proxy- und CA-Einstellungen aus der Umgebung. Ein explizitesproxy=gewinnt in HTTPX 0.28.1 gegen geerbtesHTTP_PROXY. - Ein HTTP-Ziel treffen, das Sie kontrollieren. Den Proxy-Log lesen, nicht nur den Status.
- Den Client im Kontextmanager schließen. Ein vergessener Client ist ein offenes Socket, kein schnelleres Skript.
Ohne proxy= und ohne Umgebungsvariablen traf der Client den HTTP-Origin mit Status 200 und Body origin-http:ok. Der offene Dummy-Proxy zählte null Ereignisse. Das ist die direkte Kontrolle. Sie sagt nichts darüber, was HTTPX täte, wenn HTTP_PROXY noch stünde.
Mit httpx.Proxy("http://127.0.0.1:PORT", auth=(user, passwort)) und trust_env=False kam Status 200, Origin-Kennung origin-http, Absolute-Form GET http://httpx-de.origin:PORT/, authorized: true. Der Origin sah kein Proxy-Authorization. Ein 200er allein hätte den Hop nicht benannt. Das Log hat ihn benannt.
Wenn Sie zwei Ausgänge brauchen, stecken Sie nicht zwei URLs in proxy=. Nutzen Sie mounts mit HTTPTransport(proxy=...) je Muster. verify, trust_env und retries gehören auf den Transport. Die Client-Option verify= ist in diesem Build nicht mitgefahren. Ein Mount, das nur Client(verify=ctx) erbte, scheiterte mit ConnectError und SSLCertVerificationError: unable to get local issuer certificate. Derselbe Request klappte, sobald der Transport selbst verify=ctx bekam.
Der Proxy-Checker sagt, ob ein Host überhaupt HTTP annimmt. Er ist kein Beweis für diesen Python-Prozess.
Gegen Ihren eigenen, noch laufenden Proxy reicht die Form unten. PROXY_PORT, ORIGIN_PORT und ca.pem kommen von Ihnen.
import httpx
proxy = httpx.Proxy(
"http://127.0.0.1:PROXY_PORT",
auth=("lab-user", "lab-pass"),
)
timeout = httpx.Timeout(5.0, connect=2.0, read=2.0)
with httpx.Client(proxy=proxy, trust_env=False, timeout=timeout) as client:
response = client.get("http://127.0.0.1:ORIGIN_PORT/")
print(response.status_code, response.text)

Dummy-User in diesem Text sind Etiketten, keine Konten. Passwörter gehören nicht ins Repo und nicht in Screenshots.
02HTTPS über einen HTTP-Proxy tunneln
Leute nennen das oft HTTPS-Proxy, weil die Website https:// trägt. Der Hop davor bleibt ein HTTP-Proxy, der CONNECT spricht. Die HTTPX-Doku nennt denselben Stolperstein: der Schlüssel https:// in mounts ist das Zielschema. Die Proxy-URL davor ist meist http://. Das ist kein Tippfehler.
Weiterleitung und Tunnel sind verschiedene Mechanismen. Bei http:// stellt der Proxy die Origin-Anfrage und gibt die Origin-Bytes zurück. Bei https:// schickt der Client CONNECT host:port, der Proxy öffnet TCP, TLS läuft zwischen Client und Origin durch diesen Tunnel. Eine gefälschte 200 auf CONNECT ohne Byte-Tunnel ist kein HTTPS-Proxy.
- Die Proxy-URL auf
http://127.0.0.1:PROXY_PORTlassen, auch wenn das Zielhttps://localhost:ORIGIN_HTTPS_PORT/ist. - Die Origin-CA mit
ssl.create_default_context(cafile="ca.pem")laden und alsverify=übergeben.verify=Falseist kein Normalfall. - Im Proxy-Log
CONNECTsuchen, bevor Sie den 200er feiern. - Denselben Lauf ohne diese CA wiederholen. Sie wollen TLS-Fehler nach CONNECT, nicht „Proxy tot“.
Mit korrekten Dummy-Daten kam CONNECT zu httpx-de.origin plus Origin-Status 200 und Body origin-https:ok. Ohne Labor-CA blieb CONNECT autorisiert. HTTPX hob ConnectError mit Kette SSLCertVerificationError: certificate verify failed: unable to get local issuer certificate. Der Tunnel war da. Das Zertifikat nicht.
import httpx
import ssl
ctx = ssl.create_default_context(cafile="ca.pem")
proxy = httpx.Proxy(
"http://127.0.0.1:PROXY_PORT",
auth=("lab-user", "lab-pass"),
)
with httpx.Client(proxy=proxy, verify=ctx, trust_env=False, timeout=5.0) as client:
response = client.get("https://localhost:ORIGIN_HTTPS_PORT/")
print(response.status_code)
ca.pem muss zu dem Origin passen, mit dem Sie gerade sprechen. Eine CA aus einem alten Lauf hilft nicht, wenn der Origin neu ausgestellt wurde. localhost und 127.0.0.1 sind nur dann gültig, wenn das Zertifikat diese Namen trägt.
SOCKS5 beschreibt die HTTPX-Doku als optionales Extra über pip install httpx[socks]. Dieser Lauf hat keinen SOCKS-Fixture gebaut. Behaupten Sie SOCKS-ATYP nicht aus der HTTP-Seite.

03Proxy-Anmeldung von Ziel-Anmeldung trennen
Proxy-Zugang ist nicht auth=. auth= ist Origin-Anmeldung. Wer die beiden mischt, debuggt eine Stunde die falsche Schicht.
Die Proxy-Seite erlaubt Userinfo in der Proxy-URL. Die API erlaubt außerdem httpx.Proxy(url, auth=(user, passwort)). Beide Wege sind legal. Das Dummy-Passwort in der Methodik enthielt @, :, /, # und %. Diese Zeichen gehören in die Userinfo nur nach komponentenweiser Percent-Kodierung, oder ins auth=-Tupel am Proxy, das nicht durch den URL-Parser läuft. Logs und Abbildungen haben den Wert entfernt. Drucken Sie Proxy-Authorization nicht beim Debuggen.
Fehlende und falsche Zugangsdaten sind nicht ein Verhalten.
Beim HTTP-Forwarding lieferte ein Request ohne Proxy-User Status 407. HTTPX hat das als status_code == 407 gezeigt, ohne Exception. Falsches Dummy-Passwort ebenso. Das Fixture schrieb authReason: missing und authReason: wrong. Wenn Ihr Wrapper später wirft, behalten Sie den 407er.
Beim HTTPS-CONNECT hoben dieselben fehlenden oder falschen Dummy-Daten httpx.ProxyError mit der Meldung 407 Proxy Authentication Required. Es gab kein Response-Objekt. CONNECT ist Tunnelaufbau. 407 dort ist Transportfehler, keine Origin-Seite.
Korrekte Dummy-Daten lieferten Origin 200 auf beiden Wegen. Der Origin sah kein Proxy-Authorization. Der Header bleibt am Proxy-Hop. Origin-Basic lag auf einem eigenen Pfad: ohne auth= Status 401, mit Proxy-Tupel und Origin-Tupel Status 200 und Body origin-auth-ok:origin-http.
- Proxy-User und Passwort in
httpx.Proxy(..., auth=(user, passwort))legen, wenn das Passwort reservierte Zeichen hat. auth=für die Website behalten, nicht für den Proxy.- HTTP 407 und CONNECT-
ProxyErrorgetrennt aufschreiben. Die Klasse notieren, die Sie wirklich gefangen haben. - Nicht aus curl schließen, dass HTTPX denselben Header geschickt hat. Diesen Client messen.
import httpx
proxy = httpx.Proxy(
"http://127.0.0.1:PROXY_PORT",
auth=("lab-user", "lab-pass"),
)
with httpx.Client(proxy=proxy, auth=("origin-user", "origin-pass"), trust_env=False) as client:
response = client.get("http://127.0.0.1:ORIGIN_PORT/origin-auth")
print(response.status_code)

Die Dokumentation zu residenzialen Proxys trennt denselben Hop. Das Oxylabs-README zu Residential Proxies (abgerufen am 14. Oktober 2026) nennt HTTP, HTTPS und SOCKS5, Anmeldung per Benutzername und Passwort oder IP-Freigabe, Einstieg pr.oxylabs.io:7777 mit customer-USERNAME:PASSWORD. Das ist dokumentierte Form, kein bezahlter Gateway-Test. Eine zweite Marke ohne frische, funktionierende Produktdoku kommt in die Empfehlung nicht.
04Umgebung und Ausnahmen prüfen
HTTPX liest die Umgebung standardmäßig. Umgebungsvariablen (abgerufen am 14. Oktober 2026) listen HTTP_PROXY, HTTPS_PROXY, ALL_PROXY und NO_PROXY sowie SSL_CERT_FILE und SSL_CERT_DIR. trust_env=False schaltet diese Menge aus. Es heißt nicht „Zertifikate ignorieren“.
HTTPX lädt Origin-Zugangsdaten nicht still aus einer .netrc, nur weil trust_env wahr ist. Das ist nicht Requests. Wenn Sie httpx.NetRCAuth selbst übergeben, gilt das auch mit trust_env=False. Dieser Lauf hat NetRCAuth nicht benutzt.
Loopback lügt oft. Viele Clients umgehen 127.0.0.1. Die Umgebungsfälle nutzten den Hostnamen httpx-de.origin und NO_PROXY="". Ein lokal begrenzter Namensauflöser mappt diesen Namen auf Loopback. Das ist injiziertes Resolver-Verhalten, keine Messung öffentlichen DNS.
HTTP_PROXYundHTTPS_PROXYauf die kodierte Proxy-URL setzen.NO_PROXYleer lassen, wenn das Ziel den Proxy zwingend nutzen soll.Client(trust_env=True)ohneproxy=bauen. Der Lauf lieferte 200, nur Proxy alpha sah das GET, Proxy bravo blieb idle.- Mit
NO_PROXYgleich dem Zielhost wiederholen. Der Origin blieb 200. Alpha sah dieses GET nicht. Das ist Bypass, ein eigener Fall. - Dieselben Variablen mit
trust_env=Falsewiederholen. Der Request ging direkt. Alpha sah nichts.
Explizites proxy= schlug eine widersprüchliche Umgebung. Mit alpha in HTTP_PROXY und proxy= auf bravo bekam bravo das GET, alpha nicht. Status 200 allein hätte den Hop nicht verraten. Zwei instrumentierte Identitäten haben ihn verraten.
trust_env=False hat auch SSL_CERT_FILE als Client-CA abgeschaltet. Mit Labor-CA in SSL_CERT_FILE und trust_env=True kam HTTPS zum Labor-Origin mit 200. Mit trust_env=False und Standard-verify=True hob derselbe URL ConnectError / SSLCertVerificationError. verify= als ssl.create_default_context(cafile=...) auf diesem trust_env=False-Client stellte 200 wieder her. Die Prüfung blieb an. Nur der Env-Lookup war weg.
transport= und mounts= sind verschiedene Konstruktoren. HTTPX 0.28.1 setzt allow_env_proxies = trust_env and transport is None. Ein eigenes transport= überspringt Umgebungs-Proxy-Mounts. Ein mounts=-Dict tut das nicht. Der Client baut Env-Mounts zuerst und aktualisiert die Karte danach mit Ihren Mounts. Spezifischere URL-Muster gewinnen. http:// aus HTTP_PROXY schlägt all://. Wenn geerbtes HTTP_PROXY nicht gelten soll, setzen Sie trust_env=False. Legen Sie proxy= und verify= auf jeden gemounteten HTTPTransport.
import os
import httpx
os.environ["HTTP_PROXY"] = "http://127.0.0.1:PROXY_PORT"
os.environ["NO_PROXY"] = ""
with httpx.Client(trust_env=True, timeout=5.0) as client:
via_env = client.get("http://example.invalid/")
with httpx.Client(trust_env=False, timeout=5.0) as client:
direct = client.get("http://127.0.0.1:ORIGIN_PORT/")
example.invalid ersetzen Sie durch ein Ziel, das Sie wirklich erreichen. Die Variablen setzen Sie in einem Kindprozess, nicht in der Workstation-Umgebung, die andere Tools erbt.

05Synchron und asynchron sauber schließen
Sync und Async sind zwei Clients. Sie teilen die Form von proxy=. Sie teilen keinen Connection-Pool.
with httpx.Client(proxy=..., verify=ctx) as client: ist die synchrone Form. Close passiert beim Verlassen. async with httpx.AsyncClient(proxy=..., verify=ctx) as client: ist die asynchrone Form. Sie await client.get(...). get ohne await im Async-Client ist ein Bug, kein Timeout.
Async Support (abgerufen am 14. Oktober 2026) zeigt denselben Kontextmanager und await. Der Async-Fall in diesem Lauf nutzte AsyncClient mit derselben HTTP-Proxy-URL und dem Labor-SSL-Kontext. await client.get(https_url) lieferte 200 mit Origin-Kennung origin-https. Der Proxy schrieb CONNECT. Das ist ein erfolgreicher Async-Tunnel. Es ist kein Nebenläufigkeits-Benchmark und sagt nichts über Pool-Wiederverwendung unter Last.
Selbst erzeugte Transports brauchen denselben Close-Pfad. HTTPTransport, den der Client über mounts besitzt, schließt der Client. Wenn Sie die Variable über Clients hinweg behalten, rufen Sie transport.close() in finally auf. Der Lauf hat das bei Retry- und Mount-Fällen getan.
Retries gehören auf den Transport. Transports (abgerufen am 14. Oktober 2026) sagt: HTTPTransport(retries=...) wiederholt ConnectError und ConnectTimeout. Es wiederholt nicht 429 oder 503. Mit retries=2 gegen /status/503 zählte der Origin einen Treffer. HTTPX gab 503 zurück. Das ist nicht urllib3 Retry. Kleistern Sie allowed_methods nicht in HTTPX.
import asyncio
import ssl
import httpx
ctx = ssl.create_default_context(cafile="ca.pem")
proxy = httpx.Proxy("http://127.0.0.1:PROXY_PORT", auth=("lab-user", "lab-pass"))
async def main() -> None:
async with httpx.AsyncClient(proxy=proxy, verify=ctx, trust_env=False) as client:
response = await client.get("https://localhost:ORIGIN_HTTPS_PORT/")
print(response.status_code)
asyncio.run(main())

Protokoll und IP-Herkunft sind verschiedene Achsen. Mobile Proxys und residenzielle Proxys beschreiben Herkunft, nicht das HTTPX-API. Dieser Lauf hat kein Land, keine Erfolgsquote und kein Konto behauptet.
06Verbindungs- und Leseprobleme unterscheiden
Nennen Sie die Exception, die Sie gefangen haben. HTTPX hat eine echte Hierarchie. Alles auf „Proxy-Fehler“ zu kippen, versteckt den Hop.
Ein geschlossener Loopback-Port lieferte ConnectError mit ConnectionRefusedError: [Errno 61] Connection refused. Das ist Abweisung. Es ist kein Connect-Timeout. retries=0 und ein endliches Timeout gehörten dazu. Auf diesem Darwin-Kernel hat ein Socket, das gebunden aber nie auf listen lag, nicht abgewiesen. HTTPX hob ConnectTimeout mit TimeoutError nach der Connect-Frist. Dieses Warten ist Fixture-Verhalten für Bind-ohne-Listen. Es ist keine WAN-Laufzeit.
Read-Timeouts betreffen Chunks, nachdem die Antwort begonnen hat. Timeouts (abgerufen am 14. Oktober 2026) trennt connect, read, write und pool. Der Origin /slow-body schickte vollständige Header sofort, schrieb und flushte ein Body-Byte, wartete dann länger als Timeout(read=0.45). Beim Streamen kam Status 200, das First-Byte-Ereignis feuerte, ein Byte kam an, danach ReadTimeout mit TimeoutError. Die Header lagen schon da. ConnectError wäre die falsche Klasse. ConnectTimeout wäre die falsche Klasse. Wenn Sie nur response.text ohne Stream aufrufen, laufen Sie ebenfalls in den Timeout, verlieren aber den Beweis, dass Header ankamen. Ein verzögerter Header allein ist kein Beweis für einen verzögerten Body.
TLS-Fehler nach CONNECT blieben ConnectError mit SSLCertVerificationError. Der Proxy hatte den Tunnel schon angenommen. verify=False würde das verstecken. Lassen Sie es.
| Störung | Was 0.28.1 in diesem Lauf hob | Was es nicht ist |
|---|---|---|
| HTTP-Proxy, Basic fehlt oder falsch | Response-Status 407 | Eine CONNECT-Exception |
| HTTPS-CONNECT, Basic fehlt oder falsch | ProxyError ("407 Proxy Authentication Required") | Eine Origin-407-Seite |
| Labor-HTTPS ohne Labor-CA | ConnectError / SSLCertVerificationError nach CONNECT | Beweis, dass CONNECT nie passierte |
| Geschlossener Loopback-Port | ConnectError / ConnectionRefusedError | ConnectTimeout |
| Bind ohne listen auf Darwin | ConnectTimeout (fixture-spezifisch) | Abweisung oder WAN-RTT |
| Verzögerter Body nach dem ersten Byte | ReadTimeout in iter_bytes() | Ein Connect-Fehler |
Origin /status/503 mit retries=2 | Status 503, ein Origin-Treffer | Ein Application-Retry |

Die Abbildung ist die Ergebnistabelle dieses Laufs, kein 16:9-Cover und kein Screenshot des Checkers.

Die Blöcke oben sind vollständige Vorlagen gegen einen Proxy und Origin, die bei Ihnen noch laufen. Ersetzen Sie Ports, CA und Dummy-Zugang durch Ihre aktuellen Werte. Die Loopback-Messung erklärt die Klassen. Sie liefert kein Kit.
Wenn der Client-Weg ehrlich ist, wählen Sie einen Einstieg, der HTTP-Forwarding und CONNECT dokumentiert. Die Oxylabs-Katalogseite war am 14. Oktober 2026 erreichbar. Die offizielle Doku beschreibt ein HTTP-Gateway mit Benutzername und Passwort oder IP-Freigabe. Das ist Passform auf dem Papier. Dieser Text hat sich in kein Produkt eingeloggt und reiht niemanden.
Wer nur den Browser-Exit braucht, bleibt bei Meine IP. Wer HTTPX braucht, glaubt dem Proxy-Log und der Exception-Klasse dieser Bibliothek. Die beiden widersprechen sich öfter, als Blogposts zugeben.
Wie richte ich einen Proxy in HTTPX ein?
Warum beginnt der Proxy für HTTPS mit http://?
Was unterscheidet Proxy-Anmeldung und auth=?
Schaltet trust_env=False die Zertifikatsprüfung aus?
Warum erscheint ReadTimeout nach den Antwort-Headern?
Wiederholt HTTPTransport auch 429 oder 503?
Ähnliche Artikel
Proxy mit curl nutzen: Anmeldung, CONNECT und Fehler prüfen
HTTP-Proxy in curl setzen, CONNECT für HTTPS prüfen, Anmeldung von -U und -u trennen und Timeouts an Exit-Codes lesen.
Gemini Developer API durch einen HTTP-Proxy schicken
google-genai 2.30.1 über HTTPS_PROXY und CONNECT führen, TLS mit SSL_CERT_FILE prüfen und Transportfehler von 401, 403 und 429 trennen.
Proxy in Playwright konfigurieren und prüfen
Proxy in Playwright Python am Browser oder Context setzen, CONNECT und 407 prüfen, SOCKS5 nur mit Engine-Support und TLS anlassen.




