Konfiguracja proxy w HTTPX: uwierzytelnianie, środowisko i limity czasu
Ustawić proxy w HTTPX przez proxy=, przekazać dane logowania, utrzymać HTTPS na CONNECT i odróżnić domyślne zmienne środowiska od jawnych mounts i limitów czasu.
Ten poradnik jest dla programistów Pythona, którzy potrzebują, żeby HTTPX 0.28.1 wychodził przez proxy HTTP albo SOCKS5. Prywatne sprawdzenia redakcyjne używały origin na loopback i atrapy proxy CONNECT, nie konta u dostawcy. Nie ma darmowych kluczy, a Top Proxy nie sprzedaje adresów IP. Te sprawdzenia dowodzą wyłącznie laboratoryjnej trasy. To nie jest publiczny plik do pobrania.
01Skierować żądanie przez proxy=
Zainstalowany klient przyjmuje proxy= na httpx.get i na httpx.Client. Starszy HTTPX przyjmował też mapowanie proxies= ze wzorców URL na URL proxy. To był sam HTTPX, nie słownik wyłącznie z Requests. HTTPX 0.28.0 (28 listopada 2024) usunął przestarzały argument proxies. Ten przewodnik zostaje przy 0.28.1 proxy= i mounts=. Forma jednego proxy to ciąg URL albo obiekt httpx.Proxy.
Proxy HTTP (dostęp 14 października 2026) mówi, że ten URL podaje się przy inicjalizacji klienta albo na pomocnikach najwyższego poziomu. Pojedyncze proxy="http://127.0.0.1:PORT" wysyła przez ten przeskok zarówno HTTP, jak i HTTPS. HTTPS nie potrzebuje URL proxy https://. Schemat celu i schemat proxy to różne pokrętła.
- Przypiąć klienta, który naprawdę będzie importowany. Ten przewodnik używał HTTPX 0.28.1, httpcore 1.0.9 i Pythona 3.14.6.
- Zbudować
Clientzproxy=ustawionym na URL proxy HTTP. Na czas dowodu jawnej ścieżki zostawićtrust_env=False, żeby pozostałe zmienne powłoki nie ukradły trasy. - Pobrać origin HTTP, nad którym jest kontrola. Czytać log proxy, nie tylko kod statusu. Laboratoryjny atrapowy forwarder zapisał
GET http://httpx-lab.origin:<port>/zauthorized: true. - Zamknąć klienta menedżerem kontekstu. To zamyka pulę transportu. Zapomniany klient to wyciek gniazda, nie szybszy skrypt.
Bezpośrednia linia bazowa ma znaczenie. Po wyczyszczeniu HTTP_PROXY, HTTPS_PROXY, ALL_PROXY i NO_PROXY w procesie potomnym klient bez proxy= trafił w origin HTTP, a atrapa proxy pozostała bezczynna. To kontrola bez proxy. Nie mówi, co HTTPX zrobiłby, gdyby te zmienne nadal były ustawione. To przyjdzie później.
Jeśli potrzeba dwóch wyjść, nie należy wpychać dwóch URL do proxy=. Użyć mounts z HTTPTransport(proxy=...) na wzorzec i położyć verify, trust_env oraz retries na każdym transporcie. Argument verify= na poziomie klienta w tej kompilacji nie został przekazany na transporty. Mount, który tylko odziedziczył Client(verify=ctx), oblał TLS z ConnectError / SSLCertVerificationError: unable to get local issuer certificate. To samo żądanie przeszło, gdy sam transport dostał verify=ctx.
02Wybrać proxy HTTP dla celu HTTPS
Ludzie nazywają to „proxy HTTPS”, bo witryna jest https://. Przeskok z przodu nadal jest proxy HTTP, które mówi CONNECT. Dokumentacja nazywa to pułapką: klucz https:// w słowniku mounts to schemat celu, a URL proxy przed nim zwykle jest http://.
Przekazywanie i tunelowanie to nie ten sam mechanizm. Dla http:// proxy wykonuje żądanie origin i zwraca bajty origin. Dla https:// klient wysyła CONNECT host:443, proxy otwiera TCP, a TLS idzie między klientem a origin przez ten tunel. Fałszywe 200 z CONNECT bez działającego tunelu bajtów to nie proxy HTTPS. Laboratorium przekazywało prawdziwe ciała origin na HTTP i prawdziwe bajty TLS po CONNECT.
- Zostawić URL proxy na
http://127.0.0.1:<port>nawet wtedy, gdy cel tohttps://httpx-lab.origin:<port>/. - Zaufać origin przez
ssl.create_default_context(cafile=ca.pem)i przekazać ten kontekst jakoverify=. Nie wyłączać weryfikacji. - Potwierdzić, że log proxy pokazuje
CONNECT httpx-lab.origin:<https-port>, zanim świętuje się 200. - Powtórzyć raz z domyślnym magazynem CA i bez laboratoryjnego CA. Potrzebna jest awaria TLS, która mimo to zapisała CONNECT.
Ten ostatni krok operatorzy pomijają. W tym przebiegu CONNECT się udał, a potem HTTPX rzucił ConnectError opakowujący SSLCertVerificationError: unable to get local issuer certificate. Tunel był w porządku. Certyfikat nie. Strona Jaki jest mój adres IP w przeglądarce pokazałaby wyjście przeglądarki, nie tego klienta. Sprawdzanie proxy pokazuje, czy host odpowiada HTTP albo SOCKS5, zanim skieruje się na niego HTTPX.
SOCKS5 to trzecia ścieżka. pip install httpx[socks] pociągnęło socksio 1.0.0. httpx.Proxy w 0.28.1 przyjmuje socks5 i socks5h. Wobec kontrolowanego stanowiska SOCKS5 socks5://127.0.0.1:<port> do http://127.0.0.1:<origin>/ wysłało ATYP ipv4. Ten sam klient z socks5h:// i celem-nazwą hosta wysłał ATYP domain httpx-lab.origin. Użycie socks5:// z tą nazwą hosta też wysłało ATYP domain. Ta kompilacja nie rozwiązywała nazwy hosta lokalnie, a potem nie wysyłała adresu IPv4 tak, jak robią to niektóre konfiguracje curl socks5. Nie należy kopiować folkloru socks5h z Requests do HTTPX. Trzeba zmierzyć handshake.
03Ustawić uwierzytelnianie proxy
Dane logowania proxy to nie auth=. auth= to uwierzytelnianie origin. Pomieszanie ich oznacza godzinę debugowania złego przeskoku.
Strona o proxy kładzie userinfo w URL proxy. API dokumentuje też httpx.Proxy(url, auth=(user, password)). Oba zadziałały w laboratorium. Hasło atrapy zawierało @, :, /, # i %. Te znaki należą do userinfo dopiero po kodowaniu URL składnik po składniku albo do krotki auth= na Proxy, która nigdy nie idzie przez parser URL. Logi i rysunki redagowały wartość. Przy debugowaniu nie należy wypisywać Proxy-Authorization.
Brak danych i złe dane to nie jedno zachowanie.
Przy przekazywaniu HTTP żądanie bez użytkownika proxy zwróciło HTTP 407 ze stanowiska. HTTPX pokazał to jako status_code == 407. Złe hasło dało to samo. Stanowisko zapisało authReason: missing i authReason: wrong. Bez wyjątku. Jeśli wrapper później rzuca, należy zachować 407.
Przy HTTPS CONNECT te same brakujące albo złe dane atrapy rzuciły httpx.ProxyError z komunikatem 407 Proxy Authentication Required. Nie było obiektu odpowiedzi do odczytu. CONNECT to zestawianie tunelu. 407 tam to awaria transportu, nie strona origin.
Poprawne dane zwróciły origin 200 na obu ścieżkach. Origin nigdy nie zobaczył Proxy-Authorization. Ten nagłówek zostaje na przeskoku proxy. Jeśli potrzeba też origin Basic, wysłać auth=(origin_user, origin_pass) na kliencie. Laboratoryjna trasa /origin-auth zwróciła 401 bez tego i 200, gdy oba przeskoki były uwierzytelnione.
- Użytkownika i hasło proxy kłaść w
httpx.Proxy(..., auth=(user, password)), gdy hasło ma znaki zastrzeżone. - Origin
auth=zostawić dla witryny, nie dla proxy. - HTTP 407 i CONNECT
ProxyErrortraktować jako różne wyniki. Zapisać klasę, którą faktycznie złapano. - Odrzucić myśl, że „działa w curl” dowodzi, iż HTTPX wysłał ten sam nagłówek. Trzeba to udowodnić na tym kliencie.
Produkty rezydenckie dokumentują ten sam podział. Oxylabs Residential Proxies (dostęp 14 października 2026) wymienia HTTP, HTTPS, HTTP/3 i SOCKS5, z nazwą użytkownika i hasłem albo listą dozwolonych IP, oraz wejście pr.oxylabs.io:7777 w formie customer-USERNAME:PASSWORD. To udokumentowany kształt punktu końcowego, nie test ich puli. Szybki start rezydencki Decodo (tego samego dnia) pokazuje gate.decodo.com:7000 i mapowanie Pythona, które wysyła zarówno http, jak i https przez jeden URL proxy HTTP. Angielski katalog nadal listuje ten produkt jako smartproxy-com. Publiczna nazwa w dokumentacji to Decodo. Ścieżka się nie zmieniła.
04Zrozumieć domyślne środowisko i mounts
HTTPX domyślnie czyta środowisko. Zmienne środowiska (dostęp 14 października 2026) wymieniają HTTP_PROXY, HTTPS_PROXY, ALL_PROXY i NO_PROXY, plus SSL_CERT_FILE i SSL_CERT_DIR. trust_env=False wyłącza cały ten zestaw. Nie znaczy „pominąć sprawdzenia certyfikatów”.
Proces potomny laboratorium startował z tymi zmiennymi usuniętymi, plus pozostałościami CGI, REQUESTS_CA_BUNDLE, CURL_CA_BUNDLE i SSLKEYLOGFILE. Używał pustego prywatnego pliku NETRC. HOME stacji roboczej zostawiono w spokoju. Każdy eksperyment środowiskowy startował z tej linii bazowej i wstrzykiwał tylko nazwane wartości atrap.
Ominięcie loopback wprowadzi w błąd. Klienci HTTP często pomijają 127.0.0.1. Przypadki proxy ze środowiska używały nazwy hosta httpx-lab.origin i NO_PROXY="", z ograniczoną łatą getaddrinfo, która mapuje tę nazwę na loopback. Ta łata to wstrzyknięte zachowanie resolwera. To nie pomiar publicznego DNS.
- Wyeksportować
HTTP_PROXYiHTTPS_PROXYna zakodowany URL proxy. UstawićNO_PROXYna pusty ciąg, gdy cel musi iść przez proxy. - Zbudować
Client(trust_env=True)bez argumentuproxy=. Żądanie laboratoryjne zwróciło 200 i tylko proxyalphazapisało GET. Proxybravopozostało bezczynne. - Powtórzyć z
NO_PROXY=httpx-lab.origin. Origin nadal zwrócił 200. Alpha nie zobaczyło tego GET. To ominięcie i to osobny przypadek, nie efekt uboczny, który się zakłada. - Powtórzyć z tymi samymi zmiennymi i
trust_env=False. Żądanie poszło bezpośrednio. Alpha nic nie zobaczyło.
Jawne proxy= wygrało ze sprzecznym środowiskiem. Przy alpha w HTTP_PROXY i proxy= wskazującym na bravo GET dostało bravo, a alpha nie. Sam status 200 nie powiedziałby, który przeskok został użyty. Dwie instrumentowane tożsamości tak.
trust_env=False zatrzymało też zamianę SSL_CERT_FILE w magazyn CA klienta. Przy laboratoryjnym CA w SSL_CERT_FILE i trust_env=True HTTPS do laboratoryjnego origin zwrócił 200. Przy trust_env=False i domyślnym verify=True ten sam URL rzucił ConnectError / SSLCertVerificationError. Podanie verify=ssl.create_default_context(cafile=ca.pem) na tym kliencie z trust_env=False przywróciło 200. Weryfikacja pozostała włączona. Zniknęło tylko wyszukiwanie w środowisku.
transport= i mounts= to różne argumenty konstruktora. HTTPX 0.28.1 ustawia allow_env_proxies = trust_env and transport is None. Własny obiekt transport= pomija mounts proxy ze środowiska. Słownik mounts= nie. Klient najpierw buduje mounts ze środowiska, potem aktualizuje tę mapę własnymi mounts. Bardziej szczegółowe wzorce URL wygrywają. http:// z HTTP_PROXY pokonuje all://, więc Client(mounts={"all://": some_transport}, trust_env=True) nadal może wysłać cele HTTP przez odziedziczone proxy. Ustawić trust_env=False, gdy routing ze środowiska ma być wyłączony. proxy= i verify= kłaść na każdym zamontowanym HTTPTransport. verify= na poziomie klienta nadal nie kopiuje się na te transporty. Ta ostatnia pomyłka to sposób, w jaki wraca awaria niezaufanego CA.
05Przetestować cykl życia sync i async
Sync i async to dwa klienty. Dzielą kształt proxy=. Nie dzielą puli połączeń.
with httpx.Client(proxy=..., verify=ctx) as client: to forma sync. Zamknięcie następuje przy wyjściu z kontekstu. async with httpx.AsyncClient(proxy=..., verify=ctx) as client: to forma async. Wywołuje się await client.get(...). Mieszanie get bez await wewnątrz klienta async to błąd, nie limit czasu.
Przypadek async w tym laboratorium używał AsyncClient z tym samym URL proxy HTTP i laboratoryjnym kontekstem SSL. await client.get(https_url) zwróciło 200 ze znacznikiem origin HTTPS. Proxy zapisało CONNECT. To jeden udany tunel async. To nie benchmark współbieżności i nic nie mówi o ponownym użyciu puli pod obciążeniem.
Zamontowane transporty potrzebują tej samej ścieżki zamknięcia. HTTPTransport utworzony ręcznie zamyka klient, jeśli klient nim włada przez mounts. Jeśli zmienna transportu żyje między klientami, w finally wywołać transport.close(). Laboratorium robiło to w przypadkach ponowień i mounts.
Ponowienia należą do transportu. Transporty (dostęp 14 października 2026) mówią, że HTTPTransport(retries=...) ponawia ConnectError i ConnectTimeout. Nie ponawia 429 ani 503. Laboratorium ustawiło retries=2 i pobrało /status/503. Origin policzył jedno trafienie. HTTPX zwrócił 503. To nie urllib3 Retry. Nie należy wklejać folkloru allowed_methods do HTTPX.
06Diagnozować awarie połączenia, odczytu ciała i TLS
Nazwać złapany wyjątek. HTTPX ma prawdziwą hierarchię. Spłaszczenie wszystkiego do „błędu proxy” ukrywa przeskok, który zawiódł.
Zamknięty listener na loopback dał ConnectError opakowujący ConnectionRefusedError: [Errno 61] Connection refused. To odmowa. To nie limit czasu połączenia. Na tym jądrze Darwin gniazdo, które było zbindowane i trzymane, ale nigdy nie weszło w listen, nie odmawiało. HTTPX rzucił ConnectTimeout opakowujący TimeoutError po skonfigurowanym terminie połączenia. To oczekiwanie jest oznaczone jako zachowanie wstrzykniętego stanowiska dla bind-without-listen. To nie pomiar publicznego internetu.
Limity czasu odczytu dotyczą kawałków po starcie odpowiedzi. Origin /slow-body wysłało kompletne nagłówki natychmiast, zapisało i wypchnęło jeden bajt ciała, a potem czekało dłużej niż Timeout(read=0.45). Przy strumieniowaniu ciała HTTPX zwrócił status 200, odpaliło się zdarzenie pierwszego bajtu, przyszedł jeden bajt, a potem ReadTimeout opakowujący TimeoutError. Nagłówki już wylądowały. ConnectError byłby złą klasą. ConnectTimeout byłby złą klasą. Jeśli wywołuje się tylko response.text bez strumieniowania, i tak nastąpi timeout, ale znika dowód, że nagłówki doszły.
Awarie TLS po CONNECT pozostały ConnectError z SSLCertVerificationError. Proxy już przyjęło tunel. Wyłączenie verify=False by to ukryło. Nie należy.
Użyć proxy mobilnych albo proxy rezydenckich, gdy zadaniem jest wyjście przypisane przez ISP. Obsługa protokołu i pochodzenie IP to różne wymiary. To laboratorium nigdy nie twierdziło kraju, wskaźnika sukcesu ani konta.
| Awaria | Co rzuciło laboratorium 0.28.1 | Czym to nie jest |
|---|---|---|
| Proxy HTTP, brakujący albo zły Basic | Status odpowiedzi 407 | Wyjątek CONNECT |
| HTTPS CONNECT, brakujący albo zły Basic | ProxyError („407 Proxy Authentication Required”) | Strona origin 407 |
| Laboratoryjny HTTPS bez laboratoryjnego CA | ConnectError / SSLCertVerificationError po CONNECT | Dowód, że CONNECT nigdy nie nastąpił |
| Zamknięty port loopback | ConnectError / ConnectionRefusedError | ConnectTimeout |
| Bind bez listen na Darwin | ConnectTimeout (oczekiwanie specyficzne dla stanowiska) | Odmowa albo RTT WAN |
| Opóźnione ciało po pierwszym bajcie | ReadTimeout przy iteracji iter_bytes() | Awaria połączenia |
Origin /status/503 z retries=2 | Status 503, jedno trafienie origin | Ponowienie aplikacyjne |

Rysunek to tabela asercji z tego przebiegu. To nie obraz okładki i nie zrzut interfejsu sprawdzania.
Następny blok to schematyczny szkic API. Porty, ścieżka CA i hasło to placeholdery, które zastępuje się wartościami pod własną kontrolą. To nie publiczny pakiet stanowiska i nie uruchomi się z pustego katalogu.
import httpx
import ssl
# PLACEHOLDERS. Do not treat these literals as lab values.
ctx = ssl.create_default_context(cafile="PATH/TO/LAB_CA.pem")
proxy = httpx.Proxy(
"http://127.0.0.1:PROXY_PORT",
auth=("PROXY_USER", "PROXY_PASSWORD"),
)
timeout = httpx.Timeout(5.0, connect=2.0, read=0.45)
with httpx.Client(proxy=proxy, verify=ctx, trust_env=False, timeout=timeout) as client:
http_response = client.get("http://TARGET_HOST:HTTP_PORT/")
https_response = client.get("https://TARGET_HOST:HTTPS_PORT/")
Klasy wyjątków 0.28.1 oraz wyniki CONNECT kontra 407 w tym artykule pochodzą z prywatnego stanowiska redakcyjnego. Tego stanowiska tu nie publikujemy. Zainstalować klienta, który da się zaimportować przez python -m pip install "httpx[socks]==0.28.1", zależnego od httpcore 1.* i, dla SOCKS, socksio. Host, port i dane logowania proxy HTTP wstawić w placeholdery, używając httpx.Proxy(..., auth=(user, password)), gdy hasło ma znaki zastrzeżone. URL HTTP skierować na origin pod kontrolą dla przekazywania, a URL HTTPS na origin pod kontrolą dla CONNECT, a potem TLS. Dla HTTPS podać verify= jako ssl.create_default_context(cafile=...) z plikiem CA, któremu już się ufa dla tego origin. Zostawić trust_env=False, dopóki dowodzi się jawnej ścieżki proxy=. Nie ustawiać verify=False.
07Wybrać udokumentowany punkt końcowy
Gdy ścieżka klienta jest uczciwa, wybrać host wejścia, który dokumentuje przekazywanie HTTP i CONNECT. Angielskie strony katalogu Oxylabs i Decodo (nadal listowane jako smartproxy-com) 14 października 2026 zwracały żywe samokanoniczne URL. Oficjalna dokumentacja opisuje bramy HTTP z nazwą użytkownika i hasłem albo dozwolonym IP. To dopasowanie punktu końcowego na papierze. Ten artykuł nie logował się do żadnego z tych produktów i ich nie rankinguje.

Oxylabs sprzedaje proxy rezydenckie, mobilne, ISP i datacenter w jednej subskrypcji miesięcznej od $30. Płatności: karty, przelew, AliPay, PayPal.

Decodo (dawniej Smartproxy) sprzedaje proxy rezydenckie i datacenter. Rezydenckie: $4/GB bez planu miesięcznego albo pakiety miesięczne od $3.75/GB za 3 GB. Płatności: karty, PayPal, Alipay, Google/Apple Pay, krypto (z ograniczeniami).
Jeśli potrzebne było tylko potwierdzenie w przeglądarce, zostać przy Jaki jest mój adres IP. Jeśli potrzebny był HTTPX, wierzyć logowi proxy i klasie wyjątku z tej biblioteki. Te dwa rozjeżdżają się częściej, niż przyznają wpisy na blogach.
Jak ustawić proxy w HTTPX?
Po co http:// dla proxy obsługującego HTTPS?
Czym dane logowania proxy różnią się od auth=?
Czy trust_env=False wyłącza weryfikację certyfikatów?
Dlaczego klient rzuca ReadTimeout po nadejściu nagłówków?
Czy HTTPTransport ponawia 429 albo 503?
Powiązane artykuły
Czym są proxy rezydenckie i jak działają
Proxy rezydenckie wychodzą przez adresy konsumenckich ISP. Tu jest, jak działają pule, sesje sticky, co widzą witryny i o co pytać dostawcę przed zakupem.
4 minNajlepsze proxy do web scrapingu w 2026: lista kontrolna kupującego
Zakup proxy do scrapingu w 2026 zaczyna się od celu, nie od sprzedawcy. Ta lista kontrolna obejmuje pochodzenie, sesję, geo, rozliczenie i żywy test, zanim przeskalujecie.
5 minSticky a rotacyjne proxy: sterowanie sesją wyjaśnione
Sticky a rotacyjne proxy: jak działa rotacja na żądanie i na timerze, kiedy sesja sticky bije nowy IP, jak ciasteczka reagują na zmianę adresu i jak samodzielnie przetestować identyfikator sesji.
9 min

