Przewodnik po proxy w Python Requests: składnia, uwierzytelnianie, rotacja, ponowne próby

Słownik proxies to trzy linie kodu, a jednak błędy proxy w Requests wypełniają dekadę na Stack Overflow. Oto pełna konfiguracja — składnia, uwierzytelnianie, zmienne środowiskowe, rotacja, ponowne próby i SOCKS5 — z oznaczonymi ostrymi krawędziami.

Python Requests nadal jest domyślnym klientem HTTP do scrapingu i automatyzacji, a wskazanie go na proxy to zadanie na trzy linie: przekaż słownik proxies, a każde żądanie wychodzi z IP proxy zamiast z twojego. Jednak 'python requests proxy not working' pozostaje jednym z najczęściej wyszukiwanych tematów od ponad dekady — oryginalne pytanie na Stack Overflow dotyczące słownika proxies pochodzi z 2011 roku, jego najlepsza odpowiedź ma ponad 480 głosów, a wciąż była edytowana w styczniu 2026 roku. Składnia ma ostre krawędzie: brakujący schemat wywołuje wyjątek, zły schemat wewnątrz klucza https powoduje błędy SSL, a zmienne środowiskowe cicho nadpisują kod. Ten przewodnik po proxy w Python Requests obejmuje wszystko: składnię, uwierzytelnianie, zmienne środowiskowe, rotację, ponowne próby, SOCKS5 i błędy, które faktycznie napotkasz.

Słownik proxies: składnia proxy w Python Requests

Argument proxies mapuje protokół na URL proxy. Dwa klucze obejmują normalny scraping — jeden dla zwykłych celów HTTP, drugi dla celów HTTPS — i oba zazwyczaj wskazują na to samo proxy:

import requests

proxies = {
    "http": "http://USER:PASS@gate.quantumproxies.io:PORT",
    "https": "http://USER:PASS@gate.quantumproxies.io:PORT",
}

r = requests.get("https://httpbin.org/ip", proxies=proxies, timeout=(5, 30))
print(r.json())  # {'origin': '<proxy exit IP>'}

Trzy zasady zapobiegają 90% błędów konfiguracji:

Uwierzytelnianie proxy: nazwa użytkownika i hasło

Uwierzytelnione proxy używają uwierzytelniania HTTP Basic osadzonego w URL: http://USER:PASS@host:port. Jeśli hasło zawiera @, : lub /, najpierw zakoduj je w URL za pomocą urllib.parse.quote(password, safe="") — niezakodowane znaki specjalne dzielą URL w niewłaściwym miejscu i powodują błędy uwierzytelniania, które wyglądają jak martwe proxy. Odpowiedź 407 Proxy Authentication Required oznacza, że samo proxy cię odrzuciło: błędne dane uwierzytelniające lub plan z białą listą IP wywołany z niezarejestrowanego adresu. Oba przypadki są omówione w naszym przewodniku po rozwiązywaniu problemów z 407. Do czegoś więcej niż jednorazowy skrypt, dołącz proxy do Session — uzyskasz pooling połączeń, trwałość ciasteczek i jedno miejsce do konfiguracji wszystkiego:

import requests

session = requests.Session()
session.proxies = {
    "http": "http://USER:PASS@gate.quantumproxies.io:PORT",
    "https": "http://USER:PASS@gate.quantumproxies.io:PORT",
}
session.headers.update({"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"})

r = session.get("https://httpbin.org/ip", timeout=(5, 30))
print(r.status_code, r.json())

Zmienne środowiskowe i trust_env

Requests również odczytuje ustawienia proxy ze środowiska — te same zmienne, które respektuje curl i większość narzędzi Unix: HTTP_PROXY, HTTPS_PROXY, ALL_PROXY i NO_PROXY (lista hostów do wykluczenia, np. localhost,127.0.0.1,.internal). To najczystszy sposób na proxy dla biblioteki zewnętrznej, która używa Requests pod maską, bez dotykania jej kodu. Priorytet jest taki: jawne wygrywa z ukrytym: argument proxies= w wywołaniu wygrywa, potem session.proxies, a potem środowisko. Warto znać dwa powiązane narzędzia: session.trust_env = False wyłącza całe wyszukiwanie środowiskowe — rozwiązanie, gdy zmienna proxy korporacyjnego przejmuje twojego scrapera — a urllib.request.getproxies() zwraca ustawienia proxy na poziomie systemu operacyjnego (w tym konfigurację systemu macOS i Windows) dokładnie w formie słownika, jakiego oczekuje Requests.

Diagram przepływu proxy w Python Requests: słownik proxies kieruje każde żądanie przez obracający się tunel CONNECT do docelowej strony
Słownik wybiera trasę, brama dostarcza wyjściowy IP. Przy rotacji per żądanie te same dwie linie konfiguracji dają nowy IP przy każdym wywołaniu.

Rotacja: jedna brama bije listę proxy

Tradycyjny przepis na rotację — załaduj listę IP, random.choice() na żądanie, usuń martwe — to mechanizm, którego nie musisz już budować. Obracająca się brama robi to po stronie serwera: konfigurujesz jeden punkt końcowy, a dostawca przypisuje świeży wyjściowy IP z puli przy każdym żądaniu. Przez obracające się proxy rezydencyjne ta pula to ponad 90 milionów IP gospodarstw domowych w ponad 200 krajach, więc tysiąc żądań wygląda jak tysiąc różnych odwiedzających bez ani jednej linii logiki rotacji:

import requests

proxies = {
    "http": "http://USER:PASS@gate.quantumproxies.io:PORT",
    "https": "http://USER:PASS@gate.quantumproxies.io:PORT",
}

for _ in range(3):
    r = requests.get("https://httpbin.org/ip", proxies=proxies, timeout=(5, 30))
    print(r.json()["origin"])  # a different exit IP on each iteration

Gdy przepływ obejmuje kilka żądań — logowanie, dodanie do koszyka, realizacja zakupu — rotacja per żądanie przerywa sesję. Sesje lepkie to rozwiązanie: parametr sesji w nazwie użytkownika proxy przypina jeden wyjściowy IP na określony czas, a potem rotuje. Ten sam punkt końcowy, jedna zmiana ciągu. Jeśli skalujesz się poza proste pętle, asynchroniczny Python z httpx lub aiohttp zwiększa przepustowość, a system middleware Scrapy daje ci rotację, ponowne próby i obsługę banów jako konfigurację frameworka.

Ponowne próby i limity czasu, które przetrwają złe wyjścia

Nawet premium pule serwują czasem wolne lub umierające wyjścia, więc kod produkcyjny potrzebuje dwóch zabezpieczeń: limitu czasu na każde żądanie (Requests domyślnie czeka w nieskończoność) i automatycznych ponownych prób z backoffem. Limit czasu przyjmuje krotkę (connect, read) — szybkie niepowodzenie na nieosiągalnych proxy, pozwala na wolniejsze odczyty stron. Ponowne próby montują się na warstwie transportowej przez urllib3:

import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

retry = Retry(
    total=4,
    backoff_factor=1,  # exponential backoff between attempts
    status_forcelist=[429, 500, 502, 503, 504],
    allowed_methods=["GET", "HEAD"],
)

session = requests.Session()
session.mount("http://", HTTPAdapter(max_retries=retry))
session.mount("https://", HTTPAdapter(max_retries=retry))
session.proxies = {
    "http": "http://USER:PASS@gate.quantumproxies.io:PORT",
    "https": "http://USER:PASS@gate.quantumproxies.io:PORT",
}

r = session.get("https://httpbin.org/ip", timeout=(5, 30))

Z obracającą się bramą ta kombinacja jest cicho potężna: każda ponowna próba przechodzi automatycznie przez inny wyjściowy IP, więc jeden niestabilny adres nigdy nie może spowodować niepowodzenia żądania cztery razy z rzędu.

SOCKS5 proxy z Requests

Wsparcie dla SOCKS to dodatek: zainstaluj je za pomocą pip install requests[socks]. Następnie składnia słownika jest identyczna — zmienia się tylko schemat. Preferuj socks5h:// nad socks5://: h przenosi rozwiązywanie DNS na proxy, co zapobiega wyciekom DNS z twojej rzeczywistej sieci i rozwiązuje geo-fencowane nazwy hostów z lokalizacji wyjścia. Każdy plan QuantumProxies udostępnia zarówno HTTP, jak i SOCKS5 proxy na tej samej bramie, więc zmiana protokołów to zamiana schematu, a nie nowy zakup:

proxies = {
    "http": "socks5h://USER:PASS@gate.quantumproxies.io:PORT",
    "https": "socks5h://USER:PASS@gate.quantumproxies.io:PORT",
}
Lista kontrolna porównująca działające konfiguracje proxy w Python Requests z pięcioma powszechnymi błędami, które je łamią
Pięć błędów powoduje większość niepowodzeń: brakujący schemat, https:// w kluczu https, niezakodowane hasła, brakujące dodatki SOCKS i brak limitu czasu.

Najczęstsze błędy proxy w Python Requests, zdekodowane

Aby głębiej przejść przez ślady stosu i ich przyczyny źródłowe, zobacz debugowanie ProxyError, SSLError i ConnectTimeout w Requests.

Często zadawane pytania

Jak używać proxy z Python Requests?

Przekaż słownik proxies z kluczami http i https do dowolnej metody żądania: requests.get(url, proxies={...}). Każda wartość to pełny URL proxy łącznie ze schematem, a dane uwierzytelniające są osadzone jako http://user:pass@host:port. Dołącz ten sam słownik do Session, aby automatycznie zastosować go do każdego żądania.

Dlaczego moje proxy w Python Requests nie działa?

Sprawdź cztery zwykłe podejrzane w kolejności: brakujący schemat http:// w URL proxy, https:// użyte wewnątrz klucza https, znaki specjalne w haśle, które nie zostały zakodowane w URL, i zmienne środowiskowe nadpisujące twój kod. Przetestuj te same dane uwierzytelniające za pomocą curl — jeśli curl się powiedzie, problem leży w twoim słowniku.

Czy Python Requests obsługuje proxy SOCKS5?

Tak, po zainstalowaniu dodatkowej zależności za pomocą pip install requests[socks]. Użyj schematu socks5h:// w swoim słowniku proxies, aby rozwiązywanie DNS odbywało się po stronie proxy — zwykły schemat socks5:// rozwiązuje nazwy hostów lokalnie, co wycieka zapytania DNS i może zepsuć scraping geo-celowany.

Jak ustawić proxy za pomocą zmiennych środowiskowych?

Eksportuj HTTP_PROXY i HTTPS_PROXY z pełnym URL proxy, opcjonalnie NO_PROXY dla hostów do wykluczenia. Requests automatycznie je przechwytuje, co również proxyzuje biblioteki zewnętrzne zbudowane na Requests. Aby twój kod całkowicie ignorował środowisko, ustaw session.trust_env = False.

To cały zestaw narzędzi: słownik z dwoma kluczami, dane uwierzytelniające w URL, ponowne próby zamontowane raz i rotacja obsługiwana przez bramę zamiast twojego kodu. Jedyna rzecz, której żadna składnia nie naprawi, to jakość IP — idealnie skonfigurowane proxy centrum danych nadal jest blokowane tam, gdzie wyjście rezydencyjne przechodzi bez problemu. Połącz czysty kod z czystymi IP, a Requests obsłuży zaskakująco duże obciążenia.

Zdobądź proxy rezydencyjne, które działają za pierwszym razem