Código de status HTTP · Erros do cliente (4xx)
Erro 403 Forbidden
O erro 403 Forbidden significa que o servidor entendeu o pedido e se recusa a atendê-lo, seja você quem for. As causas mais comuns são permissões de arquivo ou pasta no servidor, falta de arquivo index com listagem de diretório desligada, ou uma regra de firewall (WAF, bloqueio de IP, proteção contra bots) recusando o acesso.
| Classe | 4xx, Erros do cliente |
|---|---|
| Definido em | RFC 9110 §15.5.4 |
| Pode ir para o cache por padrão | Só com Cache-Control ou Expires explícitos |
| Pode repetir o pedido | Não com as mesmas credenciais; só com outras ou depois de mudar as permissões |
| Cabeçalhos relevantes | Nenhum específico deste código |
O que significa o 403
A RFC 9110, seção 15.5.4, diz que o servidor entendeu o pedido, mas se recusa a atendê-lo. Se o pedido trouxe credenciais, o servidor as considera insuficientes, e o cliente não deve repetir o pedido com as mesmas credenciais. A recusa também pode não ter nada a ver com login: bloqueio de IP, restrição por país ou uma regra sobre a própria URL geram 403.
A mesma seção permite que o servidor responda 404 no lugar, quando quer esconder que o recurso proibido existe. Por isso um repositório privado no GitHub ou um objeto do S3 que você não pode listar aparece como 404 ou 403, conforme o serviço e as suas permissões.
Muitos 403 nem chegam à aplicação. O nginx devolve 403 quando o pedido cai numa pasta sem arquivo index e com autoindex desligado, ou quando o processo worker não consegue ler o arquivo. Cloudflare, AWS WAF e camadas parecidas devolvem 403 para pedidos que parecem automáticos, e é por isso que uma URL abre no navegador e falha no curl ou num script.
Causas comuns
Se você está visitando o site
- A página é restrita a certas contas, funções ou assinantes, e a sua não está entre elas.
- O seu IP, país ou a saída da VPN está bloqueado pelo site ou pelo firewall dele.
- A proteção contra bots marcou o pedido: navegador incomum, JavaScript desligado ou um script sem cabeçalhos de navegador.
Se você administra o servidor
- Permissões de arquivo: o usuário do servidor web (www-data, nginx) não consegue ler o arquivo ou atravessar uma pasta acima dele. Os valores seguros típicos são 644 para arquivos e 755 para pastas.
- Uma URL de pasta sem index.html ou index.php e com listagem de diretório desligada (no nginx: "directory index of ... is forbidden" no error.log).
- Regras explícitas de bloqueio: deny no nginx, Require all denied no Apache, uma regra no .htaccess ou um plugin de segurança do WordPress bloqueando o caminho ou o seu IP.
- O Amazon S3 devolve 403 AccessDenied quando a política do bucket ou a role IAM não permite a ação, e também para objetos inexistentes quando quem chama não tem s3:ListBucket.
- Proteções do framework: CSRF inválido (o Django responde 403 "CSRF verification failed") ou uma checagem de papel no seu próprio código.
Como resolver
Se você está visitando o site
- Confira se está logado com a conta que deveria ter acesso; se não tiver, peça ao dono para liberar.
- Desligue a VPN ou o proxy e recarregue, caso o IP de saída esteja bloqueado.
- Apague cookies e cache do site e teste outro navegador para descartar uma sessão marcada.
Se você administra o servidor
- Leia primeiro o log de erros do servidor web; nginx e Apache registram o motivo exato (permission denied, directory index forbidden, access forbidden by rule).
- Corrija dono e permissões: arquivos 644, pastas 755, com o usuário de deploy como dono e leitura para o usuário do servidor. Confira todas as pastas acima, não só o arquivo.
- Adicione o arquivo index ou ajuste a diretiva index, e só ligue o autoindex se quiser uma listagem pública.
- No S3, confira a política do bucket, o Block Public Access e a política IAM de quem chama; conceda s3:ListBucket se quiser 404 de verdade para chaves inexistentes.
- Na Cloudflare ou em outro WAF, abra o log de eventos de segurança, ache a regra que disparou para o pedido e crie uma exceção se o tráfego for legítimo.
Como enviar um 403
app.delete('/projects/:id', (req, res) => {
res.status(403).json({ error: 'Only the project owner can delete it' });
});// app/projects/[id]/route.ts
export async function DELETE() {
return Response.json(
{ error: 'Only the project owner can delete it' },
{ status: 403 }
);
}mux.HandleFunc("DELETE /projects/{id}", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusForbidden) // 403
w.Write([]byte(`{"error":"Only the project owner can delete it"}`))
})from fastapi import FastAPI, HTTPException
app = FastAPI()
@app.delete("/projects/{id}")
def delete_project(id: str):
raise HTTPException(status_code=403, detail="Only the project owner can delete it")# Both blocks answer 403 Forbidden
# Never serve the .git folder or dotfiles
location ~ /\. {
deny all;
}
# Allow the admin area from the office network only
location /admin/ {
allow 203.0.113.0/24;
deny all;
}Costuma ser confundido com
- 403 vs 401
- O 401 pede que o cliente se autentique, e um login resolve; o 403 recusa de qualquer jeito, e reenviar as mesmas credenciais não adianta.
- 403 vs 404
- Servidores podem responder 404 em vez de 403 para não confirmar que o recurso proibido existe.
- 403 vs 451
- O 451 é uma recusa por motivo legal, como ordem judicial ou bloqueio geográfico exigido por lei; o 403 não informa o motivo.
Perguntas frequentes
- Qual a diferença entre erro 401 e erro 403?
- O 401 indica que o servidor precisa que você se autentique, e credenciais válidas podem resolver. O 403 indica que o servidor recusa mesmo tendo entendido o pedido, então entrar de novo com a mesma conta não adianta.
- Por que dá erro 403 no curl ou no Python, mas não no navegador?
- Um WAF ou proteção contra bots (Cloudflare, Akamai, AWS WAF) está recusando pedidos que não parecem vir de um navegador: user agent padrão, falta de cabeçalhos Accept ou uma assinatura TLS diferente. Veja se o site oferece uma API e respeite os termos de uso antes de tentar se passar por navegador.
- Como resolver o erro 403 Forbidden no nginx?
- Olhe o /var/log/nginx/error.log. "directory index of ... is forbidden" indica que falta o arquivo index daquela pasta; "permission denied" indica que o usuário do nginx não consegue ler o arquivo ou entrar numa pasta acima. Corrija com chmod 644 nos arquivos, 755 nas pastas, ou crie o arquivo index.
- Por que o WordPress mostra erro 403 Forbidden?
- Na maioria das vezes é um plugin de segurança ou uma regra no .htaccess bloqueando o pedido, permissões erradas depois de uma migração, ou o firewall da hospedagem (ModSecurity) barrando um formulário. Renomear a pasta de plugins por SFTP mostra rápido se o problema é um plugin.
- Por que o S3 devolve 403 para um arquivo que não existe?
- Sem a permissão s3:ListBucket, o S3 não revela se a chave existe, então um objeto inexistente volta como 403 AccessDenied em vez de 404. Conceda ListBucket a quem chama para receber 404 de verdade.
Revisado em por Arielton Oberek.