Back to HTTP Status Codes

403 Forbidden 4xx

The server understood the request and identified the client, but refuses to authorize it.

What does 403 mean?

A 403 Forbidden response means the server understood the request and (in most cases) knows who's making it, but refuses to authorize it anyway. Unlike 401, which says "I don't know who you are," a 403 says "I know who you are, and the answer is still no."

Crucially, authenticating again won't help with a 403. If a logged-in user gets a 403, logging out and back in with the same account changes nothing — the permission has to change on the server side, either by granting the account more access or by the request targeting something it's actually allowed to touch.

How a 403 behaves

  • It does not require any specific header (unlike 401's WWW-Authenticate requirement)
  • It's generally not cacheable, though it technically can be in specific scenarios — in practice, treating it as non-cacheable avoids permission-related caching bugs
  • It's safe to retry, but retrying the identical request with the same credentials will produce the same result — only a change in permissions, the resource itself, or the request's target will change the outcome
  • It can be used defensively — some servers return 403 (or even 404) for resources that exist but that the requester shouldn't even be able to confirm the existence of, as a security measure

Common causes

If you're building the API or website:

  • An authorization check (role, permission, ownership) correctly identifies that the user shouldn't access this resource
  • File or directory permissions on the server prevent the web server process from reading a file (a classic Apache/Nginx "403 Forbidden" for static files)
  • IP allowlisting/blocklisting is blocking the request's origin
  • A web application firewall (WAF) or security rule (e.g., on Cloudflare) is blocking the request based on patterns it considers suspicious
  • CORS-related misconfiguration occasionally surfaces as a 403 from certain server setups, even though CORS itself is technically a browser-enforced concept

If you're calling an API:

  • Your account/API key is valid (so you're past 401) but doesn't have permission for this specific action or resource
  • You're trying to access another user's or organization's data that your account isn't a member of
  • Your API key has the wrong scope (e.g., a read-only key being used for a write operation)
  • Rate limiting or abuse-prevention systems are returning 403 instead of 429 in some implementations

If you're a website visitor:

  • You're trying to access an admin area or a page restricted to certain user roles
  • The site owner has deliberately blocked access from your location, IP, or browser
  • A direct file/folder listing is disabled by the server configuration

How to fix it

As an API/website builder:

  • Make sure 403 is only returned when the user is genuinely authenticated but lacks permission — if they're not authenticated at all, return 401 instead
  • Check file/directory permissions on the server for static-asset 403s — this is one of the most common causes of unexpected 403s on shared hosting
  • Review WAF/security rule logs (e.g., Cloudflare's firewall events) if 403s are happening for requests that should be legitimate
  • Consider whether returning 404 instead of 403 is more appropriate for resources where you don't want to confirm existence to unauthorized users

As an API consumer:

  • Confirm your account/API key actually has the permission or scope required for this specific endpoint or action
  • If accessing a shared resource (org, team, project), confirm your account is actually a member with the right role
  • Check whether the API key was generated for a different environment or with restricted scopes
  • If you suspect a WAF is blocking you, check for unusual headers, user agents, or request patterns that might look automated/suspicious

As a website visitor:

  • Confirm you're logged in with an account that should have access (the right account, not just any account)
  • Contact the site owner if you believe you should have access — this isn't something you can fix from the browser
  • If accessing a static file directly (e.g., an image URL), the issue is server-side file permissions, not your browser

401 vs 403 — the classic confusion

401 Unauthorized 403 Forbidden
What it's really about Authentication — "I don't know who you are" Authorization — "I know who you are, but you can't do this"
Typical fix Log in / provide valid credentials Nothing the client can do — permissions need to change server-side
Required header WWW-Authenticate None
Analogy A locked door with no ID shown Showing your ID, but it's not on the guest list

A simple mental model: if logging in (or logging in again) could fix the problem, it's 401. If you're already logged in and the server still won't let you, it's 403.

Real-world examples

GitHub's API uses 403 for several distinct situations — exceeding rate limits in some cases, attempting to access a resource your token doesn't have the OAuth scope for, and accessing private repositories you're authenticated but not authorized to view. Many CDNs and WAFs (Cloudflare among them) also return 403 pages for requests blocked by security rules — these are often the very first 403s developers encounter, frequently when their own automated scripts or bots get flagged as suspicious traffic.

SEO implications

A 403 on a page search engines try to crawl tells them "this exists, but I can't show it to you" — search engines generally won't index 403 pages, similar to how they treat pages requiring login. If pages that should be publicly accessible are returning 403 (often due to an overly aggressive WAF rule or misconfigured permissions), this can silently remove important pages from search results without an obvious error on the site itself — worth checking server logs or a tool that crawls your site as Googlebot would, if pages seem to be missing from search despite being live in a browser.

FAQ

What's the difference between 401 and 403?

401 means the server doesn't know who you are — authentication is missing or invalid, and providing valid credentials can fix it. 403 means the server knows who you are but won't allow this action regardless — re-authenticating with the same account won't change anything.

Can logging out and back in fix a 403?

No, not if you're logging back in with the same account. A 403 means your account doesn't have permission for this action — the fix has to happen server-side (granting permission) or you need a different account that does have the right permission.

Why am I getting a 403 on a static file like an image?

This is almost always a file or directory permission issue on the server, not an application-level authorization check. The web server process doesn't have permission to read the file from disk.

Is a 403 always intentional?

Often, yes — it's the server explicitly saying "no" based on a permission check. But it can also be the unintended result of a misconfigured WAF rule, overly broad IP block, or incorrect file permissions, none of which reflect a deliberate "you specifically are not allowed" decision.

Should APIs return 403 or 404 for resources I'm not allowed to see?

Both approaches are used in practice, and it's a deliberate security tradeoff. Returning 403 confirms the resource exists (but you can't access it). Returning 404 hides even that information, which some APIs prefer for sensitive resources like private repositories or other users' private data.

Fun fact

403 is one of the few status codes whose meaning hasn't changed at all since it was first defined in the original HTTP/1.0 specification in the mid-1990s — "the server understood the request, but refuses to authorize it" reads almost identically today as it did then.

Related Status Codes