Corrigir 429 Too Many Requests: Backoff, Orçamentos e Distribuição de IPs
Um 429 é o único bloqueio que lhe diz exatamente como corrigi-lo — se você ler os cabeçalhos de resposta em vez de apenas tentar novamente. Aqui está a aritmética por trás da taxa segura de scraping.
HTTP 429 Too Many Requests é o bloqueio mais honesto que um site pode lhe enviar. Ao contrário de um 403, ele nomeia o problema — você foi rápido demais — e frequentemente traz a solução em um cabeçalho de resposta. No entanto, a reação padrão é envolver a chamada em um loop de repetição e esperar, o que converte um problema de ritmo solucionável em uma bagunça lenta e geradora de bloqueios. Este guia trata o 429 como o que ele é: um problema aritmético com quatro alavancas. Leia a resposta, ajuste-se ao limite publicado, recue corretamente quando ultrapassar, e distribua a carga restante entre identidades.
O que 429 significa, e quando está mentindo
Um limitador de taxa conta requests por identidade — geralmente um endereço IP, às vezes uma chave de API ou cookie de sessão — dentro de uma janela de tempo. Ultrapasse o limite e você recebe 429 em vez de conteúdo. As implementações diferem: baldes de tokens distribuem uma cota fixa que se recarrega em um cronograma, janelas deslizantes contam em um período contínuo em vez de minutos de relógio, e sistemas em camadas limitam em um limite suave antes de bloquear firmemente em um mais alto. Qual você enfrenta determina se uma pausa curta é suficiente ou se você deve esperar por uma janela inteira.
Agora, a ressalva que salva horas: um 429 no seu primeiro request não é uma limitação de taxa. É uma resposta de bot vestindo um disfarce de limitação de taxa. Um tópico amplamente lido no Stack Overflow descreve exatamente isso — a primeira chamada de um scraper retornou uma página dizendo "Misbehaving Content Scraper Please use robots.txt Your IP has been rate limited" junto com o 429. Nada foi excedido; o servidor simplesmente decidiu que o cliente era um bot e escolheu esse código. Se você vir 429 antes de ter enviado qualquer volume, trate-o como um problema de detecção e trabalhe os cabeçalhos e verificações de IP em nosso guia para erros 403 forbidden em vez disso.
Leia a resposta antes de mudar qualquer código
Servidores bem-comportados dizem quando voltar. Retry-After carrega um número de segundos ou uma data HTTP. Muitas APIs adicionam X-RateLimit-Limit (o teto), X-RateLimit-Remaining (o que resta na janela atual) e X-RateLimit-Reset (quando recarrega). Esses três transformam a repetição reativa em um ritmo proativo: você pode desacelerar antes do bloqueio em vez de depois.
import requests
r = requests.get("https://target.example/api/items", timeout=20)
print(r.status_code)
for h in ("Retry-After", "X-RateLimit-Limit", "X-RateLimit-Remaining", "X-RateLimit-Reset"):
if h in r.headers:
print(f"{h}: {r.headers[h]}")
# No headers at all? The limit is undocumented - measure it:
# send a slow ramp (1 req/s, then 2, then 4) and note where 429 starts.
Se nada útil voltar, meça o limite você mesmo com uma rampa: execute a um request por segundo por um minuto, depois dois, depois quatro, e registre a taxa na qual 429s aparecem. Dez minutos de medição superam uma semana de suposições, e o número que você encontrar se torna o orçamento sobre o qual tudo o mais é construído.

A aritmética do ritmo
Pegue o limite documentado e divida. Um limite de 100 requests por minuto significa 60 / 100 = 0,6 segundos entre requests como um piso absoluto — e um piso não é um alvo. A latência de rede varia, seu relógio e o do servidor não concordam, e um estouro na borda da janela pode dobrar sua taxa aparente. Mire em 70-80% do limite: aproximadamente 0,8 segundos por request nesse exemplo, o que ainda lhe dá 75 páginas por minuto.
A concorrência segue o mesmo número. Se você quiser 1,25 requests por segundo e cada request levar 2 segundos de ida e volta, você precisa de 1,25 x 2 = 2,5 requests em andamento — então um semáforo de 3, não os 50 que seu código assíncrono define como padrão. A expansão assíncrona não controlada é a causa mais comum de 429s: cem corrotinas lançadas de uma vez chegam como um único estouro instantâneo, não importa quão educada pareça a média. Se você fizer scraping com asyncio, os padrões de semáforo em scraping assíncrono em Python com httpx e aiohttp são a solução.
Backoff que funciona: exponencial, limitado, com jitter
Quando você atingir um 429, respeite Retry-After se presente. Caso contrário, comece em um segundo e dobre — 1, 2, 4, 8, 16 — até um limite rígido para que um alvo quebrado não possa paralisar sua fila para sempre. Depois adicione jitter. Sem randomização, cada trabalhador que atingiu a parede ao mesmo tempo tenta novamente no mesmo momento, reproduzindo o estouro que causou o problema.
import random, time, requests
def get_with_backoff(session, url, max_tries=6, cap=120.0):
for attempt in range(max_tries):
r = session.get(url, timeout=20)
if r.status_code != 429:
return r
ra = r.headers.get("Retry-After", "")
wait = float(ra) if ra.isdigit() else 2.0 ** attempt # 1, 2, 4, 8, 16, 32
wait = min(wait, cap)
wait += random.uniform(0, wait * 0.3) # jitter: break the lockstep
time.sleep(wait)
raise RuntimeError(f"still 429 after {max_tries} attempts: {url}")
Melhor ainda, feche o ciclo. Aumento aditivo/diminuição multiplicativa lhe dá um scraper que encontra o limite por conta própria e permanece logo abaixo dele: aumente a taxa enquanto as respostas estão limpas, reduza pela metade no instante em que um 429 chega. Mantenha um regulador por domínio — os limites são por host, e um alvo agressivo não deve desacelerar os outros quarenta.
class Pacer:
"""One per domain. Additive increase, multiplicative decrease."""
def __init__(self, rps=2.0, floor=0.2, ceiling=8.0):
self.rps, self.floor, self.ceiling = rps, floor, ceiling
def ok(self): # clean response: creep faster
self.rps = min(self.ceiling, self.rps + 0.05)
def throttled(self): # 429: halve immediately
self.rps = max(self.floor, self.rps / 2)
@property
def gap(self):
return 1.0 / self.rps
Distribuindo carga: o orçamento é por identidade, não por projeto
Uma vez que você está ajustando corretamente o ritmo e ainda precisa de mais taxa, a única alavanca restante são as identidades. Como o contador é vinculado ao seu IP, N IPs de saída lhe dão N vezes o orçamento — a aritmética é tão direta. Se um site tolera 60 requests por minuto por endereço e você precisa de 1.200 páginas por minuto, isso são 20 saídas concorrentes operando confortavelmente abaixo do limite, não uma saída operando vinte vezes acima dele.
É para isso que proxies rotativos realmente servem. Um gateway rotativo atribui a cada request um IP residencial diferente de um pool de mais de 90 milhões de endereços em mais de 200 países, então os contadores por IP nunca se enchem. Duas regras fazem a diferença entre distribuir carga e queimar um pool: mantenha a taxa por IP abaixo do limite mesmo após a rotação (a rotação multiplica seu orçamento, não o remove), e use sessões fixas para qualquer fluxo que abranja vários requests — um login, um carrinho, um conjunto de resultados paginado — para que a sessão não se quebre no meio. Quando você precisa do mesmo IP por alguns minutos e de um novo depois disso, os trade-offs estão descritos em sessões fixas versus sessões rotativas.
Multiplique seu orçamento de taxa com IPs residenciais

Mais barato do que mais IPs: envie menos requests
- Desduplicar antes de buscar. A maioria das filas de rastreamento contém a mesma URL sob parâmetros de rastreamento e barras finais - canonicize primeiro.
- Use GETs condicionais. Envie If-Modified-Since ou If-None-Match e um 304 custa uma fração da largura de banda e ainda conta como um request.
- Prefira endpoints JSON em vez de HTML renderizado. Uma chamada de API frequentemente substitui dez buscas de página, e os limites de API geralmente são documentados.
- Cache agressivamente durante o desenvolvimento. Reexecutar um analisador contra respostas salvas custa zero requests e zero bloqueios.
- Faça scraping fora do pico no fuso horário local do alvo. A mesma taxa prejudica menos um servidor às 03:00 e é menos frequentemente limitada.
- Busque apenas o que muda. Um rastreamento completo diário de um catálogo que é atualizado semanalmente são seis rastreamentos desperdiçados.
Disciplina de largura de banda paga duas vezes — menos requests significa menos 429s e uma conta menor, que é o mesmo argumento que fazemos em reduzir custos de largura de banda de proxy. E se você preferir não construir infraestrutura de ritmo, a Scraper API da QuantumProxies absorve repetições, rotação e limitação por domínio por trás de um endpoint que retorna markdown, JSON ou HTML.
Perguntas frequentes
Como evito o erro HTTP 429 too many requests em Python?
Defina um intervalo deliberado entre requests com base no limite publicado do alvo, limite a concorrência com um semáforo dimensionado para a taxa vezes a latência, respeite Retry-After quando aparecer, e tente novamente com backoff exponencial mais jitter. Se precisar de mais taxa depois disso, distribua requests entre IPs de proxy rotativos em vez de encurtar o intervalo.
Quanto tempo devo esperar após um 429?
Exatamente o tempo que Retry-After indicar, se o servidor enviar — pode ser uma contagem de segundos ou uma data HTTP. Sem esse cabeçalho, comece em um segundo e dobre a cada 429 subsequente até um limite de um ou dois minutos, adicionando jitter aleatório para que os trabalhadores paralelos não tentem novamente em uníssono.
Proxies corrigem erros 429?
Eles multiplicam seu orçamento, não removem o limite. Como os contadores são vinculados ao IP do cliente, distribuir uma execução por muitas saídas residenciais mantém cada endereço abaixo do limite. Mas um pool sendo martelado a dez vezes o limite por IP ainda coletará 429s — e queimará sua reputação. Ajuste o ritmo primeiro, depois rode.
Um 429 é o mesmo que ser banido?
Não. Um 429 é temporário por design e é liberado quando a janela é redefinida, o que o distingue de um bloqueio de identidade 403. Ignorá-lo repetidamente é como ele se torna permanente: ultrapassar continuamente é exatamente o sinal que promove uma limitação em uma proibição de IP mais duradoura.
Por que recebo 429 no primeiro request?
Porque nada foi realmente contado. Alguns servidores retornam 429 para qualquer cliente que considerem um bot, independentemente do volume — o código de status é apenas a resposta escolhida por eles. Verifique o corpo da resposta: se mencionar robots.txt, scrapers ou um firewall, corrija seus cabeçalhos, impressão digital TLS e IP de saída em vez do seu ritmo.
Trate limites de taxa como um orçamento que você gasta deliberadamente. Meça o teto, opere a 70-80% dele, recue com jitter quando ultrapassar, e compre mais identidades apenas quando o ritmo estiver correto. Feito nessa ordem, 429s deixam de ser uma classe de erro e se tornam um número em um arquivo de configuração.
Obtenha proxies rotativos e pare de lutar contra limites de taxa