Voltar ao blog

Como contornar a limitação de taxa da API ao fazer scraping com proxy: configuração de rotação e escolha de IP

Analisamos as razões para bloqueios de API ao usar proxies e mostramos métodos específicos para contornar o rate limiting: desde a configuração de rotação de IP até a escolha do tipo certo de proxy.

📅19 de fevereiro de 2026
```html

Você configurou um scraper, conectou proxies, mas a API ainda retorna erros 429 "Too Many Requests" ou bloqueia o acesso? O problema não está nos proxies em si, mas na estratégia inadequada de uso. A limitação de taxa é um mecanismo de proteção da API que limita o número de requisições de um único endereço IP em um determinado período. Neste artigo, vamos analisar por que ocorrem bloqueios ao trabalhar através de proxies e como configurar corretamente o sistema para contornar esses limites.

O que é limitação de taxa de API e como funciona

Limitação de taxa (rate limiting) é um mecanismo de proteção da API contra sobrecargas e abusos. O serviço estabelece um limite no número de requisições que podem ser feitas de uma única fonte em um determinado intervalo de tempo. Por exemplo, APIs populares utilizam tais limitações:

  • Twitter API: 300 requisições a cada 15 minutos para acesso padrão
  • Instagram Graph API: 200 requisições por hora por aplicativo
  • Google Maps API: depende do plano, geralmente 100-1000 requisições por dia
  • Wildberries API: limites não oficiais em torno de 60 requisições por minuto de um único IP
  • Avito API: 10 requisições por segundo para scraping de anúncios

Existem vários métodos para determinar a origem das requisições, onde a limitação de taxa é aplicada:

Endereço IP: o método mais comum. A API conta o número de requisições de um IP específico em uma janela de tempo.

Chave da API: se você usa autenticação por chave, o limite é vinculado a ela independentemente do IP.

User-Agent e fingerprint: algumas APIs analisam os cabeçalhos do navegador e criam uma impressão digital do cliente.

Sessão (cookies): o limite pode ser vinculado à sessão do usuário através de cookies.

Quando o limite é excedido, a API retorna o status HTTP 429 "Too Many Requests" e o cabeçalho Retry-After, indicando o tempo até que o limite seja redefinido. Alguns serviços utilizam uma "janela deslizante" (rolling window), onde o limite é atualizado gradualmente, enquanto outros utilizam uma janela fixa que é redefinida em um horário específico.

Por que proxies não salvam automaticamente da limitação de taxa

Muitos desenvolvedores erroneamente acreditam que basta conectar um proxy — e é possível enviar um número ilimitado de requisições. Na prática, surgem os seguintes problemas:

Uso de um único proxy para todas as requisições

Se seu script usa o mesmo endereço IP de proxy para todas as requisições, a API vê isso como um usuário comum e aplica os limites padrão. Por exemplo, você configurou um scraper de preços com Wildberries através de um único proxy residencial. O scraper faz 100 requisições por minuto, mas o limite é de 60 requisições. Resultado: bloqueio do IP por 10-30 minutos.

Rotação lenta de IP

Alguns usam um pool de 5-10 proxies e alternam entre eles sequencialmente. O problema é que cada IP ainda atinge o limite mais rápido do que ocorre a rotação completa. Suponha que você tenha 10 proxies e um limite de 100 requisições por hora por IP. Se você faz 1000 requisições por hora, cada proxy receberá 100 requisições — exatamente no limite. Qualquer desigualdade na distribuição levará a bloqueios.

Ignorando outros fatores de identificação

Mesmo com uma rotação ideal de IP, você pode ser bloqueado se:

  • Todas as requisições vêm com o mesmo User-Agent (por exemplo, python-requests/2.28.0)
  • Uma única chave da API é usada para todas as requisições
  • As requisições vêm com uma periodicidade perfeita (a cada 0,5 segundos) — isso parece um bot
  • Os endereços IP dos proxies estão na mesma sub-rede (por exemplo, todos no intervalo 192.168.1.x)

Reputação dos endereços IP

Proxies de data centers frequentemente entram em listas negras, pois seus IPs são usados por centenas de outros usuários para scraping. A API pode aplicar limites mais rigorosos a esses endereços ou bloqueá-los imediatamente. Por exemplo, Instagram e Facebook banem agressivamente data centers, mesmo que você não exceda os limites oficiais.

Estratégias de rotação de IP para contornar limites

A rotação correta de proxies é a chave para contornar a limitação de taxa. Vamos considerar estratégias eficazes dependendo da tarefa.

Rotação após cada requisição

A estratégia mais agressiva: cada requisição passa por um novo IP. É adequada para tarefas com limites muito rígidos (1-5 requisições por IP) ou quando é necessário espalhar a carga ao máximo. Para isso, são utilizados proxies residenciais com rotação automática — eles fornecem um pool de milhões de IPs, e cada requisição recebe automaticamente um novo endereço.

Exemplo de uso: scraping do Instagram através de uma API não oficial, onde o limite é de 5 requisições por minuto de um único IP. Com a rotação após cada requisição, você pode fazer 300 requisições por minuto através de 300 IPs diferentes.

Vantagens: máxima proteção contra limitação de taxa, cada IP é utilizado minimamente.

Desvantagens: custo elevado (proxies residenciais são mais caros), possíveis atrasos ao trocar de IP, mais difícil manter sessões.

Rotação por tempo (sticky sessions)

O endereço IP é utilizado por um determinado período (5-30 minutos), depois muda para um novo. Essa estratégia é adequada para APIs que exigem a manutenção da sessão, ou quando é necessário fazer várias requisições relacionadas de um único "usuário".

Cálculo do tempo ideal de rotação: se o limite da API é de 100 requisições por hora, e você planeja fazer 50 requisições através de um IP, use uma sticky session de 30 minutos. Durante esse tempo, você fará 25 requisições (com carga uniforme), o que é duas vezes menor que o limite.

Rotação por pool com monitoramento de limites

Estratégia avançada: seu script mantém o controle do número de requisições de cada IP e alterna automaticamente para um novo quando se aproxima do limite. Por exemplo, você tem um pool de 20 proxies, e o limite da API é de 100 requisições por hora. O script monitora o contador para cada IP e alterna para o próximo ao atingir 90 requisições.

Essa estratégia requer programação lógica, mas oferece máxima eficiência: você utiliza cada proxy em sua totalidade, sem exceder os limites.

Rotação geográfica

Algumas APIs aplicam diferentes limites dependendo da região. Por exemplo, o serviço pode restringir requisições dos EUA de forma mais rigorosa do que da Europa. Nesses casos, use proxies de diferentes países e distribua a carga entre eles.

Estratégia de rotação Quando usar Tipo de proxy
Após cada requisição Limites rígidos (1-10 requisições/IP), scraping de redes sociais Proxies residenciais com rotação automática
Por tempo (5-30 min) Necessita de sessão, limites médios (50-200 requisições/hora) Proxies residenciais sticky ou móveis
Por pool com monitoramento de limites Grande volume de scraping, limites conhecidos da API Qualquer tipo com pool de 10+ IPs
Geográfica Restrições regionais, scraping de conteúdo local Proxies residenciais de diferentes países

Configuração de atrasos entre requisições

Mesmo com uma rotação ideal de IP, é importante configurar corretamente os atrasos entre as requisições. Requisições muito rápidas parecem um ataque, mesmo que venham de diferentes IPs.

Cálculo do atraso mínimo

Fórmula: atraso = (janela de tempo em segundos / limite de requisições) × coeficiente de segurança

Exemplo: a API permite 100 requisições por hora (3600 segundos). Atraso mínimo = 3600 / 100 = 36 segundos. Adicionamos um coeficiente de segurança de 1.2: 36 × 1.2 = 43 segundos entre requisições de um único IP.

Se você usar 10 proxies com rotação, pode fazer requisições a cada 4,3 segundos (43 / 10), sem exceder o limite em nenhum IP.

Atrasos aleatórios (jitter)

Em vez de um atraso fixo de 5 segundos, use intervalos aleatórios, por exemplo, de 3 a 7 segundos. Isso faz com que seu tráfego pareça mais com as ações de um usuário real. Muitos sistemas de proteção contra bots analisam padrões: se as requisições chegam exatamente a cada 5.0 segundos, isso é suspeito.

Atraso exponencial em caso de erros

Quando você recebe um erro 429, não continue enviando requisições imediatamente. Use um atraso exponencial: a primeira tentativa após 1 segundo, a segunda após 2, a terceira após 4, a quarta após 8 e assim por diante. Esta é uma prática padrão que a API espera dos clientes.

Dica: Verifique o cabeçalho Retry-After na resposta da API. Ele indica o tempo exato em que você pode repetir a requisição. Use esse valor em vez de atrasos arbitrários.

Qual tipo de proxy escolher para trabalhar com API

A escolha do tipo de proxy impacta criticamente o sucesso em contornar a limitação de taxa. Vamos analisar os prós e contras de cada opção para trabalhar com APIs.

Proxies residenciais

Proxies residenciais utilizam endereços IP de usuários reais, fornecidos por provedores de internet. Para a API, isso parece uma internet doméstica comum.

Vantagens para APIs:

  • Alta confiança: APIs raramente banem IPs domésticos
  • Grandes pools: milhões de IPs para rotação
  • Diversidade geográfica: IPs de diferentes cidades e países
  • Ideais para redes sociais e APIs rigorosas (Instagram, Facebook, TikTok)

Desvantagens:

  • Custo elevado: pagamento geralmente por tráfego (de $5-15 por 1 GB)
  • Velocidade variável: depende da internet do usuário final
  • Instabilidade: o IP pode ser desconectado a qualquer momento

Quando usar: scraping de Instagram, Facebook, TikTok, trabalho com APIs de marketplaces (Wildberries, Ozon), quaisquer tarefas onde a reputação do IP é crítica.

Proxies móveis

Proxies móveis utilizam IPs de operadoras móveis (4G/5G). Um único IP é frequentemente utilizado por milhares de usuários reais simultaneamente, portanto, as APIs raramente os bloqueiam.

Vantagens para APIs:

  • Máxima confiança: APIs não podem banir IPs de operadoras móveis
  • Ideais para aplicativos móveis e APIs (Instagram, TikTok, Snapchat)
  • Troca automática de IP ao reconectar (modo avião)
  • Um único IP pode fazer mais requisições sem ser banido

Desvantagens:

  • Custo muito elevado: de $50-150 por um IP por mês
  • Pequenos pools: difícil obter centenas de IPs móveis
  • Velocidade variável: depende da qualidade da conexão móvel

Quando usar: trabalho com APIs móveis, scraping de Instagram/TikTok em grandes volumes, quando é necessária a máxima proteção contra bans.

Proxies de data centers

Proxies de data centers são endereços IP de servidores localizados em data centers. Eles não estão associados a usuários reais.

Vantagens para APIs:

  • Custo baixo: de $1-5 por IP por mês
  • Alta velocidade: canais de 1-10 Gbps
  • Estabilidade: IPs não se desconectam aleatoriamente
  • Grandes pools: fácil obter centenas de IPs

Desvantagens:

  • Baixa confiança: muitas APIs bloqueiam data centers
  • IPs frequentemente em listas negras devido a outros usuários
  • Não são adequados para redes sociais e serviços rigorosos

Quando usar: scraping de APIs públicas sem proteção rigorosa (clima, taxas de câmbio, notícias), trabalho com APIs próprias, testes e desenvolvimento.

Critério Residenciais Móveis Data Centers
Confiança da API Alta Máxima Baixa
Tamanho do pool Milhões de IPs Centenas de IPs Milhares de IPs
Velocidade Média (10-50 Mbps) Média (5-100 Mbps) Alta (100+ Mbps)
Custo $5-15/GB $50-150/IP/mês $1-5/IP/mês
Para redes sociais ✅ Excelente ✅ Ideal ❌ Não adequados
Para APIs públicas ✅ Bom ✅ Bom (caro) ✅ Excelente

Implementação prática: exemplos de código em Python

Vamos considerar exemplos específicos de implementação para contornar a limitação de taxa usando proxies. Todos os exemplos são em Python com a biblioteca requests.

Rotação simples de um pool de proxies

Implementação básica com rotação cíclica de IP de uma lista:

import requests
import time
from itertools import cycle

# Lista de proxies (formato: protocol://user:pass@host:port)
PROXY_LIST = [
    'http://user1:pass1@proxy1.example.com:8080',
    'http://user2:pass2@proxy2.example.com:8080',
    'http://user3:pass3@proxy3.example.com:8080',
]

# Criando um iterador cíclico
proxy_pool = cycle(PROXY_LIST)

def make_request(url):
    proxy = next(proxy_pool)  # Pegando o próximo proxy do pool
    proxies = {
        'http': proxy,
        'https': proxy
    }
    
    try:
        response = requests.get(url, proxies=proxies, timeout=10)
        return response
    except requests.exceptions.RequestException as e:
        print(f"Erro com o proxy {proxy}: {e}")
        return None

# Exemplo de uso
for i in range(10):
    response = make_request('https://api.example.com/data')
    if response and response.status_code == 200:
        print(f"Requisição {i+1}: sucesso")
    time.sleep(2)  # Atraso entre requisições

Rotação com monitoramento de limites

Versão mais avançada, que conta as requisições para cada proxy e alterna ao se aproximar do limite:

import requests
import time
from collections import defaultdict

class ProxyRotator:
    def __init__(self, proxy_list, max_requests_per_ip=90, time_window=3600):
        self.proxy_list = proxy_list
        self.max_requests = max_requests_per_ip  # Limite de requisições por IP
        self.time_window = time_window  # Janela de tempo em segundos
        self.request_counts = defaultdict(list)  # Histórico de requisições para cada IP
        self.current_index = 0
    
    def get_proxy(self):
        """Retorna o proxy com o menor número de requisições"""
        current_time = time.time()
        
        # Limpa registros antigos fora da janela de tempo
        for proxy in self.request_counts:
            self.request_counts[proxy] = [
                t for t in self.request_counts[proxy]
                if current_time - t < self.time_window
            ]
        
        # Busca o proxy com o menor número de requisições
        available_proxies = []
        for proxy in self.proxy_list:
            count = len(self.request_counts[proxy])
            if count < self.max_requests:
                available_proxies.append((proxy, count))
        
        if not available_proxies:
            # Se todos os proxies esgotaram o limite, aguarde
            oldest_request = min(
                min(times) for times in self.request_counts.values() if times
            )
            wait_time = self.time_window - (current_time - oldest_request) + 1
            print(f"Todos os proxies esgotaram o limite. Aguardando {wait_time:.0f} seg...")
            time.sleep(wait_time)
            return self.get_proxy()
        
        # Escolhe o proxy com o menor número de requisições
        proxy = min(available_proxies, key=lambda x: x[1])[0]
        self.request_counts[proxy].append(current_time)
        return proxy
    
    def make_request(self, url, **kwargs):
        proxy = self.get_proxy()
        proxies = {'http': proxy, 'https': proxy}
        
        try:
            response = requests.get(url, proxies=proxies, timeout=10, **kwargs)
            return response
        except requests.exceptions.RequestException as e:
            print(f"Erro com o proxy {proxy}: {e}")
            return None

# Exemplo de uso
PROXY_LIST = [
    'http://user:pass@proxy1.example.com:8080',
    'http://user:pass@proxy2.example.com:8080',
]

rotator = ProxyRotator(PROXY_LIST, max_requests_per_ip=100, time_window=3600)

for i in range(500):  # Fazendo 500 requisições
    response = rotator.make_request('https://api.example.com/data')
    if response and response.status_code == 200:
        print(f"Requisição {i+1}: sucesso")
    time.sleep(1)  # Atraso mínimo

Tratamento de erros 429 com atraso exponencial

Tratamento correto da resposta "Too Many Requests" considerando o cabeçalho Retry-After:

import requests
import time

def make_request_with_retry(url, proxies, max_retries=5):
    """Faz uma requisição com tentativas automáticas em caso de erro 429"""
    
    for attempt in range(max_retries):
        try:
            response = requests.get(url, proxies=proxies, timeout=10)
            
            if response.status_code == 200:
                return response
            
            elif response.status_code == 429:
                # Verifica o cabeçalho Retry-After
                retry_after = response.headers.get('Retry-After')
                
                if retry_after:
                    wait_time = int(retry_after)
                    print(f"Limite de taxa. Aguardando {wait_time} seg (do Retry-After)")
                else:
                    # Atraso exponencial: 2^attempt segundos
                    wait_time = 2 ** attempt
                    print(f"Limite de taxa. Tentativa {attempt+1}, aguardando {wait_time} seg")
                
                time.sleep(wait_time)
                continue
            
            else:
                print(f"Erro HTTP {response.status_code}")
                return None
        
        except requests.exceptions.RequestException as e:
            print(f"Erro de conexão: {e}")
            if attempt < max_retries - 1:
                time.sleep(2 ** attempt)
                continue
            return None
    
    print(f"Excedido o número de tentativas ({max_retries})")
    return None

# Exemplo de uso
proxies = {
    'http': 'http://user:pass@proxy.example.com:8080',
    'https': 'http://user:pass@proxy.example.com:8080'
}

response = make_request_with_retry('https://api.example.com/data', proxies)
if response:
    print("Dados recebidos:", response.json())

Uso de proxies residenciais com rotação automática

Muitos provedores de proxies residenciais oferecem um endpoint que muda automaticamente o IP a cada requisição. Exemplo de configuração:

import requests
import random
import time

# Proxies residenciais com rotação automática
# Formato: protocol://username:password@gateway:port
ROTATING_PROXY = 'http://customer-USER:PASS@proxy.provider.com:12321'

def make_request_rotating(url):
    """Requisição através de um proxy rotativo (novo IP a cada vez)"""
    proxies = {
        'http': ROTATING_PROXY,
        'https': ROTATING_PROXY
    }
    
    # Adiciona um User-Agent aleatório para maior anonimato
    user_agents = [
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
        'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36',
        'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36',
    ]
    
    headers = {
        'User-Agent': random.choice(user_agents)
    }
    
    try:
        response = requests.get(url, proxies=proxies, headers=headers, timeout=15)
        return response
    except requests.exceptions.RequestException as e:
        print(f"Erro: {e}")
        return None

# Fazendo 100 requisições através de diferentes IPs
for i in range(100):
    response = make_request_rotating('https://api.example.com/data')
    if response and response.status_code == 200:
        print(f"Requisição {i+1}: sucesso, IP alterado")
    
    # Atraso aleatório de 1-3 segundos
    time.sleep(random.uniform(1, 3))

Monitoramento de limites e tratamento de erros

Trabalhar efetivamente com APIs requer monitoramento constante dos limites e tratamento adequado de erros. Aqui estão práticas-chave:

Análise dos cabeçalhos de resposta

Muitas APIs retornam informações sobre limites nos cabeçalhos de resposta. Cabeçalhos padrão:

  • X-RateLimit-Limit — número máximo de requisições na janela
  • X-RateLimit-Remaining — quantas requisições restam
  • X-RateLimit-Reset — tempo de redefinição do limite (timestamp Unix)
  • Retry-After — em quantos segundos você pode repetir a requisição

Exemplo de leitura desses cabeçalhos:

response = requests.get(url, proxies=proxies)

# Verificando cabeçalhos de limites
limit = response.headers.get('X-RateLimit-Limit')
remaining = response.headers.get('X-RateLimit-Remaining')
reset_time = response.headers.get('X-RateLimit-Reset')

if remaining:
    remaining = int(remaining)
    if remaining < 10:
        print(f"Atenção! Restam apenas {remaining} requisições")
        
if reset_time:
    import datetime
    reset_dt = datetime.datetime.fromtimestamp(int(reset_time))
    print(f"O limite será redefinido em {reset_dt}")

Registro e estatísticas

Mantenha estatísticas detalhadas das requisições para cada proxy. Isso ajudará a identificar IPs problemáticos e otimizar a rotação:

import json
from datetime import datetime

class RequestLogger:
    def __init__(self):
        self.stats = {}
    
    def log_request(self, proxy, status_code, response_time):
        if proxy not in self.stats:
            self.stats[proxy] = {
                'total': 0,
                'success': 0,
                'rate_limited': 0,
                'errors': 0,
                'avg_response_time': 0
            }
        
        self.stats[proxy]['total'] += 1
        
        if status_code == 200:
            self.stats[proxy]['success'] += 1
        elif status_code == 429:
            self.stats[proxy]['rate_limited'] += 1
        else:
            self.stats[proxy]['errors'] += 1
        
        # Atualiza o tempo médio de resposta
        current_avg = self.stats[proxy]['avg_response_time']
        total = self.stats[proxy]['total']
        self.stats[proxy]['avg_response_time'] = (
            (current_avg * (total - 1) + response_time) / total
        )
    
    def print_stats(self):
        print("\n=== Estatísticas do proxy ===")
        for proxy, data in self.stats.items():
            success_rate = (data['success'] / data['total'] * 100) if data['total'] > 0 else 0
            print(f"\nProxy: {proxy}")
            print(f"  Total de requisições: {data['total']}")
            print(f"  Bem-sucedidas: {data['success']} ({success_rate:.1f}%)")
            print(f"  Limitadas: {data['rate_limited']}")
            print(f"  Erros: {data['errors']}")
            print(f"  Tempo médio de resposta: {data['avg_response_time']:.2f}s")

# Uso
logger = RequestLogger()

start_time = time.time()
response = requests.get(url, proxies=proxies)
response_time = time.time() - start_time

logger.log_request(proxy, response.status_code, response_time)
logger.print_stats()

Mudança automática de estratégia

Se você está constantemente recebendo erros 429, diminua automaticamente os atrasos nas requisições ou aumente o pool de proxies:

class AdaptiveRateLimiter:
    def __init__(self, initial_delay=1.0):
        self.delay = initial_delay
        self.consecutive_429 = 0
    
    def on_success(self):
        """Requisição bem-sucedida - pode acelerar um pouco"""
        self.consecutive_429 = 0
        self.delay = max(0.5, self.delay * 0.95)  # Diminui o atraso em 5%
    
    def on_rate_limit(self):
        """Recebeu 429 - precisa desacelerar"""
        self.consecutive_429 += 1
        self.delay *= 1.5  # Aumenta o atraso em 1.5 vezes
        
        if self.consecutive_429 > 5:
            print("ATENÇÃO: Muitas erros 429. Verifique as configurações!")
    
    def wait(self):
        """Aguarda antes da próxima requisição"""
        time.sleep(self.delay)
        return self.delay

# Uso
limiter = AdaptiveRateLimiter(initial_delay=2.0)

for i in range(1000):
    response = make_request(url)
    
    if response.status_code == 200:
        limiter.on_success()
    elif response.status_code == 429:
        limiter.on_rate_limit()
    
    delay = limiter.wait()
    print(f"Requisição {i+1}, atraso: {delay:.2f}s")

Tratamento de CAPTCHA e outros bloqueios

Algumas APIs, ao exceder os limites, mostram um CAPTCHA em vez de um bloqueio direto. Sinais:

  • Código de status 403 com corpo de resposta contendo "captcha" ou "recaptcha"
  • Redirecionamento para uma página com CAPTCHA (status 302)
  • Cabeçalhos especiais como X-Captcha-Required: true

Nesses casos, é necessário:

  1. Parar imediatamente de usar esse IP
  2. Alternar para outro proxy do pool
  3. Aumentar os atrasos entre as requisições
  4. Adicionar mais diversidade nos User-Agent e outros cabeçalhos

Importante: Se você enfrenta regularmente CAPTCHA ao usar proxies residenciais, o problema provavelmente está nos padrões de comportamento (cabeçalhos iguais, requisições muito rápidas), e não nos endereços IP.

Conclusão

Contornar a limitação de taxa de API ao usar proxies não é apenas uma configuração técnica, mas uma estratégia abrangente que inclui a escolha correta do tipo de proxy, configuração da rotação de IP, gerenciamento de atrasos e monitoramento de limites. Principais conclusões do artigo:

  • Proxies por si só não resolvem o problema da limitação de taxa — é necessária uma estratégia de rotação adequada
  • Para redes sociais e APIs rigorosas, use proxies residenciais ou móveis; para APIs públicas, os data centers são adequados
  • Calcule o tamanho do pool de proxies com base nos limites da API e na velocidade desejada de scraping
  • Sempre monitore os limites e ajuste sua estratégia conforme necessário
```