403 Forbidden: how to find out who's blocking the request

A 403 can come from a CDN, a firewall, the web server or your app. How to tell which, and how to fix file permissions, deny rules and over-eager bot protection.

· 4 min read · By the Spot Downtime team

403 Forbidden means the server understood the request and refuses to answer it. Logging in again won't help (that's 401). Something decided this request, from this client, isn't allowed. Your job is to find out which layer made that decision.

Find out who said no

A 403 can come from four very different places. The response itself usually gives it away:

  • A CDN or WAF (Cloudflare, AWS WAF, Akamai). The page is branded, has a ray or reference ID, and the request never reached your server, so it's missing from your logs.
  • The web server (nginx, Apache). A plain page like 403 Forbidden nginx, and an entry in its error log.
  • Your application. Your own error page or a JSON error such as insufficient_scope.
  • Storage like S3 or Google Cloud Storage returning AccessDenied XML.
HTTP headers checkerCheck the response headers: a server: cloudflare or cf-ray header means the CDN answered, not your server.

Web server causes

File permissions

The web server's user can't read the file, or can't enter a folder on the way to it. Files usually need to be readable (644) and every parent directory executable (755) by that user:

bash
namei -l /var/www/site/public/index.html   # permissions of every folder on the path
sudo tail -n 20 /var/log/nginx/error.log    # look for "Permission denied" (13)

No index file, and listing disabled

Requesting a folder with no index.html or index.php, when directory listing is off, gives 403 rather than 404. Common after a deploy that put files one folder too deep.

Deny rules

An .htaccess rule, a deny all in nginx, or an IP allowlist that doesn't include the visitor. Check rules added recently, especially ones that match by IP or country.

Firewall and bot protection causes

WAFs block requests that look automated or malicious: unusual user agents, requests from data centers, too many requests, or a body that trips a rule (an SQL keyword in a blog comment is a classic). Your firewall's event log names the rule that matched. Fix the rule, or add an exception for that path, rather than turning protection off.

403 only for your monitoring?

Bot protection often blocks uptime checks while real browsers get through, which makes a healthy site look down. Allow your monitoring service instead of loosening protection for everyone. The firewall allowlist guide shows how to let Spot Downtime through with a secret header or its IP addresses.

Cloud storage causes

S3 returns 403 both for “not allowed” and, when the caller can't list the bucket, for files that don't exist. Check the bucket policy, whether public access is blocked, and that the object key is spelled exactly right, including case.

Keep an eye on it

A 403 on your home page after a deploy or a firewall change is an outage for everyone it blocks. Spot Downtime treats 4xx responses as down and records the code, so a too-eager WAF rule shows up as an alert, not as a quiet drop in sign-ups.

Keep reading