Códigos de status que realmente te machucam — 301 vs 302, 401 vs 403 e o campo 5xx
Não é um dicionário. Um guia focado nos códigos de status HTTP que causam bugs reais em produção — o redirecionamento errado que agora está cacheado para sempre, a confusão entre 401/403 que revela sua lógica de autenticação, 429 sem Retry-After e a confusão entre 503 e 5-04 que te leva a debugar a camada errada.
Você enviou um redirecionamento e ele foi do tipo errado. Agora, todos os navegadores que o acessaram antes de você notarem já o armazenaram permanentemente, e a única forma de corrigir isso é esperar o expiração da cache ou pedir aos usuários para limpá-los. Isso é um 301.
Isso não é um dicionário de códigos de status — existem muitos desses. Este é o guia que você quer após ter lido a tabela e ainda ter enviado o código errado. Estamos passando pelos casos que causam bugs reais: caches permanentes quando você queria um temporário, erros de autenticação que revelam informações, respostas de limite de taxa que você não está tratando corretamente, e timeouts de gateway que apontam para a camada errada.
301 vs 302 vs 307 vs 308: A Matriz de Redirecionamento
O erro que todos cometem pelo menos uma vez: você usa 301 Moved Permanently enquanto testa uma reestruturação de URL. Funciona. Você continua. Depois, você reestrutura novamente. E agora, um grupo de seus usuários — todos que visitaram antes da segunda mudança — são enviados para o destino antigo para sempre, armazenado diretamente no navegador.
O 301 é permanente e armazena com agressividade. Os navegadores definem o TTL do redirecionamento armazenado como quase infinito, a menos que você tenha definido um Cache-Control cabeçalho. Não há forma programática de expirar esse redirecionamento no navegador do usuário. Se você ainda está definindo sua estrutura de URL, use 302.
O problema de preservação do método é uma entidade diferente. Quando um navegador segue um 301 ou 302, ele pode (e na prática, quase sempre faz) reduzir um POST para um GET no redirecionamento. Isso é tecnicamente uma violação do especificação original do HTTP/1.0, mas os navegadores normalizaram isso há muito tempo, e o RFC 7231 reconhece isso como comportamento padrão. Se você está redirecionando um POST — por exemplo, após uma submissão de formulário — e espera que o método seja preservado, você precisa usar 307 ou 308.
| Código | Permanente? | Preserva o Método? | Use para |
|---|---|---|---|
| 301 | Sim | Não (POST → GET) | Mudanças de URL permanentes onde GET é suficiente após o redirecionamento |
| 302 | Não | Não (POST → GET) | Redirecionamentos temporários, flags de recursos, testes A/B |
| 307 | Não | Sim | Redirecionamentos temporários onde o método deve ser preservado |
| 308 | Sim | Sim | Redirecionamentos permanentes onde o método deve ser preservado |
O suporte ao 308 é sólido agora — Chrome, Firefox, Safari e Edge tratam corretamente. A advertência: alguns clientes antigos de API e bibliotecas HTTP ainda não seguem o 308 corretamente, então, se você está redirecionando tráfego máquina para máquina e não controla nem o cliente nem sua biblioteca HTTP, teste explicitamente.
401 vs 403: Autenticação vs Autorização
O 401 significa “você não se identificou”. A especificação exige que ele inclua um WWW-Authenticate cabeçalho informando ao cliente como autenticar. É o código correto quando não há sessão válida, sem token ou quando o token expirou.
O 403 significa “eu sei quem você é e a resposta é não”. O usuário está autenticado, mas falta permissão. Retornar 403 em um token expirado é errado — isso é um 401. Retornar 401 em uma solicitação com permissões válidas mas insuficientes também é errado, e pior, confunde sua depuração de autenticação: você procurará por credenciais ausentes quando o problema real é a atribuição de papéis.
O argumento de segurança para retornar 404 em vez de 403 é real. Se sua API retornar 403 em GET /admin/users, você acabou informando a qualquer atacante que o endpoint existe e que eles precisariam de privilégios mais altos para acessá-lo. Retornar 404 em vez disso não revela nenhuma informação sobre a existência do recurso. É uma escolha de julgamento: o 403 é tecnicamente correto e mais fácil de depurar; o 404 é a escolha mais segura para endpoints sensíveis onde a enumerabilidade importa.
429: O Limite de Taxa é Inútil Sem Retry-After
Uma resposta 429 sem um Retry-After cabeçalho é uma caixa preta. O cliente sabe que foi limitado. Não sabe se deve esperar 100ms ou 24 horas. A maioria das implementações de cliente ou tenta novamente imediatamente (acabando com seu limite de taxa) ou desiste completamente.
Retry-After O cabeçalho pode ser um número inteiro (segundos para esperar) ou uma data HTTP (quando tentar novamente):
HTTP/1.1 429 Too Many Requests
Retry-After: 60
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1749254400
O X-RateLimit-* cabeçalhos não estão em nenhum RFC — são uma convenção de fato que surgiu do API do GitHub e que foi copiada por todos. Inclua-os junto com Retry-After. O trio de Limit/Remaining/Reset informa ao cliente onde está antes de atingir a parede, o que é mais útil do que apenas saber que atingiu a parede.
Uma coisa importante a destacar: Retry-After é também válido em respostas 503, e significa a mesma coisa — “volte daqui em diante em tantos segundos”. Se seu serviço está temporariamente indisponível por uma janela de manutenção, envie um 503 com Retry-After em vez de simplesmente interromper as conexões.
503 vs 504: Onde está o Falha?
Esses dois parecem semelhantes, mas apontam para camadas completamente diferentes de falha, e confundir os dois envia você na direção errada para depuração.
503 Serviço Indisponível Significa que o servidor que você alcançou não pode lidar com a solicitação agora — está sobrecarregado, em modo de manutenção ou uma dependência de backend está fora do ar. O próprio servidor respondeu; ele simplesmente está recusando o trabalho.
504 Gateway Timeout Significa que um proxy ou gateway (seu balanceador de carga, nginx, gateway de API, CDN) tentou alcançar um servidor upstream e não obteve resposta no tempo estipulado. O servidor que você alcançou está vivo. O que está atrás dele não está respondendo.
Na prática: se você está atrás de nginx e seu servidor de aplicação (Node, Rails, Django, etc.) cai, você recebe 502 Bad Gateway — nginx obteve uma resposta, mas era ruim. Se o servidor de aplicação para de responder completamente, você recebe 504. Se você retornar um erro intencional na camada de aplicação, você recebe 503. A distinção importa quando você está triagindo: 504 significa olhe para o serviço upstream, sua configuração de timeout e sua rede. 503 significa olhe para o próprio aplicativo.
422 vs 400: Erros de Validação Possuem Seu Próprio Código
400 Requisição Inválida É para requisições que o servidor não consegue interpretar — JSON malformado, sintaxe inválida na string de consulta, cabeçalhos obrigatórios ausentes. É um problema estrutural.
422 Entidade Inprocessável É para requisições que o servidor entendeu, mas não pode atuar porque os dados falham na validação — um intervalo de data onde o início é após o fim, um campo de e-mail com endereço inválido, um campo de quantidade com valor negativo. A requisição era sintaticamente correta. Os significados estavam errados.
A maioria das APIs combina ambos em 400 e esconde os detalhes de validação no corpo da resposta. Isso funciona, mas torna a manipulação de erros no lado do cliente mais difícil: os clientes precisam analisar o corpo para saber se é um erro de parsing ou um erro de validação. Usar 422 para erros de validação permite aos clientes usar o código de status como chave. O Rails já faz isso corretamente desde sempre; o JSON:API spec especifica 422 para erros de validação também.
A única nuance: o 422 é definido no WebDAV (RFC 4918), não no especificação principal do HTTP. Na prática isso não importa — todos os clientes e servidores HTTP tratam bem o 422 — mas você poderá encontrar um pedante que insiste em usar 400 em vez disso. Eles não estão errados, exatamente. Mas o 422 é mais específico e amplamente compreendido.
204 vs 200 com corpo vazio: Um é correto para DELETE
Quando um DELETE é bem-sucedido, a resposta correta é 204 Sem Conteúdo — e não 200 com corpo vazio, nem 200 com {"success": true}.
O 204 é o sinal explícito de “isso foi bem-sucedido e há intencionalmente nenhum corpo de resposta”. Um 200 com corpo vazio é tecnicamente válido, mas é ambíguo — os clientes não sabem se o corpo deveria estar lá e foi perdido, ou se a ausência é intencional. O 204 elimina essa ambiguidade.
A mesma lógica se aplica a PUT e PATCH quando você não retorna o recurso atualizado. Se sua API retorna o objeto atualizado após um PATCH, use 200. Se não, use 204. Não retorne 200 com um corpo vazio de {} ou null — isso é o 204 vestindo um traje.
Um detalhe importante: O 204 não deve incluir um corpo de mensagem de acordo com o RFC 9110. Se você retornar 204 e incluir acidentalmente um corpo (algumas bibliotecas permitem isso), alguns clientes HTTP irão lidar com isso de forma graciosa, outros não. Remova o corpo no seu manipulador de resposta, não apenas na sua intenção.
Referência Rápida: Os Códigos que Causam Problemas e Por Que
| Código | Significado | Erro Comum | Correção |
|---|---|---|---|
| 301 | Redirecionamento permanente | Usando durante testes — agora está armazenado para sempre | Use 302 até que o redirecionamento seja confirmado como permanente |
| 302 | Redirecionamento temporário | O POST é reduzido para GET ao seguir | Use 307 se o método deve ser preservado |
| 307 | Redirecionamento temporário (seguro em relação ao método) | Confundido com 302 | Use quando redirecionar POST/PUT/PATCH temporariamente |
| 308 | Redirecionamento permanente (seguro em relação ao método) | Ignorado em favor de 301 por hábito | Use em vez de 301 quando o método importa |
| 400 | Requisição inválida (erro de parsing) | Usado para erros de validação também | Use 422 para falhas de validação semânticas |
| 401 | Não autenticado | Retornado quando o usuário falta permissão (deveria ser 403) | Retorne 401 apenas quando as credenciais faltarem ou expirarem |
| 403 | Proibido | Retornado em vez de 404 para endpoints sensíveis de segurança | Considere 404 quando ocultar a existência do endpoint importa |
| 422 | Entidade não processável | Colapsada em 400 | Use para falhas de validação onde o corpo era parseável |
| 429 | Limitado por taxa | Sem cabeçalho Retry-After | Inclua sempre o cabeçalho Retry-After + X-RateLimit-* |
| 503 | Serviço indisponível | Confundido com 504 | Use quando o servidor alcançado não consegue lidar com a requisição |
| 504 | Timeout do gateway | Confundido com 503 | Investigue o serviço upstream, não o gateway |
| 204 | Sem conteúdo | Retornando 200 com corpo vazio em vez disso | Use 204 para DELETE/PUT/PATCH bem-sucedidos sem corpo de resposta |
Se você precisar rapidamente consultar qualquer código de status enquanto está debugando, IO Tools tem uma consulta de códigos de status HTTP que cobre a faixa completa com descrições e notas sobre quando usar cada um.
O padrão por trás de todos esses casos
A maioria desses erros vem do mesmo lugar: tratar códigos de status como categorias vagas (“4xx é erro do cliente, 5xx é erro do servidor, acabou”) em vez de como um protocolo com semânticas específicas. As semânticas importam porque os clientes — navegadores, bibliotecas HTTP, CDNs, ferramentas de monitoramento — realmente dependem delas. Um CDN não armazenará um 200 e um 204 da mesma forma. Um cliente HTTP não tentará novamente um 400 e um 503 com a mesma lógica. Um navegador não armazenará um 302 e um 301 com o mesmo TTL.
Use o código certo. A sobrecarga é zero. O benefício de depuração quando algo quebrar é não.
Instale nossas extensões
Adicione ferramentas de IO ao seu navegador favorito para acesso instantâneo e pesquisa mais rápida
恵 O placar chegou!
Placar é uma forma divertida de acompanhar seus jogos, todos os dados são armazenados em seu navegador. Mais recursos serão lançados em breve!
Ferramentas essenciais
Ver tudo Novas chegadas
Ver tudoAtualizar: Nosso ferramenta mais recente foi adicionado em 8 de junho de 2026
