Skip to content
Voltar ao blog
Tutoriais

Códigos HTTP: guia completo (1xx-5xx) com exemplos

Referência completa de códigos HTTP de 1xx a 5xx com exemplos reais, erros comuns (401 vs 403, 301 vs 302) e impacto no SEO. Consulte a colinha agora.

14 min de leitura

Códigos HTTP: guia completo (1xx-5xx) com exemplos

Você abre o DevTools e a aba Network está metade vermelha. Seu endpoint devolve 502 em produção, 200 localmente, e um colega acabou de perguntar no Slack “isso deveria ser 401 ou 403?”. Códigos de status HTTP parecem simples (três dígitos, cinco categorias), mas a escolha errada vaza informação, quebra SEO e transforma o plantão num pesadelo.

Este guia é uma colinha completa de códigos HTTP para quem desenvolve no dia a dia. Você leva três coisas: uma tabela de referência rápida com todos os códigos que aparecem de verdade na produção, matrizes de decisão para os pares que mais causam confusão (301 vs 302, 401 vs 403, 404 vs 410, 502 vs 504) e uma seção de ferramentas mostrando como inspecionar os códigos com curl, fetch e Python requests. Cada código a seguir está fundamentado na RFC 9110, padrão atual de semântica HTTP, e no Registro de Códigos de Status HTTP do IANA.

Referência rápida: todos os códigos HTTP num só lugar

Estes são os códigos que você encontra na produção, agrupados por classe. Salve esta tabela; o restante do artigo destrincha os mais traiçoeiros.

CódigoNomeQuando aparece
100ContinueEnvio de POST grande com Expect: 100-continue
101Switching ProtocolsHandshake de WebSocket, upgrade para HTTP/2
103Early HintsServidor envia headers Link antes da resposta real
200OKSucesso padrão para GET, PUT, PATCH
201CreatedPOST que cria um recurso (devolve Location)
202AcceptedTrabalho assíncrono enfileirado, ainda não concluído
204No ContentDELETE com sucesso, PUT sem corpo de resposta
206Partial ContentRange request, seek de vídeo, download retomável
301Moved PermanentlyURL antiga aposentada, buscadores transferem link equity
302FoundRedirecionamento temporário, URL original ainda é canônica
303See OtherPadrão Post/Redirect/Get após POST de formulário
304Not ModifiedGET condicional com ETag ou If-Modified-Since casando
307Temporary RedirectComo 302, mas preserva método e corpo
308Permanent RedirectComo 301, mas preserva método e corpo
400Bad RequestJSON malformado, campo obrigatório ausente, falha de schema
401UnauthorizedSem credenciais ou token expirado
403ForbiddenAutenticado, mas sem permissão
404Not FoundRecurso não existe (ou você está escondendo)
405Method Not AllowedPOST num endpoint só de GET (precisa incluir Allow)
408Request TimeoutCliente demorou demais para enviar a requisição
409ConflictFalha de optimistic lock, chave duplicada
410GoneRecurso removido em definitivo, não volta
415Unsupported Media TypeContent-Type errado, p. ex. XML para uma API JSON
422Unprocessable ContentSintaxe válida, semântica inválida (erro de validação)
425Too EarlyRisco de replay de early-data no TLS 1.3
428Precondition RequiredServidor exige If-Match para evitar lost update
429Too Many RequestsRate limit (precisa incluir Retry-After)
451Unavailable for Legal ReasonsDMCA, retirada por LGPD/GDPR, geo-block
500Internal Server ErrorExceção não tratada no seu código
501Not ImplementedMétodo ou recurso não suportado (raro em REST)
502Bad GatewayUpstream devolveu resposta inválida
503Service UnavailableModo de manutenção ou sobrecarga
504Gateway TimeoutUpstream não respondeu a tempo
507Insufficient StorageWebDAV ficou sem disco
508Loop DetectedRedirecionamento ou recursão infinita em WebDAV
511Network Authentication RequiredCaptive portal de WiFi de hotel/aeroporto

O restante deste artigo destrincha cada classe com matrizes de decisão, antipadrões e as consequências de SEO de errar a escolha.

Como funcionam os códigos HTTP (anatomia dos 3 dígitos)

Por que três dígitos?

Códigos HTTP têm três dígitos decimais porque o HTTP/0.9 precisava de um sinal de largura fixa, pequeno o bastante para um parser ramificar rápido e grande o bastante para deixar espaço para códigos novos. Três dígitos dão 900 valores possíveis (100–999), muito mais que o suficiente: o registro do IANA usa hoje cerca de 60.

O primeiro dígito é a classe. O segundo e o terceiro identificam o código específico dentro dela. Um cliente que não reconhece 418 deve recair no tratamento como 4xx genérico. A RFC 9110 §15 deixa isso explícito: clientes devem tratar códigos desconhecidos como o x00 da classe correspondente.

As cinco categorias num relance

ClasseSignificadoExige corpo?Cacheável por padrão?
1xxInformativo: provisório, ainda vem maisNãoNão
2xxSucesso: requisição entendida e aceitaGeralmenteDepende do método
3xxRedirecionamento: mais ação necessáriaOpcional301, 308 sim; 302, 307 não
4xxErro do cliente: culpa sua, conserte a requisiçãoSim (explicar)Em geral, não
5xxErro do servidor: culpa nossa, talvez retentar ajudeSim (explicar)Não

A coluna “Cacheável por padrão” importa muito. CDNs e navegadores cacheiam 301 e 308 agressivamente e para sempre. Escolher o código de redirect errado em produção é difícil de desfazer porque os usuários já têm o redirect cacheado localmente. Voltaremos a isso na seção de SEO.

Se quiser se aprofundar na estrutura de URL (que é justamente sobre o que os códigos de redirect operam), o guia Codificação e Decodificação de URL percorre percent-encoding, query strings e o pipeline em nível de byte que define o que faz uma URL ser válida.

1xx — Informativo (quando você realmente vê)

A maioria dos desenvolvedores passa anos sem ver um 1xx direto. São respostas provisórias: o servidor avisa ao cliente “ainda estou aqui, pode continuar”. O DevTools do navegador costuma escondê-los, e quase toda biblioteca HTTP os colapsa na resposta final.

Para cada código abaixo, a referência de status de resposta HTTP do MDN é a referência cruzada mais amigável caso você queira uma segunda opinião sobre uma definição.

100 Continue

O cliente envia Expect: 100-continue nos headers e espera antes de transmitir um corpo grande. O servidor responde 100 Continue se topar receber o corpo, ou um 4xx se for rejeitar de qualquer jeito. Isso economiza banda em uploads grandes: não faz sentido enviar 200 MB se o servidor vai recusar por falta de um header.

curl -v -H "Expect: 100-continue" \
  -H "Content-Type: application/octet-stream" \
  --data-binary @big-file.bin \
  https://api.example.com/upload

Se você não vir < HTTP/1.1 100 Continue na saída verbosa, provavelmente seu cliente removeu o header ou o servidor não suporta.

101 Switching Protocols

O handshake que transforma uma conexão HTTP em conexão WebSocket ou HTTP/2. O cliente manda Upgrade: websocket, o servidor responde 101 Switching Protocols e, a partir daí, a conexão fala outro protocolo. Você vê isso na aba Network de qualquer app de chat, dashboard ao vivo ou ferramenta de colaboração.

103 Early Hints

Um código relativamente novo (RFC 8297, 2017) que permite ao servidor enviar headers Link com dicas de preload antes da resposta principal estar pronta. O navegador começa a baixar CSS e JS enquanto o servidor ainda está renderizando. Em 2026, Cloudflare, Fastly e Vercel já suportam 103 em produção, sendo a alternativa moderna ao server push do HTTP/2 (que foi descontinuado no Chrome).

HTTP/1.1 103 Early Hints
Link: </styles.css>; rel=preload; as=style
Link: </app.js>; rel=preload; as=script

HTTP/1.1 200 OK
Content-Type: text/html
...

Verificação de antipadrão. Se seu cliente nunca vê códigos 1xx quando deveria, normalmente o problema está num proxy reverso. Versões antigas do nginx removem Expect: 100-continue e 103 Early Hints. Confira a configuração do proxy antes de assumir que o servidor está quebrado.

2xx — Sucesso (além do mero 200)

Devolver 200 OK para tudo é o code-smell mais comum em APIs REST. A família 2xx carrega informação semântica que deixa os clientes mais inteligentes e os caches mais eficientes.

200 OK

O padrão. Um GET devolve o recurso, um PUT devolve o recurso atualizado (ou 204), um PATCH devolve o recurso patchado. Se você não tem motivo para usar um código mais específico, use 200.

201 Created

Um POST que cria um recurso novo deve devolver 201 mais um header Location apontando para o recurso recém-criado. É assim que clientes RESTful descobrem a URL canônica daquilo que acabaram de fazer.

HTTP/1.1 201 Created
Location: /api/users/42
Content-Type: application/json

{"id": 42, "name": "Ada Lovelace"}

202 Accepted

O servidor aceitou a requisição, mas ainda não terminou de processar. Use para trabalho assíncrono: o cliente faz polling, assina um webhook ou consulta um endpoint de status. Combine com um job ID no corpo.

204 No Content

Sucesso, sem corpo. Comum em DELETE (o recurso sumiu, o que devolveria?) e em operações PUT em que o cliente já conhece o novo estado. Navegadores não trocam de página se um envio de formulário devolve 204, o que é útil para ações fire-and-forget em SPAs.

206 Partial Content

Devolvido para range requests: o cliente pediu os bytes 1000-2000 com um header Range: bytes=1000-2000 e o servidor devolveu apenas essa fatia. Streaming de vídeo, downloads retomáveis e sincronização de arquivos via HTTP dependem do 206.

Decisão: 200 vs 201 vs 204 para POST

CenárioCódigoCorpo
POST cria um recurso novo201 CreatedRecurso novo (ou só ID) + Location
POST dispara trabalho assíncrono, resultado não pronto202 AcceptedJob ID, URL de polling
POST é uma ação sem recurso (p. ex. /login)200 OKResultado da ação (token, status)
POST teve sucesso mas a resposta é vazia204 No Content(nenhum)

Se ficar na dúvida entre 200 e 201, pergunte: “o servidor criou um recurso que agora tem URL própria?”. Se sim, 201. Se não, 200.

3xx — Redirecionamento (301 vs 302 vs 307 vs 308)

Redirects são a classe mais mal usada. As diferenças entre 301, 302, 307 e 308 se resumem a três perguntas ortogonais: a mudança é permanente, o método é preservado e a resposta é cacheável.

301 Moved Permanently

O recurso mudou e não volta. Buscadores transferem o link equity para a URL nova. Navegadores e CDNs cacheiam 301 por tempo indeterminado: se você redireciona /old para /new com 301 e depois muda de ideia, usuários com o redirect cacheado vão continuar indo para /new para sempre (ou até limparem o cache).

Historicamente, navegadores podem reescrever o método numa resposta 301 (POST → GET), o que motivou o HTTP/1.1 a introduzir o 308 para corrigir esse comportamento.

302 Found

Redirect temporário. A URL original continua canônica, então buscadores devem seguir indexando a original. Use para roteamento de teste A/B, páginas de manutenção ou fluxos de “faça login para continuar”.

Como o 301, navegadores historicamente reescreviam POST como GET no 302. Se você precisa redirecionar um POST mantendo o POST, use 307.

303 See Other

Sempre reescreve o método para GET. O padrão Post/Redirect/Get: o formulário faz POST em /submit, o servidor devolve 303 com Location: /thank-you e o navegador faz GET /thank-you. Atualizar a página de agradecimento não reenvia o formulário. É exatamente para isso que o 303 foi desenhado.

304 Not Modified

A resposta condicional. O cliente envia If-None-Match: "abc123" (ou If-Modified-Since), o servidor verifica se o recurso mudou e, se não mudou, devolve 304 sem corpo. O navegador usa a cópia em cache. É assim que toda CDN e camada de cache deixa seu site rápido.

307 Temporary Redirect

Como 302, mas o método não pode mudar. POST continua POST, o corpo é preservado. Use quando quiser um redirect temporário em requisição que não é GET.

308 Permanent Redirect

Como 301, mas o método não pode mudar. Escolha moderna e segura para redirects permanentes em APIs que aceitam POST/PUT.

Matriz de decisão: qual código de redirect?

Permanente (cachear sempre)Temporário (não cachear)
Método pode virar GET301 Moved Permanently302 Found
Método precisa permanecer o mesmo308 Permanent Redirect307 Temporary Redirect

Caso especial: se você quer especificamente POST → GET (o padrão Post/Redirect/Get), use 303 See Other.

Para páginas HTML com navegação de navegador, 301 e 302 costumam servir porque GET é GET. Para APIs e formulários, prefira 308 e 307, evitando reescrita inesperada do método.

4xx — Erros do cliente (escolhendo o certo)

4xx quer dizer que o cliente errou em algo. Quanto mais rico for seu vocabulário 4xx, mais fácil sua API fica de usar, porque clientes podem ramificar pelo código em vez de fazer parsing de strings de erro.

400 Bad Request

Erro de sintaxe genérico. JSON malformado, campo obrigatório ausente em nível estrutural, requisição que o servidor nem consegue parsear. Se a requisição parseia mas falha numa validação de negócio, prefira 422.

401 Unauthorized vs 403 Forbidden

O par mais confundido do HTTP. A divisão é simples assim que você enxerga:

  • 401 Unauthorized: a requisição não tem autenticação válida. O servidor não sabe quem você é. Reenviar as credenciais (ou renovar o token) pode resolver. A resposta deve incluir um header WWW-Authenticate conforme a RFC 9110 §15.5.2.
  • 403 Forbidden: o servidor sabe quem você é e mesmo assim recusa. Reenviar a requisição não vai adiantar. Você precisa de outras credenciais ou outras permissões.
Você vêO que isso significa
401 com WWW-Authenticate: BearerSem token, token expirado ou token inválido
403 depois de login bem-sucedidoLogado, mas este usuário não pode acessar este recurso
401 depois de login bem-sucedidoBug: você provavelmente quer 403

Antipadrão: 403 disfarçado de 404. Alguns sites devolvem 403 quando um usuário não autenticado pede /admin/dashboard. Isso vaza a existência de /admin/dashboard. O GitHub resolve isso devolvendo 404 para repositórios privados dos quais você não é membro: sob seu ponto de vista, o recurso “não existe”. Isso é uma escolha deliberada de ocultação de informação, não um bug.

404 Not Found vs 410 Gone

Ambos dizem “este recurso não está aqui”. A diferença é a permanência e o SEO.

  • 404 Not Found: pode existir, pode não, pode voltar. Buscadores continuam checando.
  • 410 Gone: existia, foi removido propositalmente, não vai voltar. Buscadores tiram do índice muito mais rápido.

Se você apaga uma página de produto e quer que ela saia do índice do Google agora, 410 é a chamada certa. Se a URL está só temporariamente quebrada, 404 está bom.

405 Method Not Allowed

A URL existe, mas não aceita esse método. A resposta deve incluir um header Allow listando os métodos suportados.

HTTP/1.1 405 Method Not Allowed
Allow: GET, HEAD, OPTIONS
Content-Type: application/json

{"error": "POST is not allowed on this endpoint"}

Esquecer o header Allow é a violação de contrato número 1 em APIs REST artesanais.

408 Request Timeout

O cliente começou a enviar uma requisição e ficou em silêncio. O servidor desistiu. Diferente do 504 Gateway Timeout, que trata do upstream, 408 é “você, cliente, demorou demais”.

409 Conflict

A requisição conflita com o estado atual. Uso mais comum: optimistic locking. O cliente envia If-Match: "etag-v3" e o ETag atual do servidor é "etag-v4", então a atualização é rejeitada com 409.

410 Gone

Veja acima: exclusão definitiva. Útil para tirar registros soft-deleted dos índices de busca.

415 Unsupported Media Type

O cliente enviou um corpo que o servidor não entende. Postar XML para uma API só de JSON dá 415. A resposta deve sinalizar quais tipos são aceitos.

422 Unprocessable Content

A requisição parseia bem, mas falha na validação semântica. A RFC 9110 finalmente promoveu este código do WebDAV para a especificação central em 2022. Use 422 para erros de validação:

{
  "error": "validation_failed",
  "details": [
    {"field": "email", "message": "must be a valid email"},
    {"field": "age", "message": "must be at least 13"}
  ]
}

Se sua API ficar em dúvida entre 400 e 422, a regra geral é: 400 para “nem consigo parsear isso”, 422 para “parseei e não faz sentido”.

425 Too Early

Enviado quando o servidor não quer correr o risco de processar uma requisição que pode ser replay de early-data do TLS 1.3. Importa principalmente em CDNs e proxies reversos.

428 Precondition Required

O servidor exige que você envie If-Match ou If-Unmodified-Since para evitar o problema do lost update. Usado em APIs de edição colaborativa.

429 Too Many Requests

Rate limit. A resposta deve incluir Retry-After (em segundos, ou como data HTTP) para que clientes bem-comportados façam backoff.

HTTP/1.1 429 Too Many Requests
Retry-After: 30
Content-Type: application/json

{"error": "rate_limited", "limit": 100, "window": "1m"}

O número é uma referência ao Bradbury. O caso de uso não é ficção: takedowns de DMCA, remoções por direito de ser esquecido (LGPD/GDPR) e geo-blocks por país justificam um 451. A resposta deve incluir um header Link apontando para a autoridade legal que exige o bloqueio, conforme a RFC 7725.

418 I’m a Teapot (o easter egg)

Sim, é real. A RFC 2324 (1º de abril de 1998) e a IETF mantiveram este código no catálogo porque produtos demais o implementaram de brincadeira. Não use 418 numa API de verdade, porque a maioria dos proxies reversos e load balancers vai tratar mal.

Matriz de decisão: qual 4xx?

SituaçãoCódigo
Corpo malformado ou impossível de parsear400
Sem autenticação / token expirado401
Autenticado mas sem permissão403
URL não existe (ou você está escondendo)404
URL existia, removida propositalmente410
Método HTTP errado405 (com Allow)
Content-Type errado415
Conflito de optimistic lock409
Erro de validação (parseia mas não valida)422
Rate limit429 (com Retry-After)
Bloqueio por motivos legais451

5xx — Erros do servidor (o que está realmente quebrado)

5xx é “culpa nossa”. Quem está de plantão se importa muito com qual 5xx o acordou às 3 da manhã, porque o código indica em qual camada começar a investigar.

500 Internal Server Error

O coringa. Quase sempre quer dizer que uma exceção não tratada subiu até o handler padrão do framework. Não conta nada sobre a causa, e por isso log estruturado importa mais aqui do que o status code em si.

501 Not Implemented

O servidor não suporta o método de jeito nenhum. Diferente do 405 (este método não é permitido nesta URL), 501 diz “este servidor não tem ideia do que é PROPFIND”. Raro em APIs REST.

502 Bad Gateway

Um proxy reverso ou load balancer recebeu uma resposta inválida do upstream. O upstream respondeu, mas com lixo: protocolo errado, headers malformados, conexão derrubada no meio da resposta. Se você vê 502 vindo da sua CDN, o origem provavelmente está crashando ou devolvendo corpos truncados.

503 Service Unavailable

O servidor não está atendendo de propósito agora. Use em janelas de manutenção ou como resposta de sobrecarga controlada. Deve incluir Retry-After.

504 Gateway Timeout

O proxy reverso esperou o upstream e o upstream nunca respondeu a tempo. O upstream está lento ou travado, diferente do 502, em que o upstream respondeu com lixo.

502 vs 504: o diagnóstico no plantão

Você vêPrimeira coisa a checar
502 Bad GatewayUpstream respondendo com dados inválidos: verifique logs da origem em busca de crashes, respostas malformadas, descasamento de protocolo
504 Gateway TimeoutUpstream travando: verifique CPU da origem, queries de banco, chamadas a APIs downstream e o proxy_read_timeout do proxy

Confusão comum: uma query de banco que leva 60 segundos vai aparecer como 504 se seu proxy tem timeout de 30 segundos, mas como 500 se o servidor de aplicação tem timeout de 90 segundos e levanta uma exceção. Mesma causa raiz, código diferente, linha de log diferente; treine seus dashboards para mostrar os dois.

507 Insufficient Storage

Específico de WebDAV. Disco cheio no servidor. Se você vê isso vindo de uma API que não é WebDAV, alguém está sobrecarregando o significado.

508 Loop Detected

Recursão infinita em operações PROPFIND do WebDAV. Muito raro.

511 Network Authentication Required

Códigos de captive portal: o WiFi de hotel ou aeroporto manda 511 para avisar ao seu navegador “primeiro você precisa logar no portal”. A resposta inclui um Location apontando para a página do portal.

Matriz de troubleshooting: qual camada checar primeiro

CódigoAppProxyDBRede
500SimTalvez (erro de DB não capturado)
502Sim (upstream malformado)Talvez (TCP reset)
503Sim (flag de manutenção)Sim (rejeição por rate limit)
504Sim (handler lento)Sim (config de timeout)Sim (query lenta)Sim (DNS, perda de pacote)

Antipadrões comuns com códigos HTTP

Estes cinco erros respondem pela maior parte do código ruim que reviso.

1. Embrulhar erros em 200 OK

HTTP/1.1 200 OK
{"success": false, "error": "user_not_found"}

Toda ferramenta de monitoramento, CDN e cache passa a achar que a requisição teve sucesso. Lógica de retry quebra. Load balancers cientes de status code roteiam tráfego ruim para backends “saudáveis”. Esse padrão veio do JSON-RPC e foi herdado pelo GraphQL (o GraphQL faz isso porque sucessos parciais precisam de relato de erro por campo, o que é justo). REST não tem desculpa: use 4xx para erros do cliente, 5xx para erros do servidor e ponha o detalhe estruturado no corpo.

2. Misturar 401 e 403

Se seu 401 e 403 não forem consistentes, atacantes conseguem sondar sua API para descobrir que recursos existem. Adote uma política: ou devolva 404 para “você não pode ver isso” (a abordagem do GitHub para repositórios privados) ou devolva 403 sempre. Inconsistência vaza informação.

3. Esconder 403 atrás de 404

Às vezes correto, muitas vezes bug. O GitHub devolver 404 para repositórios privados é deliberado, porque a própria existência do repositório é informação sensível. Mas se sua API devolve 404 para “esta conta de usuário foi suspensa”, agora usuários legítimos não conseguem distinguir se digitaram o nome errado ou se foram suspensos. Documente sua política de forma explícita e aplique de modo consistente.

4. Usar 500 como catch padrão

Frameworks facilitam isso, e o problema é justamente esse. Toda exceção não capturada vira 500 e seu alerta deixa de distinguir “banco fora do ar” de “usuário passou um UUID malformado”. Capture erros de validação e devolva 400 ou 422. Capture NotFound do seu ORM e devolva 404. Reserve o 500 para falhas realmente inesperadas, e quando for usar, registre um request ID para correlacionar.

5. Cadeias longas de redirect

Cada hop custa um round trip. Se /old/intermediate/canonical, isso são duas resoluções DNS extras e dois handshakes TCP extras (no pior caso). O Google rebaixa especificamente a prioridade de crawl em cadeias maiores que 3 hops, e navegadores limitam a cadeia em torno de 20 para evitar loops. Colapse as cadeias na origem, na config da CDN ou no mapa de redirects da aplicação.

Códigos HTTP e SEO

Buscadores tratam códigos de status como sinais autoritativos sobre manter, descartar ou transferir uma URL. Errar isso e o ranking se mexe.

301 Moved Permanently transfere PageRank: o Google trata a URL nova como destino canônico de todos os sinais que apontavam para a antiga. 302 Found não transfere link equity (ou transfere lentamente, dependendo das heurísticas do Google). Se você renomeou uma URL para sempre, use 301. Se redireciona um visitante para /login, use 302.

404 vs 410 vs Soft 404

O Google distingue três estados de “ausente”:

  • 404 Not Found: o Google recheca periodicamente e mantém a URL no índice por um tempo.
  • 410 Gone: o Google retira a URL mais rápido, em geral num único ciclo de crawl.
  • Soft 404: termo do Google para uma página que devolve 200 OK mas mostra mensagem de “não encontrado”. O Google detecta isso por padrões de conteúdo e trata como 404 mesmo assim, mas você desperdiçou um crawl e possivelmente diluiu seu conteúdo real.

Se você está limpando um índice antigo, devolva 410 real para URLs removidas em definitivo.

5xx e crawl budget

O crawler do Google reduz a taxa quando um site devolve 5xx de forma persistente. O relatório de Crawl Stats no Search Console mostra isso: um pico sustentado de 5xx pode derrubar seu crawl budget por dias, o que significa que páginas novas demoram mais para indexar. Trate a taxa de 5xx como métrica de SEO, não só de confiabilidade.

200 OK que na verdade está quebrado

Devolver 200 OK com uma página de erro (o antipadrão soft-404) é o pior cenário para SEO. O Google indexa a mensagem de erro, ranqueia para nada e devagar percebe que a página está quebrada. Sempre devolva o status code correto a partir do servidor, mesmo que sua SPA renderize uma UI de erro amigável.

Como inspecionar códigos HTTP (ferramental)

Você não conserta o que não enxerga. Todo desenvolvedor em atividade deveria dominar pelo menos três destas opções.

Painel Network do DevTools

Chrome, Firefox e Safari mostram uma coluna Status na aba Network. Clique com botão direito no cabeçalho da coluna para adicionar Status Text se não estiver visível. Truques úteis:

  • Preserve log: mantém entradas entre navegações para você ver a cadeia completa de redirects.
  • Filtro por status: digite status-code:5xx (Chrome) para ver só erros de servidor.
  • Replay XHR: clique direito em qualquer requisição → Replay XHR para reexecutar sem recarregar a página.

Para redirects, expanda a requisição e veja cada hop e o código de status em cada etapa.

curl (a resposta universal)

O curl mostra tudo. Três padrões resolvem 90% do debug:

# Just the status code
curl -o /dev/null -s -w "%{http_code}\n" https://api.example.com/users/1

# Headers only (HEAD request, follow redirects)
curl -I -L https://example.com

# Full verbose with request and response headers
curl -v https://api.example.com/users/1

Quando você está montando URLs de teste com caracteres especiais nas query strings, use --data-urlencode para o curl tratar a codificação por você, ou cole a URL no nosso Decodificador e Codificador de URL para conferir quais bytes vão de fato pela rede.

# curl encodes the query value for you
curl -G "https://api.example.com/search" \
  --data-urlencode "q=hello world & friends"

# Sends: GET /search?q=hello%20world%20%26%20friends

JavaScript fetch

A propriedade Response.status traz o código inteiro. Response.ok é true para qualquer 2xx.

const res = await fetch('https://api.example.com/users/1');

console.log(res.status);      // 200
console.log(res.statusText);  // "OK"
console.log(res.ok);          // true

if (!res.ok) {
  if (res.status === 401) {
    // refresh token and retry
  } else if (res.status === 429) {
    const retryAfter = Number(res.headers.get('Retry-After')) || 1;
    await new Promise(r => setTimeout(r, retryAfter * 1000));
  } else if (res.status >= 500) {
    throw new Error(`Server error: ${res.status}`);
  }
}

No axios, a mesma lógica vive nos interceptors:

import axios from 'axios';

axios.interceptors.response.use(
  response => response,
  error => {
    const status = error.response?.status;
    if (status === 401) {
      // redirect to login
    }
    return Promise.reject(error);
  }
);

Python requests

import requests

r = requests.get('https://api.example.com/users/1')

print(r.status_code)  # 200
print(r.reason)       # 'OK'

# Raises requests.exceptions.HTTPError for 4xx/5xx
r.raise_for_status()

# Manual handling
if r.status_code == 429:
    retry_after = int(r.headers.get('Retry-After', '1'))
    time.sleep(retry_after)
elif 500 <= r.status_code < 600:
    raise RuntimeError(f'Server error: {r.status_code}')

raise_for_status() é o idioma do Python para “falhe alto em 4xx/5xx”. Use em scripts onde você prefere exceções sobre erros em vez de ramificar pelo status_code.

Postman e Bruno

Os dois deixam você asseverar sobre códigos de status num script de teste:

// Postman/Bruno test script
pm.test("Status is 201", () => {
  pm.response.to.have.status(201);
});

pm.test("Has Location header", () => {
  pm.expect(pm.response.headers.get('Location')).to.match(/^\/users\/\d+$/);
});

Rode esses testes contra o staging em CI para pegar violações de contrato antes da produção.

FAQ

Qual é a diferença entre 401 e 403?

401 Unauthorized significa que o servidor não sabe quem você é: suas credenciais estão ausentes, expiradas ou inválidas. 403 Forbidden significa que o servidor sabe quem você é e mesmo assim recusa. Se enviar credenciais diferentes pode resolver, use 401. Se não pode, use 403.

Quando usar 301 ou 302?

Use 301 quando a mudança é permanente: a URL antiga não vai voltar e você quer que buscadores transfiram o link equity para a nova URL. Use 302 para redirects temporários em que a URL original ainda é canônica (fluxos de login, testes A/B, páginas de manutenção). Em APIs, prefira 308 e 307 porque preservam o método da requisição.

O que significa o erro 502 Bad Gateway?

502 significa que um proxy reverso ou load balancer recebeu uma resposta inválida do servidor upstream. O upstream respondeu, mas com lixo: protocolo errado, headers malformados ou conexão derrubada. É diferente do 504 Gateway Timeout, em que o upstream não respondeu de jeito nenhum. Primeiro lugar a checar: logs do servidor de origem em busca de crashes ou respostas truncadas.

O que é um “soft 404”?

Um “soft 404” é uma página que devolve 200 OK mas, na prática, exibe uma mensagem de “não encontrado”. O Google detecta esses casos por heurística e trata como 404 mesmo assim. Eles desperdiçam crawl budget e podem diluir seu conteúdo real. Sempre devolva códigos 404 ou 410 reais a partir do servidor, mesmo que sua SPA renderize uma UI de erro amigável.

Quando usar 422 em vez de 400?

Use 400 Bad Request quando o servidor não consegue nem parsear a requisição: JSON malformado, campos estruturais ausentes, erros de sintaxe. Use 422 Unprocessable Content quando a requisição parseia bem mas falha na validação de negócio: formato de e-mail inválido, valor fora da faixa, campos semanticamente inconsistentes. Em resumo: 400 para sintaxe, 422 para semântica.

Como responder a um 429 Too Many Requests?

Leia o header Retry-After (um número de segundos ou uma data HTTP) e faça backoff por pelo menos esse tempo antes de tentar de novo. Se Retry-After estiver ausente, use backoff exponencial com jitter começando em torno de 1 segundo. Nunca tente de novo imediatamente, porque é assim que você acaba banido.

Códigos informativos 1xx ainda são usados em 2026?

Sim, mas a maioria é invisível para o código de aplicação. 100 Continue e 101 Switching Protocols são recursos básicos do HTTP/1.1. 103 Early Hints é cada vez mais usado por Cloudflare, Fastly e Vercel para empurrar dicas de preload antes da resposta principal, o que melhora o Largest Contentful Paint de forma perceptível. A maioria das bibliotecas HTTP colapsa 1xx na resposta final, então você costuma ver esses códigos só no DevTools ou no curl -v.

O 418 “I’m a teapot” é um código real?

Sim, surpreendentemente. A RFC 2324 foi uma piada de 1º de abril de 1998, mas produtos suficientes a implementaram para a IETF manter o código nos registros pela RFC 7168. Não use 418 em produção: muitos proxies reversos e load balancers não tratam direito, e ele não serve a propósito real fora da piada.

Artigos relacionados

Ver todos os artigos