Objetivos de aprendizado
Depois de ler este artigo, você vai conseguir:
- Entender os três tipos de limite: por rota, global e de requisições inválidas
- Ler os headers e o corpo de uma resposta 429
- Corrigir e evitar o rate limit em discord.js e discord.py
Você olha o console do bot e vê isto:
{
"message": "You are being rate limited.",
"retry_after": 1.337,
"global": false
}É o corpo de uma resposta HTTP com status 429 Too Many Requests. O Discord limita quantas chamadas cada bot pode fazer à API, e você passou do limite. Na maioria dos casos a biblioteca já espera sozinha e o bot segue funcionando.
O caso grave é quando o bot ignora o aviso, acumula respostas de erro e o Discord bloqueia o IP por um tempo. Esse bloqueio temporário é o que a própria documentação do Discord chama de "Cloudflare ban".
Quais são os limites do Discord?#
Existem três mecanismos diferentes, e confundir os três gera a maior parte das dúvidas.
- Limite por rota. Cada endpoint tem um bucket próprio. Enviar mensagens num canal tem um limite, editar um canal tem outro. Os valores mudam e o Discord pede que você não os fixe no código: leia os headers.
- Limite global. Até 50 requisições por segundo por bot. Sem o header
Authorization, o limite vale por IP. Endpoints de interação (respostas a slash commands) não entram nessa conta. - Limite de requisições inválidas. Respostas 401, 403 e 429 contam como inválidas. Acima de 10.000 em 10 minutos, o IP é bloqueado temporariamente. Um 429 com
X-RateLimit-Scope: shared(limite de um recurso compartilhado) não conta.
Há ainda o limite do Gateway, a conexão WebSocket: 120 eventos enviados por conexão a cada 60 segundos. Acima disso, o Discord desconecta o bot na hora.
Como ler uma resposta 429?#
Os headers que importam:
| Header | O que informa |
|---|---|
Retry-After |
Tempo de espera antes de tentar de novo |
X-RateLimit-Remaining |
Requisições restantes no bucket |
X-RateLimit-Reset-After |
Segundos até o bucket renovar (aceita decimais) |
X-RateLimit-Bucket |
ID do bucket, útil para agrupar rotas |
X-RateLimit-Global |
Presente só quando o limite global foi atingido |
X-RateLimit-Scope |
user, global ou shared, só em respostas 429 |
O corpo JSON traz message, retry_after (segundos, com decimais) e global. Se global for true, o bot inteiro está parado, não só uma rota.
Por que meu bot recebe 429?#
Da causa mais comum para a menos comum:
- Loops sem pausa. Renomear 200 canais, dar cargo a todos os membros ou apagar mensagens uma a uma, tudo de uma vez.
- Edição constante de mensagens. Um "contador ao vivo" ou barra de progresso que edita a cada segundo bate no limite da rota de mensagens.
- Muitos eventos gerando chamadas. Um bot que responde a cada mensagem de um servidor movimentado ou reage a cada evento com uma chamada à API.
- Retry cego. Quando uma chamada falha, o código repete na hora, sem esperar, e cada tentativa vira mais um 429.
- Token inválido em loop de reinício. O bot sobe, recebe 401, cai, reinicia e repete. Cada ciclo soma requisições inválidas. Veja o artigo sobre token do bot.
- Reconexões em excesso ao Gateway. O limite é de 1.000 chamadas IDENTIFY por 24 horas. Ao atingir esse limite, o Discord encerra as sessões do bot e redefine o token.
Como corrigir o erro 429?#
No discord.js (v14)#
A biblioteca já espera cada rate limit sozinha. Seu trabalho é observar e reduzir o volume. Este trecho registra cada limite atingido e avisa quando as respostas inválidas se acumulam:
import { Client, GatewayIntentBits, RESTEvents } from "discord.js";
const client = new Client({
intents: [GatewayIntentBits.Guilds],
rest: {
// avisa a cada 500 respostas 401/403/429 na janela de 10 minutos
invalidRequestWarningInterval: 500,
},
});
client.rest.on(RESTEvents.RateLimited, (info) => {
console.warn(
`429 em ${info.method} ${info.route}: espera de ${info.timeToReset} ms (global: ${info.global})`,
);
});
client.rest.on(RESTEvents.InvalidRequestWarning, (info) => {
console.warn("Muitas requisições inválidas:", info);
});
await client.login(process.env.DISCORD_TOKEN);A opção rejectOnRateLimit (uma função que recebe os dados do limite e retorna true, como () => true, ou uma lista de rotas) faz a biblioteca lançar um RateLimitError em vez de esperar, útil para um comando que prefere responder "tente em instantes" a ficar preso na fila. Dois padrões que vale conhecer: globalRequestsPerSecond vem em 50, o limite global do Discord, e o aviso de invalidRequestWarningInterval vem desligado (0).
No discord.py (2.x)#
O discord.py também espera por conta própria e, por padrão, sem teto de espera. Você pode definir um com max_ratelimit_timeout (mínimo de 30 segundos, só para limites não globais); acima disso, a biblioteca lança discord.RateLimited, com o tempo em retry_after:
import asyncio
import os
import discord
intents = discord.Intents.default()
client = discord.Client(intents=intents, max_ratelimit_timeout=30.0)
async def renomear_canais(canais: list[discord.TextChannel]) -> None:
for canal in canais:
try:
await canal.edit(name=f"{canal.name}-arquivo")
except discord.RateLimited as erro:
print(f"Limite atingido, esperando {erro.retry_after:.1f}s")
await asyncio.sleep(erro.retry_after)
await canal.edit(name=f"{canal.name}-arquivo") # tenta de novo uma vez
await asyncio.sleep(1) # pausa entre itens do lote
client.run(os.environ["DISCORD_TOKEN"])O que vale para qualquer biblioteca#
- Respeite
Retry-After. Não repita antes do tempo. Se você faz requisições HTTP à mão, leia o header e espere. - Processe lotes com intervalo. Uma fila com pausa entre itens custa segundos e evita o problema.
- Edite menos. Atualize um painel a cada 10 ou 30 segundos, não a cada segundo.
- Use o endpoint em lote quando existir. Apagar muitas mensagens tem endpoint próprio (
bulk delete), em vez de uma chamada por mensagem. - Não repita 401 e 403. Token inválido ou falta de permissão não se resolvem tentando de novo. Corrija a causa.
O que é o ban temporário do Cloudflare?#
Se o seu IP passa de 10.000 requisições inválidas em 10 minutos, o Discord bloqueia temporariamente esse IP na API. Isso dá cerca de 16 a 17 inválidas por segundo, sem parar. Acontece em loops de reinício e em retry sem pausa, não em uso normal.
Se você suspeita de bloqueio:
- Pare o bot. Cada tentativa nova só alimenta o contador.
- Descubra o que gerava as respostas 401, 403 e 429. Os logs mostram a rota.
- Corrija o loop e espere o bloqueio expirar.
- Suba o bot de novo com
invalidRequestWarningIntervalligado, como no exemplo acima.
Como saber se é rate limit ou outro problema?#
- 429 com
retry_afterpequeno: rate limit comum, a biblioteca resolve. - 429 com
global: truerepetido: você passou de 50 requisições por segundo. Procure o loop. - 401 repetido: token errado ou redefinido.
- 403 repetido: o bot não tem permissão naquele canal ou cargo. Confira antes de chamar.
- Todas as chamadas falham de uma vez: possível bloqueio de IP.
- Bot cai e reinicia sem parar: veja por que o bot fica offline.
Como fazer isso na Square Cloud#
O rate limit é uma regra da API do Discord e vale em qualquer hospedagem. O que muda de uma hospedagem para outra é a rapidez com que você enxerga o problema. Na Square Cloud, os logs ficam disponíveis em tempo real no painel, na CLI e no VS Code, então um aviso de requisições inválidas aparece enquanto o bot roda.
O reinício automático, opcional e ligado por padrão no deploy pelo painel, traz o bot de volta quando o processo encerra com erro. Isso mantém o bot no ar, mas com um token inválido cada reinício pode gerar mais uma resposta 401, como no loop descrito acima. Por isso, trate o erro de login no código: registre uma mensagem clara no log, não repita a tentativa e corrija o token nas variáveis de ambiente antes de reiniciar.
Bots de Discord rodam em containers isolados, com discord.js, discord.py, JDA, Discord.Net ou outra biblioteca de Gateway, e a latência média até o Gateway do Discord é de cerca de 30 ms. O deploy é por upload de ZIP, CLI, GitHub ou extensão do VS Code, e o token fica nas variáveis de ambiente da aplicação. Veja os detalhes em hospedagem de bots de Discord. Para subir o primeiro bot, siga o guia de como hospedar um bot do discord.js.
Hospedagem de bots
Seu bot online 24/7, com reinício automático
Perguntas frequentes
Quanto tempo dura um erro 429 no Discord?
O tempo vem na própria resposta, no header Retry-After e no campo retry_after do JSON, em segundos. Esperar esse tempo e tentar de novo resolve.
Qual é o limite global de requisições do Discord?
Cada bot pode fazer até 50 requisições por segundo à API REST. Além disso, cada rota tem o próprio limite, que você descobre pelos headers X-RateLimit-*.
Posso ser banido por causa de erros 429?
Sim. Respostas 401, 403 e 429 contam como requisições inválidas, e 10.000 delas em 10 minutos fazem o Discord bloquear temporariamente o IP. Um 429 com X-RateLimit-Scope shared não conta.
O discord.js e o discord.py tratam o 429 sozinhos?
Sim, ambos esperam o rate limit por padrão. O problema aparece quando o código gera volume demais, repete requisições que falham ou reinicia em loop com um token inválido.
Mais em Bots
Ver todos os 33 artigos- Quanto custa hospedar um bot do Discord?O custo de hospedar um bot do Discord depende de RAM, tempo online, banco de dados e serviços externos. Veja como estimar o seu e onde o gasto aparece.
- Rodar bot no celular (Termux) ou no PC vs hospedar: o que mudaUm bot no PC ou no celular (Termux) fica offline quando o aparelho desliga, dorme ou perde a rede. Compare as três opções e veja quando cada uma serve.
- Como deixar um bot do Discord online 24/7Para deixar um bot do Discord online 24/7, rode o processo numa máquina sempre ligada com reinício automático. Veja PC, VPS com pm2 ou systemd e hospedagem.
- Por que meu bot do Discord fica offline (e como resolver)Bot do Discord offline quase sempre é processo caído, token inválido, intent não habilitada ou falta de memória. Veja como diagnosticar cada causa e corrigir.