devkult_
tools29converters34

403 Forbidden

4xx client error

The server understood the request but refuses to allow it.

403 is a refusal. Authentication isn't the problem, or wouldn't help: the server has decided this client may not access this resource. Servers sometimes answer 404 instead, so as not to reveal that the resource exists at all.

Class4xx Client Error
Retry?No — change the request first
Cacheable by defaultNo — only with explicit Cache-Control
Response bodyAllowed
Defined inRFC 9110 §15.5.4 — 403 Forbidden
Example response
HTTP/1.1 403 Forbidden
Content-Type: application/json
Content-Length: 21

{"error":"Forbidden"}

Common causes

  • The signed-in user lacks the role or permission (an admin-only endpoint).
  • File permissions: the web server's user can't read the file or traverse the directory.
  • Directory listing is disabled and there's no index file.
  • A WAF, bot protection or IP allow-list blocked the request (Cloudflare, AWS WAF).
  • A missing or invalid CSRF token on a form POST.
  • Private S3 or cloud storage objects, or a signed URL that has expired.

How to fix it

  1. Check the user's roles against the resource's access rules.
  2. For static files, make files 644 and directories 755, readable by the web server's user.
  3. Add an index.html, or enable directory listing only if you mean to.
  4. If a WAF blocked you, its logs name the rule that matched.

Useful here: 401 vs 403 · chmod 755 · chmod 644

Send a 403 from your server

Express
res.status(403).json({ error: "Forbidden" });
Next.js route handler
return Response.json({ error: "Forbidden" }, { status: 403 });
Flask
return {"error": "Forbidden"}, 403
Go net/http
http.Error(w, "Forbidden", http.StatusForbidden)
nginx
return 403;

Check what a URL returns

Print just the status line from the command line, or check a whole list of URLs at once, with their response headers, in the HTTP Status Checker.

curl -sI https://example.com/your-path | head -n 1

Frequently asked questions

403 vs 401?

401 means 'authenticate first'. 403 means 'you're authenticated, or it doesn't matter, and the answer is still no'. Retrying with the same credentials won't change a 403.

Why does nginx return 403 Forbidden?

Usually file permissions or a missing index file. nginx needs execute permission on every parent directory and read permission on the file: directories 755 and files 644 is the usual fix.

Should private resources return 403 or 404?

404 when revealing the resource exists would leak information — a private repository, another user's document. 403 when its existence is no secret.

Headers used with 403
Related status codes