# HTTP 403 Forbidden — Meaning, Causes & Fixes

> 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.

- Class: 4xx Client Error
- Retry: No — change the request first
- Cacheable by default: no
- Defined in: [RFC 9110 §15.5.4 — 403 Forbidden](https://www.rfc-editor.org/rfc/rfc9110.html#section-15.5.4)

## Example response

```http
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.

## 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;
```

## FAQ

### 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.

## Related status codes

- [401 Unauthorized](https://www.devkult.com/http/401.md)
- [404 Not Found](https://www.devkult.com/http/404.md)
- [451 Unavailable For Legal Reasons](https://www.devkult.com/http/451.md)

Open the interactive page: https://www.devkult.com/http/403