Códigos de Status HTTP: O Que Seu Servidor Está Realmente Dizendo ao Cliente
Toda resposta HTTP inclui um código de status de três dígitos. Acerte-os e sua API é intuitiva. Erre-os e os desenvolvedores passam horas debugando por que o cliente faz retry em um 200 que deveria ser 400.
As Cinco Classes
| Faixa | Categoria | Significado |
|---|
| 1xx | Informacional | Requisição recebida, continuando |
| 2xx | Sucesso | Requisição aceita e processada |
| 3xx | Redirecionamento | Cliente deve tomar ação adicional |
| 4xx | Erro do Cliente | Requisição tem um problema |
| 5xx | Erro do Servidor | Servidor falhou ao cumprir requisição válida |
Códigos de Sucesso (2xx)
| Código | Nome | Quando Usar |
|---|
| 200 | OK | GET bem-sucedido, PUT/PATCH atualizou com sucesso |
| 201 | Created | POST criou um novo recurso. Inclua header Location com a URL do novo recurso. |
| 202 | Accepted | Requisição aceita para processamento assíncrono (ex: job na fila). Ainda não concluído. |
| 204 | No Content | DELETE bem-sucedido, nada a retornar. Também bom para PUT sem corpo de resposta. |
// Exemplos Express.js
app.post('/users', (req, res) => {
const user = createUser(req.body);
res.status(201).json(user);
});
app.delete('/users/:id', (req, res) => {
deleteUser(req.params.id);
res.status(204).send();
});
app.post('/reports', (req, res) => {
queueReportGeneration(req.body);
res.status(202).json({ message: 'Relatório sendo gerado' });
});
Códigos de Redirecionamento (3xx)
| Código | Nome | Quando Usar |
|---|
| 301 | Moved Permanently | URL do recurso mudou permanentemente. Browsers cacheiam. Use para migrações de domínio. |
| 302 | Found | Redirect temporário. Browser usa GET para o redirect (mesmo se original era POST). |
| 304 | Not Modified | GET condicional — recurso não mudou desde a versão cacheada. |
| 307 | Temporary Redirect | Como 302, mas preserva o método HTTP. POST continua POST. |
| 308 | Permanent Redirect | Como 301, mas preserva o método HTTP. |
Erro comum: Usar 302 quando deveria ser 301. Se a mudança de URL é permanente (mudou para novo domínio, alterou estrutura de URL), use 301 para que buscadores atualizem o índice.
Códigos de Erro do Cliente (4xx)
| Código | Nome | Quando Usar |
|---|
| 400 | Bad Request | JSON malformado, campos obrigatórios faltando, tipos de dados inválidos |
| 401 | Unauthorized | Sem autenticação ou token inválido. Nome enganoso — significa "não autenticado". |
| 403 | Forbidden | Autenticado mas sem permissão. O usuário é conhecido, mas não pode acessar este recurso. |
| 404 | Not Found | Recurso não existe nesta URL. |
| 405 | Method Not Allowed | Endpoint existe, mas não para este método HTTP (ex: POST em endpoint só GET). |
| 409 | Conflict | Conflita com estado atual — email duplicado, versão incompatível, edição concorrente. |
| 422 | Unprocessable Entity | JSON é válido, mas dados não passam na validação (ex: formato de email errado). |
| 429 | Too Many Requests | Rate limited. Inclua header Retry-After. |
// 400 vs 422 — ambos são válidos, escolha uma convenção
// 400: requisição é estruturalmente errada (JSON malformado)
// 422: requisição é estruturalmente correta, mas dados são inválidos
app.post('/users', (req, res) => {
if (!req.body.email) {
return res.status(422).json({
error: 'Validação falhou',
details: [{ field: 'email', message: 'Email é obrigatório' }]
});
}
});
Códigos de Erro do Servidor (5xx)
| Código | Nome | Quando Usar |
|---|
| 500 | Internal Server Error | Genérico "algo quebrou." Não vaze stack traces para clientes. |
| 502 | Bad Gateway | Proxy reverso (Nginx) não conseguiu conectar ao servidor upstream (seu app crashou). |
| 503 | Service Unavailable | Servidor temporariamente fora — manutenção, sobrecarregado. Inclua Retry-After. |
| 504 | Gateway Timeout | Proxy reverso deu timeout esperando seu app responder. |
Princípio chave: 4xx significa que o cliente precisa corrigir algo. 5xx significa que o servidor precisa corrigir algo. Se o cliente nunca pode ter sucesso mudando a requisição, é um 5xx.
Árvore de Decisão
A requisição é válida?
├── Não → É um problema estrutural?
│ ├── Sim → 400 Bad Request
│ └── Não → 422 Unprocessable Entity
├── Sim → O usuário está autenticado?
│ ├── Não → 401 Unauthorized
│ └── Sim → O usuário está autorizado?
│ ├── Não → 403 Forbidden
│ └── Sim → O recurso existe?
│ ├── Não → 404 Not Found
│ └── Sim → Foi processado com sucesso?
│ ├── Sim → 200/201/204
│ └── Não → 500 Internal Server Error
Referência rápida: Códigos de Status HTTP — tabela pesquisável com descrições, categorias e exemplos para cada código.