Guida ai Proxy di Python Requests: Sintassi, Autenticazione, Rotazione, Ritentativi
Il dizionario dei proxy è composto da tre righe di codice, eppure gli errori di proxy in Requests riempiono un decennio di discussioni su Stack Overflow. Ecco la configurazione completa — sintassi, autenticazione, variabili d'ambiente, rotazione, ritentativi e SOCKS5 — con i bordi taglienti etichettati.
Python Requests è ancora il client HTTP predefinito per scraping e automazione, e indirizzarlo a un proxy è un lavoro di tre righe: passa un dizionario di proxy e ogni richiesta esce dall'IP del proxy invece che dal tuo. Eppure 'python requests proxy non funzionante' è rimasto una delle ricerche principali per oltre un decennio — la domanda originale su Stack Overflow riguardo al dizionario dei proxy risale al 2011, la risposta più votata ha oltre 480 voti, ed è stata ancora modificata a gennaio 2026. La sintassi ha bordi taglienti: uno schema mancante solleva un'eccezione, lo schema sbagliato all'interno della chiave https provoca errori SSL, e le variabili d'ambiente sovrascrivono silenziosamente il codice. Questa guida ai proxy di Python Requests copre tutto: sintassi, autenticazione, variabili d'ambiente, rotazione, ritentativi, SOCKS5 e gli errori che incontrerai realmente.
Il dizionario dei proxy: sintassi del proxy di Python Requests
L'argomento proxies mappa un protocollo a un URL di proxy. Due chiavi coprono lo scraping normale — una per i target HTTP semplici, una per i target HTTPS — e di solito entrambe puntano allo stesso 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>'}
Tre regole prevengono il 90% dei fallimenti di configurazione:
- Lo schema è obbligatorio. Dalla versione 2.0.0 di Requests, un URL di proxy senza
http://sollevaMissingSchema. Le stringheip:portnude funzionavano nella versione 1.x e si sono rotte ovunque quando è arrivata la 2.0. - Usa
http://all'interno della chiavehttps. La chiave nomina il protocollo di destinazione; il valore nomina come raggiungi il proxy. I proxy accettano HTTP semplice e tunnel TLS tramite una richiesta CONNECT. Scriverehttps://lì è la causa classica diSSLError: UNEXPECTED_EOF_WHILE_READING. - Le chiavi possono indirizzare host specifici. Una chiave come
https://api.example.cominstrada solo quell'host attraverso un dato proxy — utile per inviare un dominio difficile attraverso IP residenziali mentre tutto il resto va diretto.
Autenticazione del proxy: username e password
I proxy autenticati usano l'autenticazione HTTP Basic incorporata nell'URL: http://USER:PASS@host:port. Se la password contiene @, : o /, codificala prima con urllib.parse.quote(password, safe="") — i caratteri speciali non codificati dividono l'URL nel posto sbagliato e producono errori di autenticazione che sembrano proxy morti. Una risposta 407 Proxy Authentication Required significa che il proxy stesso ti ha rifiutato: credenziali errate, o un piano di whitelist IP chiamato da un indirizzo non registrato. Entrambi i casi sono analizzati nella nostra guida alla risoluzione dei problemi 407. Per qualsiasi cosa oltre uno script una tantum, allega i proxy a una Session — ottieni il pooling delle connessioni, la persistenza dei cookie e un unico posto per configurare tutto:
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())
Variabili d'ambiente e trust_env
Requests legge anche le impostazioni del proxy dall'ambiente — le stesse variabili che curl e la maggior parte degli strumenti Unix rispettano: HTTP_PROXY, HTTPS_PROXY, ALL_PROXY e NO_PROXY (un elenco separato da virgole di host da escludere, ad esempio localhost,127.0.0.1,.internal). Questo è il modo più pulito per proxy un libreria di terze parti che utilizza Requests senza toccare il suo codice. La precedenza segue il principio esplicito-batte-implicito: un argomento proxies= nella chiamata vince, poi session.proxies, poi l'ambiente. Due strumenti correlati vale la pena conoscere: session.trust_env = False disattiva tutte le ricerche nell'ambiente — la soluzione quando una variabile di proxy aziendale dirotta il tuo scraper — e urllib.request.getproxies() restituisce le impostazioni di proxy a livello di sistema operativo (inclusi i sistemi macOS e Windows) esattamente nella forma di dizionario che Requests si aspetta.

Rotazione: un gateway batte una lista di proxy
La ricetta tradizionale di rotazione — caricare una lista di IP, random.choice() per richiesta, eliminare quelli morti — è un meccanismo che non devi più costruire. Un gateway rotante lo fa lato server: configuri un endpoint e il fornitore assegna un nuovo IP di uscita dal pool ad ogni richiesta. Attraverso proxy residenziali rotanti quel pool è composto da oltre 90 milioni di IP domestici in più di 200 paesi, quindi mille richieste sembrano mille visitatori diversi senza una sola riga di logica di rotazione:
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
Quando un flusso copre diverse richieste — login, aggiungi al carrello, checkout — la rotazione per richiesta interrompe la sessione. Le sessioni sticky risolvono questo: un parametro di sessione nel nome utente del proxy fissa un IP di uscita per una finestra impostata, poi ruota. Stesso endpoint, un cambio di stringa. Se stai scalando oltre semplici loop, Python asincrono con httpx o aiohttp moltiplica la capacità, e il sistema di middleware di Scrapy ti offre rotazione, ritentativi e gestione dei ban come configurazione del framework.
Ritentativi e timeout che sopravvivono a uscite difettose
Anche i pool premium servono occasionalmente uscite lente o morenti, quindi il codice di produzione ha bisogno di due protezioni: un timeout su ogni richiesta (Requests di default attende all'infinito) e ritentativi automatici con backoff. Il timeout prende una tupla (connect, read) — fallisce rapidamente su proxy irraggiungibili, consente letture di pagina più lente. I ritentativi si montano a livello di trasporto tramite 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))
Con un gateway rotante questa combinazione è silenziosamente potente: ogni ritentativo viaggia automaticamente attraverso un diverso IP di uscita, quindi un indirizzo instabile non può mai far fallire una richiesta quattro volte di seguito.
Proxy SOCKS5 con Requests
Il supporto SOCKS è un extra: installalo con pip install requests[socks]. Poi la sintassi del dizionario è identica — cambia solo lo schema. Preferisci socks5h:// a socks5://: la h spinge la risoluzione DNS al proxy, che impedisce perdite DNS dalla tua rete reale e risolve nomi host geo-restritti dalla posizione dell'uscita. Ogni piano QuantumProxies espone sia proxy HTTP che proxy SOCKS5 sullo stesso gateway, quindi cambiare protocollo è uno scambio di schema, non un nuovo acquisto:
proxies = {
"http": "socks5h://USER:PASS@gate.quantumproxies.io:PORT",
"https": "socks5h://USER:PASS@gate.quantumproxies.io:PORT",
}

Errori comuni di proxy di Python Requests, decodificati
- MissingSchema — l'URL del proxy manca di
http://. Obbligatorio dalla versione 2.0.0 di Requests. - ProxyError: Cannot connect to proxy — host o porta errati, o un proxy morto. Verifica l'endpoint con curl prima di incolpare il tuo codice.
- SSLError / UNEXPECTED_EOF_WHILE_READING — di solito
https://all'interno della chiavehttps. Imposta lo schema del valore suhttp://. - 407 Proxy Authentication Required — credenziali errate, caratteri speciali non codificati nella password, o un IP sorgente non in whitelist.
- ConnectTimeout / ReadTimeout — uscita lenta o target lento. Imposta
timeout=(5, 30)e lascia che i ritentativi ruotino su un nuovo IP. - Il proxy funziona in curl, fallisce in Python — una variabile d'ambiente sta sovrascrivendo il tuo dizionario. Stampa
session.proxiese provatrust_env = False.
Per un'analisi più approfondita delle tracce dello stack e delle loro cause principali, vedi debugging ProxyError, SSLError e ConnectTimeout in Requests.
Domande frequenti
Come uso un proxy con Python Requests?
Passa un dizionario proxies con chiavi http e https a qualsiasi metodo di richiesta: requests.get(url, proxies={...}). Ogni valore è un URL di proxy completo incluso lo schema, e le credenziali sono incorporate come http://user:pass@host:port. Allega lo stesso dizionario a una Session per applicarlo automaticamente a ogni richiesta.
Perché il mio proxy di Python Requests non funziona?
Controlla i quattro sospetti usuali in ordine: uno schema http:// mancante nell'URL del proxy, https:// usato all'interno della chiave https, caratteri speciali nella password che non sono stati codificati nell'URL, e variabili d'ambiente che sovrascrivono il tuo codice. Testa le stesse credenziali con curl — se curl ha successo, il problema è nel tuo dizionario.
Python Requests supporta i proxy SOCKS5?
Sì, dopo aver installato la dipendenza extra con pip install requests[socks]. Usa lo schema socks5h:// nel tuo dizionario dei proxy in modo che la risoluzione DNS avvenga sul lato proxy — lo schema semplice socks5:// risolve i nomi host localmente, il che perde le query DNS e può interrompere lo scraping geo-targeted.
Come imposto un proxy con le variabili d'ambiente?
Esporta HTTP_PROXY e HTTPS_PROXY con l'URL completo del proxy, e facoltativamente NO_PROXY per gli host da escludere. Requests li rileva automaticamente, il che proxy anche le librerie di terze parti costruite su Requests. Per far sì che il tuo codice ignori completamente l'ambiente, imposta session.trust_env = False.
Questo è l'intero toolkit: un dizionario a due chiavi, credenziali nell'URL, ritentativi montati una volta, e rotazione gestita dal gateway invece che dal tuo codice. L'unica cosa che nessuna sintassi può risolvere è la qualità dell'IP — un proxy datacenter perfettamente configurato viene ancora bloccato dove un'uscita residenziale passa senza problemi. Abbina codice pulito a IP puliti e Requests gestirà carichi sorprendentemente grandi.
Ottieni proxy residenziali che funzionano al primo tentativo