O que fazer se proxies são constantemente banidos: guia completo de diagnóstico e solução de problemas
Bloqueios constantes de proxies — um dos problemas mais frequentes ao fazer web scraping, automação e trabalhar com múltiplas contas. Neste artigo, vamos analisar por que isso acontece e como resolver o problema sistematicamente, em vez de mudar infinitamente de provedores na esperança de um milagre.
Por que realmente banindo proxies
Antes de procurar soluções, você precisa entender a mecânica dos bloqueios. Os sistemas anti-fraude modernos usam proteção em múltiplas camadas, e o ban de proxy é apenas uma consequência, não a causa. Compreender como esses sistemas funcionam permite construir uma estratégia eficaz de bypass.
Reputação de IP e listas negras
Cada endereço IP tem uma reputação formada com base no histórico de seu uso. Se um endereço foi usado anteriormente para spam, ataques DDoS ou web scraping em massa, ele entra em bancos de dados como Spamhaus, SORBS ou listas proprietárias de serviços específicos. Quando você se conecta através de tal IP, o sistema imediatamente o trata com suspeita.
Proxies de data center são particularmente propensos a esse problema. Subnets inteiras podem ser marcadas como "hosting", e qualquer tráfego delas recebe automaticamente um nível elevado de verificação. Amazon AWS, Google Cloud, DigitalOcean — seus intervalos de IP são bem conhecidos e frequentemente bloqueados preventivamente.
Você pode verificar a reputação do IP através de serviços como IPQualityScore, Scamalytics ou AbuseIPDB. Se seu proxy mostrar um fraud score acima de 75, o problema está exatamente aqui — mude o provedor ou o tipo de proxy.
Padrões de requisições
Um humano não faz 100 requisições por segundo. Um humano não navega por páginas com periodicidade perfeita de 2 segundos. Um humano não ignora imagens, CSS e JavaScript, solicitando apenas HTML. Os sistemas anti-fraude analisam exatamente esses padrões, e qualquer desvio do comportamento "humano" aumenta o risco de bloqueio.
Particularmente revelador é o estatístico de tempo entre requisições. Se você tem um intervalo estável — é um sinal claro de automação. Adicionar um atraso aleatório (por exemplo, de 1 a 5 segundos) reduz significativamente a probabilidade de detecção.
Incompatibilidade de metadados
Quando seu User-Agent diz que você está usando Chrome no Windows, mas os cabeçalhos HTTP revelam características do Python requests — isso é uma bandeira vermelha. Quando o endereço IP está geolocalizado na Alemanha, mas as configurações de idioma do navegador indicam russo — outra bandeira vermelha. Quando o fuso horário em JavaScript não corresponde à geografia do IP — terceira bandeira.
O acúmulo de tais incompatibilidades leva o sistema a classificar a conexão como suspeita e aplicar medidas de proteção: desde captcha até bloqueio completo do IP.
Impressão digital do navegador
Os sistemas de proteção modernos coletam dezenas de parâmetros do navegador: resolução de tela, fontes instaladas, plugins, renderização WebGL, contexto de áudio e muito mais. O conjunto desses parâmetros cria uma "impressão digital" única que permanece constante mesmo ao mudar de IP.
Se você muda de proxy, mas a impressão digital permanece a mesma, o sistema entende que é o mesmo usuário. E se uma impressão digital aparece com centenas de IPs diferentes em pouco tempo — é um sinal claro de automação.
Diagnóstico: como entender a causa do bloqueio
Antes de mudar as configurações aleatoriamente, faça um diagnóstico. Isso economizará horas de experimentação e ajudará a encontrar a causa real do problema. Uma abordagem sistemática para diagnóstico é a chave para uma solução eficaz.
Passo 1: Verifique o próprio proxy
Comece com uma verificação básica da funcionalidade do proxy independentemente de seu script principal:
import requests
proxy = {
"http": "http://user:pass@proxy-server:port",
"https": "http://user:pass@proxy-server:port"
}
# Verificação de funcionalidade básica
try:
response = requests.get("https://httpbin.org/ip", proxies=proxy, timeout=10)
print(f"IP através do proxy: {response.json()['origin']}")
except Exception as e:
print(f"Erro de conexão: {e}")
# Verificação de vazamento de IP real
response = requests.get("https://browserleaks.com/ip", proxies=proxy)
# Compare com seu IP real
Se o proxy não funciona nem em requisições simples — o problema está no próprio proxy ou nas credenciais. Verifique o formato correto de conexão, a presença de fundos no saldo e os limites do provedor.
Passo 2: Verifique a reputação do IP
Use vários serviços para uma avaliação abrangente:
# Obtenha o IP do proxy
proxy_ip = requests.get("https://api.ipify.org", proxies=proxy).text
# Verifique nestes serviços:
# https://www.ipqualityscore.com/free-ip-lookup-proxy-vpn-test
# https://scamalytics.com/ip/{proxy_ip}
# https://www.abuseipdb.com/check/{proxy_ip}
# https://whatismyipaddress.com/ip/{proxy_ip}
print(f"Verifique o IP {proxy_ip} nos serviços acima")
Preste atenção aos seguintes indicadores: fraud score (deve estar abaixo de 50), tipo de IP (residencial é melhor que data center), presença em listas negras. Se o IP for marcado como VPN/Proxy — muitos sites o tratarão com suspeita desde o início.
Passo 3: Isole o problema
Tente o mesmo proxy em diferentes sites de destino. Se o bloqueio ocorre em todos — o problema está no proxy ou em sua configuração. Se apenas em um site específico — o problema está na proteção desse site ou em seu comportamento nele.
Também tente diferentes proxies no mesmo site. Se todos forem bloqueados — o problema não está no proxy, mas em seu script, impressão digital ou padrão de comportamento. Este é um teste criticamente importante que muitos pulam.
Passo 4: Análise de respostas do servidor
Diferentes tipos de bloqueios se manifestam de formas diferentes. Aprenda a distingui-los:
def analyze_response(response):
status = response.status_code
if status == 403:
print("Acesso proibido — possível IP na lista negra")
elif status == 429:
print("Muitas requisições — reduza a frequência")
elif status == 503:
print("Serviço indisponível — possível proteção contra DDoS")
elif status == 407:
print("Autenticação de proxy necessária — verifique credenciais")
elif "captcha" in response.text.lower():
print("Captcha detectada — suspeita de bot")
elif "blocked" in response.text.lower():
print("Bloqueio explícito — mude o IP e reconsidere a abordagem")
elif len(response.text) < 1000:
print("Resposta suspeitosamente curta — possível stub")
else:
print(f"Status {status}, comprimento da resposta: {len(response.text)}")
Rotação adequada: frequência, lógica, implementação
Rotação de proxy não é simplesmente "mudar IP com mais frequência". A rotação incorreta pode prejudicar mais do que sua ausência. Vamos considerar diferentes estratégias e quando aplicá-las.
Estratégia 1: Rotação por número de requisições
A abordagem mais simples — mudar o IP após um certo número de requisições. Adequada para web scraping, onde a sessão não é necessária:
import random
class ProxyRotator:
def __init__(self, proxy_list, requests_per_proxy=50):
self.proxies = proxy_list
self.requests_per_proxy = requests_per_proxy
self.current_proxy = None
self.request_count = 0
def get_proxy(self):
if self.current_proxy is None or self.request_count >= self.requests_per_proxy:
# Adicione aleatoriedade ao número de requisições
self.requests_per_proxy = random.randint(30, 70)
self.current_proxy = random.choice(self.proxies)
self.request_count = 0
self.request_count += 1
return self.current_proxy
# Uso
rotator = ProxyRotator(proxy_list)
for url in urls_to_scrape:
proxy = rotator.get_proxy()
response = requests.get(url, proxies={"http": proxy, "https": proxy})
Observe a aleatoriedade no número de requisições por proxy. Um número fixo (por exemplo, exatamente 50) é um padrão que pode ser detectado. Um intervalo aleatório torna o comportamento menos previsível.
Estratégia 2: Rotação por tempo
Para tarefas onde a sessão é importante (por exemplo, trabalhar com contas), é melhor vincular o IP ao tempo:
import time
import random
class TimeBasedRotator:
def __init__(self, proxy_list, min_minutes=10, max_minutes=30):
self.proxies = proxy_list
self.min_seconds = min_minutes * 60
self.max_seconds = max_minutes * 60
self.current_proxy = None
self.rotation_time = 0
def get_proxy(self):
current_time = time.time()
if self.current_proxy is None or current_time >= self.rotation_time:
self.current_proxy = random.choice(self.proxies)
# Intervalo aleatório até a próxima rotação
interval = random.randint(self.min_seconds, self.max_seconds)
self.rotation_time = current_time + interval
print(f"Novo proxy, próxima rotação em {interval//60} minutos")
return self.current_proxy
Estratégia 3: Sessões pegajosas para contas
Ao trabalhar com múltiplas contas, é crítico que cada conta use um IP permanente. Mudar o IP para uma conta conectada é um caminho certo para o ban:
class AccountProxyManager:
def __init__(self, proxy_pool):
self.proxy_pool = proxy_pool
self.account_proxies = {} # account_id -> proxy
self.used_proxies = set()
def get_proxy_for_account(self, account_id):
# Se a conta já tem um proxy atribuído — retorne-o
if account_id in self.account_proxies:
return self.account_proxies[account_id]
# Encontre um proxy livre
available = [p for p in self.proxy_pool if p not in self.used_proxies]
if not available:
raise Exception("Sem proxies livres para novas contas")
proxy = random.choice(available)
self.account_proxies[account_id] = proxy
self.used_proxies.add(proxy)
return proxy
def release_account(self, account_id):
"""Libera o proxy ao remover a conta"""
if account_id in self.account_proxies:
proxy = self.account_proxies.pop(account_id)
self.used_proxies.discard(proxy)
# Uso
manager = AccountProxyManager(residential_proxy_list)
for account in accounts:
proxy = manager.get_proxy_for_account(account.id)
# Todas as ações desta conta passam por um IP
Estratégia 4: Rotação adaptativa
A abordagem mais avançada — mudar de proxy em resposta a sinais do site de destino:
class AdaptiveRotator:
def __init__(self, proxy_list):
self.proxies = proxy_list
self.current_proxy = random.choice(proxy_list)
self.proxy_scores = {p: 100 for p in proxy_list} # "Saúde" inicial do proxy
def get_proxy(self):
return self.current_proxy
def report_result(self, success, response_code=200):
"""Chamado após cada requisição"""
if success and response_code == 200:
# Requisição bem-sucedida — aumentamos o score ligeiramente
self.proxy_scores[self.current_proxy] = min(100,
self.proxy_scores[self.current_proxy] + 1)
elif response_code == 429:
# Rate limit — reduzimos muito e rotacionamos
self.proxy_scores[self.current_proxy] -= 30
self._rotate()
elif response_code == 403:
# Ban — zeramos o score e rotacionamos
self.proxy_scores[self.current_proxy] = 0
self._rotate()
elif response_code == 503:
# Possível proteção — reduzimos e rotacionamos
self.proxy_scores[self.current_proxy] -= 20
self._rotate()
def _rotate(self):
# Selecionamos o proxy com melhor score
available = [(p, s) for p, s in self.proxy_scores.items() if s > 20]
if not available:
# Todos os proxies estão "mortos" — resetamos os scores
self.proxy_scores = {p: 50 for p in self.proxies}
available = list(self.proxy_scores.items())
# Seleção ponderada por score
self.current_proxy = max(available, key=lambda x: x[1])[0]
print(f"Rotação para proxy com score {self.proxy_scores[self.current_proxy]}")
Impressão digital do navegador e seu papel nos bloqueios
Fingerprint é o conjunto de características do navegador que permite identificar um usuário mesmo sem cookies. Se você muda de IP, mas o fingerprint permanece o mesmo, o sistema de proteção facilmente vincula todas as suas sessões.
Do que consiste o fingerprint
O fingerprint moderno inclui dezenas de parâmetros. Aqui estão as principais categorias:
| Categoria | Parâmetros | Peso na identificação |
|---|---|---|
| User-Agent | Navegador, versão, SO | Médio |
| Tela | Resolução, profundidade de cor, pixel ratio | Médio |
| Fontes | Lista de fontes instaladas | Alto |
| WebGL | Renderer, vendor, hash de renderização | Muito alto |
| Canvas | Hash da imagem desenhada | Muito alto |
| Áudio | Fingerprint AudioContext | Alto |
| Fuso horário | Fuso horário, offset | Médio |
| Idiomas | navigator.languages | Médio |
| Plugins | navigator.plugins | Baixo (em navegadores modernos) |
Consistência de fingerprint e IP
É criticamente importante que o fingerprint corresponda à geografia do IP. Se o proxy está na Alemanha, o fingerprint deve parecer um usuário alemão:
// Exemplo de inconsistência (RUIM):
// IP: Alemanha
// Fuso horário: America/New_York
// Idiomas: ["ru-RU", "ru"]
// Isso causará suspeita
// Fingerprint consistente (BOM):
// IP: Alemanha
// Fuso horário: Europe/Berlin
// Idiomas: ["de-DE", "de", "en-US", "en"]
Ferramentas para gerenciar fingerprint
Para trabalho sério, use ferramentas especializadas:
Playwright com Stealth:
from playwright.sync_api import sync_playwright
from playwright_stealth import stealth_sync
with sync_playwright() as p:
browser = p.chromium.launch(
proxy={"server": "http://proxy:port", "username": "user", "password": "pass"}
)
context = browser.new_context(
viewport={"width": 1920, "height": 1080},
locale="de-DE",
timezone_id="Europe/Berlin",
geolocation={"latitude": 52.52, "longitude": 13.405},
permissions=["geolocation"]
)
page = context.new_page()
stealth_sync(page) # Aplicamos patches stealth
page.goto("https://target-site.com")
Puppeteer com puppeteer-extra:
const puppeteer = require('puppeteer-extra');
const StealthPlugin = require('puppeteer-extra-plugin-stealth');
puppeteer.use(StealthPlugin());
const browser = await puppeteer.launch({
args: [`--proxy-server=http://proxy:port`]
});
const page = await browser.newPage();
// Redefinimos timezone
await page.evaluateOnNewDocument(() => {
Object.defineProperty(Intl.DateTimeFormat.prototype, 'resolvedOptions', {
value: function() {
return { timeZone: 'Europe/Berlin' };
}
});
});
Navegadores anti-detecção
Para trabalhar com contas, frequentemente usam navegadores anti-detecção (Multilogin, GoLogin, Dolphin Anty e outros). Eles permitem criar perfis isolados com fingerprints únicos. Cada perfil tem seu próprio conjunto de parâmetros, cookies, localStorage — um ambiente completamente isolado.
A vantagem dos anti-detecção é que resolvem o problema de fingerprint "fora da caixa". A desvantagem é o custo e a complexidade da automação (embora muitos tenham API).
Padrões comportamentais: como não parecer um bot
Mesmo com fingerprint perfeito e IP limpo, você pode ser banido por comportamento não-humano. Os sistemas modernos analisam não apenas parâmetros técnicos, mas também padrões de interação com o site.
Atrasos temporais
Um humano não faz requisições com intervalo constante. Adicione atrasos aleatórios com distribuição normal:
import random
import time
import numpy as np
def human_delay(min_sec=1, max_sec=5, mean=2.5):
"""
Gera um atraso que parece humano.
Usa distribuição lognormal —
a maioria dos atrasos são curtos, mas às vezes há atrasos longos.
"""
delay = np.random.lognormal(mean=np.log(mean), sigma=0.5)
delay = max(min_sec, min(max_sec, delay))
return delay
def human_typing_delay():
"""Atraso entre pressionamentos de tecla ao digitar texto"""
return random.uniform(0.05, 0.25)
# Uso
for url in urls:
response = requests.get(url, proxies=proxy)
process(response)
time.sleep(human_delay()) # Pausa aleatória entre requisições
Imitação de navegação
Um humano não vai direto para a página do produto por um link direto. Ele entra na página inicial, usa a busca, navega por categorias. Imite este caminho:
async def human_like_navigation(page, target_url):
"""Imita navegação humana para a página de destino"""
# 1. Vamos para a página inicial
await page.goto("https://example.com")
await page.wait_for_timeout(random.randint(2000, 4000))
# 2. Às vezes rolamos a página inicial
if random.random() > 0.5:
await page.evaluate("window.scrollBy(0, 300)")
await page.wait_for_timeout(random.randint(1000, 2000))
# 3. Usamos busca ou navegação
if random.random() > 0.3:
search_box = await page.query_selector('input[type="search"]')
if search_box:
await search_box.type("search query", delay=100)
await page.keyboard.press("Enter")
await page.wait_for_timeout(random.randint(2000, 4000))
# 4. Vamos para a página de destino
await page.goto(target_url)
# 5. Rolamos a página como um humano
await human_scroll(page)
async def human_scroll(page):
"""Imita rolagem humana"""
scroll_height = await page.evaluate("document.body.scrollHeight")
current_position = 0
while current_position < scroll_height * 0.7: # Não até o final
scroll_amount = random.randint(200, 500)
await page.evaluate(f"window.scrollBy(0, {scroll_amount})")
current_position += scroll_amount
await page.wait_for_timeout(random.randint(500, 1500))
Movimentos do mouse
Alguns sistemas rastreiam movimentos do mouse. Movimento em linha reta do ponto A ao ponto B é um sinal de bot. Um humano move o mouse em uma curva com micro-correções:
import bezier
import numpy as np
def generate_human_mouse_path(start, end, num_points=50):
"""
Gera um caminho de mouse que parece humano,
usando curvas de Bezier com pequeno ruído.
"""
# Pontos de controle para a curva de Bezier
control1 = (
start[0] + (end[0] - start[0]) * random.uniform(0.2, 0.4) + random.randint(-50, 50),
start[1] + (end[1] - start[1]) * random.uniform(0.2, 0.4) + random.randint(-50, 50)
)
control2 = (
start[0] + (end[0] - start[0]) * random.uniform(0.6, 0.8) + random.randint(-50, 50),
start[1] + (end[1] - start[1]) * random.uniform(0.6, 0.8) + random.randint(-50, 50)
)
# Criamos a curva de Bezier
nodes = np.asfortranarray([
[start[0], control1[0], control2[0], end[0]],
[start[1], control1[1], control2[1], end[1]]
])
curve = bezier.Curve(nodes, degree=3)
# Geramos pontos na curva
points = []
for t in np.linspace(0, 1, num_points):
point = curve.evaluate(t)
# Adicionamos micro-ruído
x = point[0][0] + random.uniform(-2, 2)
y = point[1][0] + random.uniform(-2, 2)
points.append((x, y))
return points
async def human_click(page, selector):
"""Clica no elemento com movimento de mouse humanóide"""
element = await page.query_selector(selector)
box = await element.bounding_box()
# Ponto de destino — não o centro, mas um ponto aleatório dentro do elemento
target_x = box['x'] + random.uniform(box['width'] * 0.2, box['width'] * 0.8)
target_y = box['y'] + random.uniform(box['height'] * 0.2, box['height'] * 0.8)
# Posição atual do mouse (ou posição inicial aleatória)
start_x = random.randint(0, 1920)
start_y = random.randint(0, 1080)
# Geramos o caminho
path = generate_human_mouse_path((start_x, start_y), (target_x, target_y))
# Movemos o mouse pelo caminho
for x, y in path:
await page.mouse.move(x, y)
await page.wait_for_timeout(random.randint(5, 20))
# Pequena pausa antes do clique
await page.wait_for_timeout(random.randint(50, 150))
await page.mouse.click(target_x, target_y)
Carregamento de recursos
Um navegador real carrega não apenas HTML, mas também CSS, JavaScript, imagens, fontes. Se você usar requests e solicitar apenas HTML — isso é suspeito. Ao trabalhar com navegadores headless, esse problema é resolvido automaticamente, mas ao usar clientes HTTP, você precisa considerar esse aspecto.
Escolha do tipo de proxy para sua tarefa
Diferentes tipos de proxy têm características diferentes e são adequados para diferentes tarefas. A escolha incorreta é uma causa frequente de bloqueios.
Proxies de data center
Proxies de data center — são endereços IP pertencentes a provedores de hospedagem. Eles são fáceis de identificar pela propriedade AS (sistemas autônomos) de grandes data centers.
Vantagens:
- Alta velocidade e estabilidade
- Baixo custo
- Grandes pools de IP
Desvantagens:
- Fáceis de detectar
- Frequentemente em listas negras
- Não adequados para sites com proteção séria
Adequados para: ferramentas SEO, verificação de disponibilidade, trabalho com APIs sem proteção rigorosa, testes.
Proxies residenciais
Proxies residenciais — são endereços IP de usuários reais, fornecidos através de programas de parceria ou SDK em aplicativos. Eles pertencem a provedores de internet comuns (ISP).
Vantagens:
- Parecem usuários comuns
- Baixo fraud score
- Geografia ampla
- Difíceis de detectar
Desvantagens:
- Custo mais alto (pagamento por tráfego)
- Velocidade depende do usuário final
- IPs podem "desaparecer" (usuário desligou o dispositivo)
Adequados para: web scraping de sites protegidos, trabalho com redes sociais, e-commerce, qualquer tarefa onde é importante não ser detectado.
Proxies móveis
Proxies móveis — são endereços IP de operadoras móveis (MTS, Beeline, Megafon e análogos em outros países). Eles têm um status especial por causa da tecnologia CGNAT.
Vantagens:
- Confiança máxima dos sites
- Um IP é usado por milhares de usuários reais — difícil de banir
- Ideais para trabalho com contas
- Mudança de IP por solicitação (reconexão à rede)
Desvantagens:
- Custo mais alto
- Velocidade limitada
- Menos escolha de geografias
Adequados para: multi-contas, trabalho com Instagram/Facebook/TikTok, registro de contas, qualquer tarefa com alto risco de ban.
Tabela comparativa
| Parâmetro | Data center | Residenciais | Móveis |
|---|---|---|---|
| Detectabilidade | Alta | Baixa | Muito baixa |
| Velocidade | Alta | Média | Baixa-média |
| Custo | $ | $$ | $$$ |
| Para redes sociais | Não adequados | Adequados | Ideais |
| Para web scraping | Sites simples | Qualquer site | Excessivo |
Técnicas avançadas de bypass de proteção
Quando os métodos básicos não funcionam, você precisa usar técnicas mais complexas. Vamos considerar várias abordagens avançadas.
Trabalho com Cloudflare e proteções similares
Cloudflare, Akamai, PerimeterX — esses sistemas usam desafios JavaScript para verificar o navegador. Uma requisição HTTP simples não passará. Opções de solução:
1. Uso de navegador real:
from playwright.sync_api import sync_playwright
def bypass_cloudflare(url, proxy):
with sync_playwright() as p:
browser = p.chromium.launch(
headless=False, # Às vezes headless é detectado
proxy={"server": proxy}
)
page = browser.new_page()
page.goto(url)
# Aguardamos a passagem da verificação (geralmente 5-10 segundos)
page.wait_for_timeout(10000)
# Verificamos se passamos
if "challenge" not in page.url:
# Salvamos cookies para requisições subsequentes
cookies = page.context.cookies()
return cookies
browser.close()
return None
2. Uso de soluções prontas:
# cloudscraper — biblioteca para bypass de Cloudflare
import cloudscraper
scraper = cloudscraper.create_scraper(
browser={
'browser': 'chrome',
'platform': 'windows',
'desktop': True
}
)
scraper.proxies = {"http": proxy, "https": proxy}
response = scraper.get("https://protected-site.com")
Solução de captcha
Se o site mostra captcha, existem várias abordagens:
Serviços de reconhecimento: 2Captcha, Anti-Captcha, CapMonster. Eles resolvem captcha para você