Toda biblioteca HTTP em Python aceita um proxy como uma URL no formato scheme://user:pass@host:port; o que muda é o nome do parâmetro, se é definido por cliente ou por requisição, e como SOCKS5 e DNS são tratados. Os exemplos abaixo são o código exato que funciona com as versões atuais de requests, httpx e aiohttp — cada um foi executado através de um proxy com autenticação antes da publicação deste artigo — seguidos pelas três coisas que respondem pela maioria das perguntas do tipo “meu proxy não funciona em Python”: nomes de parâmetros errados copiados de tutoriais antigos, extras SOCKS ausentes e uma impressão digital TLS que denuncia o script independentemente do IP.
A URL do proxy
http://user:pass@proxy.example.com:8080 # Proxy HTTP, usado tanto para alvos http:// quanto https://
socks5://user:pass@proxy.example.com:1080 # SOCKS5, DNS resolvido localmente
socks5h://user:pass@proxy.example.com:1080 # SOCKS5, DNS resolvido pelo proxy (use este)
Dois pontos que confundem as pessoas. Primeiro, um proxy HTTP também lida com alvos HTTPS — o cliente envia CONNECT e tunela TLS através dele — então você quase nunca precisa de um esquema de proxy https://; isso significaria TLS para o próprio proxy, o que poucos provedores oferecem. Segundo, se seu nome de usuário contém parâmetros de rotação (user-country-de-session-abc123) ou sua senha contém @, : ou /, codifique-os em percentual (urllib.parse.quote(pw, safe='')) ou a URL será analisada incorretamente.
requests
import requests
PROXY = "http://user:pass@proxy.example.com:8080"
proxies = {"http": PROXY, "https": PROXY}
# Por requisição
r = requests.get("https://api.ipify.org?format=json", proxies=proxies, timeout=20)
print(r.json())
# Por sessão (reutiliza conexões; a forma normal)
s = requests.Session()
s.proxies.update(proxies)
r = s.get("https://api.ipify.org?format=json", timeout=20)
O dicionário é indexado pelo esquema do alvo: requisições para URLs http:// usam a entrada "http", requisições para URLs https:// usam "https". Defina ambos para o mesmo proxy, a menos que tenha um motivo para não fazer isso. Sempre passe um timeout; um proxy travado pode travar seu script para sempre.
SOCKS5 precisa do extra: pip install "requests[socks]". Então proxies = {"http": "socks5h://…", "https": "socks5h://…"}. Sem o extra, você recebe InvalidSchema: Missing dependencies for SOCKS support.
Variáveis de ambiente: requests honra HTTP_PROXY / HTTPS_PROXY / NO_PROXY por padrão (trust_env=True). Se um proxy está misteriosamente em uso quando você não definiu um, ou não está em uso quando você definiu, verifique o ambiente.
httpx
import httpx
PROXY = "http://user:pass@proxy.example.com:8080"
# Síncrono
with httpx.Client(proxy=PROXY, timeout=20) as client:
r = client.get("https://api.ipify.org?format=json")
print(r.json())
# Assíncrono
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())
O parâmetro é proxy= (singular). Tutoriais antigos mostram proxies={"http://": …, "https://": …}; essa palavra-chave foi depreciada no httpx 0.26 e removida no 0.28, e passá-la agora levanta TypeError: Client.__init__() got an unexpected keyword argument 'proxies'. Se você precisa de proxies diferentes para alvos diferentes, use 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]", então proxy="socks5://…". httpx resolve nomes de host através do proxy SOCKS por padrão. HTTP/2: pip install "httpx[http2]" e httpx.Client(http2=True, …) — relevante porque um navegador via proxy já está em HTTP/2 (veja HTTP/2 e HTTP/3 através de proxies).
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())
O proxy é passado por requisição (ou definido uma vez via um conector personalizado). As credenciais vão na URL; a forma separada proxy_auth=aiohttp.BasicAuth(...) ainda funciona no 3.x, mas está depreciada a partir do 3.14 e programada para remoção no 4.0, então prefira a forma com URL. aiohttp não lê variáveis de ambiente HTTP_PROXY a menos que você crie a sessão com trust_env=True. O aiohttp nativo fala apenas proxies HTTP; para SOCKS use o pacote aiohttp-socks e seu ProxyConnector.
Rotacionando proxies: o padrão de session-ID
Com um gateway de backconnect (veja como funcionam os gateways de rotação) você raramente rotaciona em Python — você rotaciona mudando o nome de usuário. Um novo session ID significa um novo IP de saída; um reutilizado o mantém:
import secrets, requests
def proxy_for(session_id: str, country: str = "de") -> dict:
user = f"customer-country-{country}-session-{session_id}" # formato específico do provedor
url = f"http://{user}:PASSWORD@gate.provider.com:7777"
return {"http": url, "https": url}
# Sticky: mesmo IP para um fluxo de várias etapas
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=...)
# Rotacionando: novo IP por item
for url in urls:
requests.get(url, proxies=proxy_for(secrets.token_hex(4)), timeout=20)
Rotacione também em caso de falha: capture 403/429 e um marcador de CAPTCHA, e tente novamente com um session ID novo e um novo cookie jar — o mesmo IP com os mesmos cookies é o mesmo visitante.
O erro que nenhum proxy corrige: impressão digital TLS
Todas as três bibliotecas fazem conexões TLS através do módulo ssl do Python (OpenSSL). Sistemas anti-bot identificam esse handshake e sabem que não é um navegador, independentemente de como você define o User-Agent. Atrás de um IP residencial perfeito, o script ainda é identificado como script — o mecanismo está em impressão digital TLS explicada. Para alvos protegidos, mude para um cliente que imita navegador; curl_cffi mantém uma API semelhante à do requests:
# pip install curl_cffi
from curl_cffi import requests as cffi_requests
r = cffi_requests.get("https://protected.example/",
impersonate="chrome", # reproduz a impressão digital TLS + HTTP/2 do Chrome
proxies={"https": "http://user:pass@proxy.example.com:8080"},
timeout=20)
Então mantenha o resto da história consistente — um User-Agent do Chrome, client hints sec-ch-ua correspondentes, Accept-Language plausível para o país do proxy. Para sites que adicionalmente exigem desafios JavaScript, nenhum cliente HTTP é suficiente; use um navegador real como em Proxies em Playwright, Puppeteer e Selenium.
Erros e o que significam
| Você vê | Significa | Correção |
|---|---|---|
ProxyError … 407 Proxy Authentication Required | Credenciais erradas, ou seu IP não está na lista de permissões | Verifique usuário/senha (strings de rotação longas!), codifique caracteres especiais, verifique a lista de permissões |
InvalidSchema: Missing dependencies for SOCKS support | requests sem o extra socks | pip install "requests[socks]" |
TypeError: … unexpected keyword argument 'proxies' | httpx ≥ 0.28 com o parâmetro removido | Use proxy= ou mounts= |
ProxyError … Cannot connect to proxy / ConnectTimeout | Host/porta errados, proxy fora do ar ou firewall | Verifique com curl -x; tente o outro protocolo |
| IP real retornado por um endpoint de eco de IP | Proxy não aplicado (chave de dicionário errada, variável de ambiente sobrescrevendo, parâmetro por requisição ausente no aiohttp) | Imprima session.proxies; verifique trust_env; passe proxy= na requisição |
SSLError apenas através do proxy | Proxy está interceptando TLS (MITM) ou esquema errado | Use esquema http:// para o proxy; pergunte ao provedor se eles terminam TLS |
| 403/CAPTCHA em sites protegidos, IP parece ok | Impressão digital TLS/HTTP identifica Python | curl_cffi com impersonate, ou um navegador real |
| Funciona por um tempo, depois 429 | Limite de taxa por IP atingido | Rotacione o session ID; diminua a velocidade; veja o guia de rotação |
Um modelo mínimo e correto
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"}) # UA honesto para alvos tolerantes
return s
s = make_session()
r = s.get("https://api.ipify.org?format=json", timeout=20)
r.raise_for_status()
print(r.json())
Verifique se o IP muda e então construa em cima disso. Para um pré-voo completo (vazamentos, cabeçalhos, listas de bloqueio) veja Como testar um proxy; para escolher entre datacenter e residencial para um determinado alvo, a comparação de tipos de proxy.
Perguntas frequentes
Como usar um proxy com Python requests?
Passe proxies={"http": url, "https": url} para a requisição ou defina em uma Session, onde url é http://user:pass@host:port. Adicione timeout=. Para SOCKS5 instale requests[socks] e use socks5h://.
Por que o httpx diz ‘unexpected keyword argument proxies’?
Porque proxies= foi removido no httpx 0.28. Use proxy="http://…" para um proxy, ou mounts= para proxies por alvo.
Como definir um proxy no aiohttp?
Passe proxy="http://user:pass@host:port" para cada requisição (session.get(url, proxy=…)). O parâmetro proxy_auth= está depreciado; coloque as credenciais na URL. Use aiohttp-socks para SOCKS.
Como rotacionar proxies em Python?
Com um provedor de backconnect, mude o session ID no nome de usuário do proxy por requisição ou por fluxo — sem necessidade de lista de IPs. Rotacione em 403/429 e associe cada novo IP a um cookie jar novo.
Por que meu script é bloqueado quando meu navegador no mesmo proxy não é?
Impressão digital TLS e HTTP/2: o módulo ssl do Python não parece um navegador. Use curl_cffi com impersonate= ou automatize um navegador real.
Devo usar socks5 ou socks5h?
socks5h. O h faz o proxy resolver nomes de host, prevenindo vazamentos de DNS e permitindo alcançar hosts que apenas o proxy pode resolver.