pingrobot

HTTP status codes / 403

403 Forbidden — HTTP Status Code

· 4 min read

Short answer

403 Forbidden means the server understood the request and is refusing to fulfill it. Logging in again with the same credentials will not change the answer. On websites the usual culprits are firewall or bot rules, file permissions, and directories with no index file and listing turned off.

What 403 means

RFC 9110 (Section 15.5.4) defines 403 Forbidden as the server understanding the request but refusing to fulfill it. If credentials were sent, the server considers them insufficient, and the client should not simply retry with the same ones. The RFC also notes that a request can be forbidden for reasons unrelated to credentials, and that a server may answer 404 instead if it prefers to hide that the resource exists.

The key difference from 401: a 401 invites the client to authenticate, while a 403 is a decision. The server either knows who you are and says no, or it is refusing based on something else entirely, such as your IP address or user agent.

When you see it

  • CDNs and WAFs. Cloudflare, AWS WAF and similar services block requests that match firewall rules, bot scores, country blocks or rate rules, and the block usually reaches the client as a 403. Cloudflare's "Access denied" pages are an example.
  • Web servers. nginx and Apache return 403 when they cannot read a file, when a path is a directory with no index file and listing is disabled, or when an allow/deny rule matches.
  • Security plugins. CMS security plugins and modules such as ModSecurity block suspicious requests with 403.
  • Applications. A logged-in user who lacks the required role gets 403 from the app.
  • API gateways. An AWS API Gateway REST API returns 403 with "Missing Authentication Token" when a request hits a path or method that is not defined, which often confuses people expecting a 404.

Common causes

  1. Bot or WAF rules that block unknown user agents, data center IPs or traffic without JavaScript and cookies.
  2. File permissions after a deploy. Files owned by the wrong user, or directories without the execute bit, so the web server user cannot read them.
  3. Missing index file. Requesting /docs/ when there is no index.html there and directory listing is off. nginx logs this as "directory index of ... is forbidden."
  4. IP allowlists that forgot a new office, VPN or monitoring source.
  5. Hotlink protection rejecting requests whose Referer is not your own site.
  6. App authorization working as designed: the user is logged in but not permitted.

How to fix it

Find out which layer said no. A CDN block page looks different from an nginx error page, and the response headers usually reveal the source (for example a server: cloudflare header or a request ID from your WAF). Then check that layer's logs.

For file permissions on a typical Linux host, directories need to be traversable and files readable by the web server user:

find /var/www/site -type d -exec chmod 755 {} \;
find /var/www/site -type f -exec chmod 644 {} \;

For a directory without an index, either add an index file or route the request to your app. In nginx, autoindex is off by default, which is the safe choice; fix the missing index rather than turning listing on:

location / {
    try_files $uri $uri/ /index.html;
}

In Apache, the equivalent safe setting is Options -Indexes, combined with a DirectoryIndex that matches the file you actually deploy.

For WAF blocks, look up the matching event in your firewall log and add a narrow exception, such as a rule that skips bot checks for a known user agent on a specific path, rather than turning protection off.

How to check it

Compare what a browser-like client and a bot-like client receive:

curl -sS -o /dev/null -w "%{http_code}\n" https://example.com/
curl -sS -o /dev/null -w "%{http_code}\n" \
  -A "PingRobot/1.0 (+https://pingrobot.io/bot)" https://example.com/

If the second command returns 403 and the first does not, a user-agent-based rule is responsible. Add -i to see which server or CDN produced the response.

What it means for uptime monitoring

PingRobot's checker sends a GET with the user agent PingRobot/1.0 (+https://pingrobot.io/bot), follows redirects, and counts the final response as up only if its status is 200 to 399. Any 403 is reported as down.

A 403 is the classic case where you need to decide between a real outage and a misconfigured monitor:

  • Misconfigured monitor. The site works for people, but bot protection blocks the checker. PingRobot's checks run on Cloudflare's network rather than from a fixed list of IP addresses, so allowlist the user agent in your WAF or bot settings instead of IPs. The PingRobot bot page explains what the checker sends.
  • Real outage. Every client gets 403 after a deploy, a permission change or a new firewall rule. Visitors are locked out, and the alert is doing its job.

Running the two curl commands above settles which case you are in.

Start monitoring free — 10 monitors, no credit card.

Frequently asked questions

Why do I get 403 in my monitor but the site loads fine in my browser?

Firewalls and bot protection often treat automated clients differently from browsers. A rule that blocks non-browser user agents, data center IP ranges or requests without cookies will refuse the monitor while letting you through.

Can a 403 hide a page that exists?

Yes, and the opposite as well. RFC 9110 allows a server to answer 404 instead of 403 when it does not want to reveal that a forbidden resource exists, which is why some private pages look missing rather than blocked.

Does a 403 hurt SEO?

If search engine crawlers get 403 on pages you want indexed, those pages will not be indexed and may drop out over time. Check your WAF and bot rules against crawler traffic in your server logs.