403 Forbidden
The server understood the request and is refusing it - authentication will not help.
What 403 means
403 means the server knows who you are and you still may not do this. Unlike 401, re-authenticating changes nothing: the credentials are valid and the answer is still no. That is the operational significance of the distinction - a client should not refresh a token and retry on a 403.
It covers genuine authorisation failures - insufficient role or scope, an object belonging to another tenant, an operation disabled for this account - and also a range of infrastructure refusals: a WAF rule, an IP allowlist, a geographic restriction, or an expired signed URL.
There is a security consideration in choosing between 403 and 404. A 403 confirms the resource exists, which leaks information about what is present. APIs handling sensitive resources often return 404 for anything the caller may not access, so that presence itself is not disclosed.
Where the refusal is not obviously about permissions, saying which reason applies in the body saves a great deal of debugging - 'insufficient scope' and 'blocked by WAF' look identical from outside.
Common causes of a 403
- The authenticated user lacks the required role or permission.
- An OAuth token missing the necessary scope for this operation.
- Attempting to access a resource belonging to a different tenant or organisation.
- A WAF or bot-protection rule matching the request.
- An IP allowlist or geographic restriction.
- A signed URL whose expiry has passed, or whose signature does not match.
- S3 or similar object storage where the bucket policy denies the action - S3 also returns 403 for a missing object when ListBucket is not permitted.
How to fix a 403
- Check the token's scopes and the user's roles against what the endpoint requires.
- Confirm the resource belongs to the authenticated tenant.
- Look at WAF and CDN logs - infrastructure 403s never reach your application logs.
- For signed URLs, check the expiry and that the signature covers the parameters actually sent.
- Return a reason in the body: 'insufficient scope' and 'blocked by WAF' are indistinguishable otherwise.
Should a client retry?
Authentication is not the problem, so retrying - with or without a fresh token - cannot succeed. Something has to change server-side.
FAQ
- What is the difference between 403 and 404?
- 403 says the resource exists and you may not have it; 404 says nothing about existence. Because 403 confirms presence, APIs handling sensitive resources often return 404 instead, so that an attacker cannot enumerate what exists.
- Should a client retry a 403?
- No. The credentials are valid and the answer is still no, so nothing about retrying - including refreshing the token - can change the outcome.
- Why does S3 return 403 for a file that does not exist?
- Because without s3:ListBucket permission, S3 cannot tell you whether the object is missing without revealing bucket contents, so it returns 403 for both cases. Granting ListBucket makes it return 404 for genuinely missing objects.
Often confused with
- 401 Unauthorized Authentication is required and has failed or not been provided - despite the name, this means unauthenticated.
- 404 Not Found The server has no resource at that URL.