HTTP status codes / 4xx — Client errors
403 Forbidden
Authenticated (or known), but not allowed to do this.
What it means
The server understood the request and refuses to authorize it: missing permission/role/scope, IP restrictions, or resource-level rules. Re-authenticating with the same identity will not help — that is the difference from 401.
Common causes
- Token valid but missing scope/role/permission
- Resource-level policy (S3 bucket policy, org rules)
- IP allowlist or geo block
- WAF/bot protection rejecting the request pattern
Reproduce it in cURL
curl -i https://httpbin.org/status/403
Same request, no terminal: paste this into the cURL converter for native code, or straight into ReqPad on your phone.
How to debug it
Verify the token scopes/roles against what the endpoint requires; for cloud APIs check resource policies (e.g. S3 bucket policy) rather than the credentials themselves.
Server-side note: Re-authenticating with the same identity will not help — fix the permission, not the login. Compare token scopes against what the endpoint requires.
The fastest way to pin down a 403 is to reproduce the exact request and inspect what actually went over the wire — status, headers, timing and body, without your app code in the way. That is what an API client is for; ReqPad does it from your phone, with every request saved to history.
Related codes
400 Bad Request · 401 Unauthorized · 402 Payment Required · 404 Not Found · 405 Method Not Allowed · 406 Not Acceptable — or the full reference.
Reproduce that 403 in 10 seconds.
Build the request, send it, read status + headers + timing — on your iPhone. Free to start.