Se você faz scraping, crawling ou automatiza qualquer coisa em escala com Python, mais cedo ou mais tarde o site alvo percebe que todas as requisições vêm de um único IP e te bloqueia. Rotacionar proxies em Python distribui seu tráfego entre vários endereços IP, de modo que nenhum deles sozinho dispara um limite de taxa ou recebe um banimento. Este guia mostra o código exato para requests, httpx e aiohttp, além de como escolher entre um gateway rotativo e um pool de IP gerenciado.
Duas decisões transversais moldam tudo o que vem a seguir. Primeira: sessões rotativas vs sticky — um novo IP por requisição, ou um IP mantido para um fluxo de várias etapas. Segunda: IPs residenciais vs datacenter — veja a matriz de decisão de tipo de proxy. Acerte nessas duas e o código é a parte fácil.
1. Rotação por gateway (recomendado). Você se conecta a um único endpoint e o provedor te entrega um novo IP de saída a cada nova conexão. Sem lista para gerenciar, sem IPs mortos para eliminar. O pool residencial dinâmico da JIBAO funciona assim: mesmo host e porta, um novo IP a cada requisição.
2. Lista de IP autogerenciada. Você mantém uma lista de entradas host:port e escolhe uma por requisição. Mais controle, mas você é responsável pela verificação de saúde, pelas retentativas e pelo rastreamento de banimentos. Útil com IPs de datacenter dedicados quando você precisa de endereços conhecidos e estáveis.
O caso mais simples — rotear uma requisição através de um gateway que rotaciona para você. Use socks5h:// (o h no final significa que o DNS é resolvido no lado do proxy, o que evita vazar consultas):
import requests
# JIBAO rotating residential gateway: a new exit IP per connection
PROXY = "socks5h://USERNAME:[email protected]:10001"
proxies = {"http": PROXY, "https": PROXY}
for _ in range(5):
r = requests.get("https://httpbin.org/ip", proxies=proxies, timeout=30)
print(r.json()["origin"]) # a different IP each loop
Precisa que o requests fale SOCKS5? Instale o extra: pip install "requests[socks]". Se você preferir um endpoint de proxy HTTP, troque o esquema para http:// — o resto é idêntico.
import random
import requests
PROXY_POOL = [
"socks5h://USERNAME-country-us:[email protected]:10001",
"socks5h://USERNAME-country-uk:[email protected]:10001",
"socks5h://USERNAME-country-de:[email protected]:10001",
]
def fetch(url):
proxy = random.choice(PROXY_POOL)
return requests.get(url, proxies={"http": proxy, "https": proxy}, timeout=30)
resp = fetch("https://example.com")
print(resp.status_code)
Fluxos de login, carrinhos e resultados paginados quebram se o IP muda no meio da tarefa. Fixe um IP adicionando um token de sessão ao nome de usuário; reutilize o mesmo token para manter o mesmo IP de saída durante toda a sua vida útil:
import requests
SESSION_ID = "task-0001"
PROXY = f"socks5h://USERNAME-session-{SESSION_ID}:[email protected]:10001"
s = requests.Session()
s.proxies = {"http": PROXY, "https": PROXY}
s.post("https://example.com/login", data={"u": "me", "p": "secret"})
s.get("https://example.com/dashboard") # same IP, session intact
O httpx te dá um cliente moderno com HTTP/2 e async nativo. Note que versões mais recentes recebem um único argumento proxy=:
import httpx
PROXY = "socks5h://USERNAME:[email protected]:10001"
with httpx.Client(proxy=PROXY, timeout=30) as client:
for _ in range(5):
print(client.get("https://httpbin.org/ip").json()["origin"])
O suporte a SOCKS no httpx precisa de pip install "httpx[socks]". Para HTTP/2, adicione http2=True ao cliente — isso faz seu tráfego parecer mais com o de um navegador real, o que combina bem com a correspondência de impressão digital TLS.
Para alta vazão, dispare muitas requisições de uma vez. Cada conexão através do gateway recebe seu próprio IP de saída, então concorrência e rotação andam juntas:
import asyncio
import aiohttp
from aiohttp_socks import ProxyConnector
PROXY = "socks5://USERNAME:[email protected]:10001"
async def fetch(url):
connector = ProxyConnector.from_url(PROXY)
async with aiohttp.ClientSession(connector=connector) as session:
async with session.get(url, timeout=aiohttp.ClientTimeout(total=30)) as r:
return await r.text()
async def main():
urls = ["https://httpbin.org/ip"] * 20
results = await asyncio.gather(*(fetch(u) for u in urls))
print(f"fetched {len(results)} pages")
asyncio.run(main())
Instale o conector SOCKS com pip install aiohttp_socks. Construa um conector novo por tarefa para que cada requisição abra uma nova conexão via proxy.
A rotação só compensa se você refizer as falhas em um IP novo. Aplique backoff exponencial e rotacione o token de sessão a cada tentativa:
import requests
from time import sleep
def fetch_with_retry(url, max_retries=4):
for attempt in range(max_retries):
proxy = f"socks5h://USERNAME-session-r{attempt}:[email protected]:10001"
try:
r = requests.get(url, proxies={"http": proxy, "https": proxy}, timeout=30)
if r.status_code in (403, 429):
raise requests.HTTPError(f"blocked: {r.status_code}")
r.raise_for_status()
return r.text
except requests.RequestException:
sleep(2 ** attempt) # 1s, 2s, 4s, 8s
raise RuntimeError(f"failed after {max_retries} tries: {url}")
Antes de uma execução grande, confirme que o IP realmente muda. Acesse um endpoint de eco algumas vezes e verifique se os IPs diferem. Para também confirmar que sua impressão digital TLS não está te entregando, rode a requisição contra o verificador gratuito de impressão digital JA3/TLS da JIBAO — um IP rotativo com uma impressão digital Python óbvia ainda é bloqueado.
Quando a rotação está sólida, o próximo muro que você enfrenta normalmente é o fingerprinting, não os IPs. Se IPs residenciais limpos ainda recebem 403, leia como contornar o fingerprinting TLS com curl_cffi e a receita completa de bypass do Cloudflare.
Ganhe 500MB de tráfego grátis e um gateway residencial rotativo que te entrega um novo IP a cada requisição.
Começar Teste GrátisNovos usuários recebem 500MB ao se cadastrar, mais um bônus na primeira recarga. Oferta por tempo limitado.