errors.x7.al › HTTP status codes

403 Forbidden

403 Forbidden is an HTTP status code that tells the client the server understood the request but will not carry it out. If 401 asks "identify yourself", 403 says "I know who you are — and you still may not do this". The rule that blocked you may be file permissions, a server configuration directive, an IP-based filter, or an application-level access check.

Advertisement

What it means

A 403 is an authorisation answer, not an authentication one: the request was valid and the server processed it, but the resource is off-limits. Servers return it in three broad situations. First, the resource exists but the server is configured to deny access — a directory listing that has been switched off, or a file blocked by a rule. Second, the client authenticated successfully but the account lacks the required role or permission. Third, a security layer such as a web application firewall, geo-block, or hotlink protection rejected the request before the application ever saw it.

The difference from 401 is the usual source of confusion, and it is worth settling in your head. 401 Unauthorized is a slightly misleading name; it really means unauthenticated, and it arrives with a WWW-Authenticate header inviting the client to supply credentials. A 403 carries no such invitation, because supplying credentials again would not help — any credentials that were present were simply not enough. When you see a 401, log in. When you see a 403, check permissions and rules instead.

One subtlety: many sites deliberately return 403 where a 404 might reveal that a resource exists, which can make a 403 look like a missing page. If a URL you expect to work returns 403 from a site you do not administer, it may be an intentional block rather than a bug you can fix from your side.

Common causes

  • File or directory permissions are wrong — the web server user cannot read the file, or a directory is missing its execute/search bit.
  • Directory listing is disabled and there is no index file, so the server refuses to show the folder contents.
  • A web application firewall, IP allow or deny list, or geo-block is rejecting the request.
  • Hotlink protection, a CORS policy, or a required header or token is missing, so the application denies the call.
  • The signed-in account lacks the role, group, or ownership needed for that page or API endpoint.

How to fix it

  1. Confirm it really is a 403. Check the response status directly instead of trusting the page text, because some sites disguise other errors as a 403:
    curl -I https://example.com/private/
    A 403 Forbidden line confirms the server chose to refuse the request.
  2. If you run the server, fix file permissions. The web server process must be able to read files and traverse directories. For a typical Nginx or Apache setup on Linux:
    sudo chown -R www-data:www-data /srv/www/example
    find /srv/www/example -type d -exec chmod 755 {} \;
    find /srv/www/example -type f -exec chmod 644 {} \;
  3. Provide an index file. If the request targets a folder, add an index.html or index.php, or consciously enable directory listing if a listing is genuinely what you want.
  4. Review the access rules. Inspect the server configuration and any security plugin or firewall for deny rules, allow-lists, or geo restrictions that match your IP or the request path.
  5. Check the account's role. If the application returns 403 for a logged-in user, grant the missing permission or group membership, then verify the session is not stale by signing out and in again.
Advertisement

How to prevent it

Prefer explicit access rules over accidental ones. Test after every permission or configuration change, and keep a staging copy that mirrors production so you catch a bad rule before your users do. Never loosen permissions globally just to make the error disappear — grant the narrowest right that gets the job done, and record what you changed.

Log 403 responses together with the reason, so you can tell a genuine attack from a misconfiguration at a glance. Where hiding the resource matters, return a not-found response instead so you do not confirm that a protected file exists. A little structure here turns a frustrating "access denied" into a rule you can name and change.

Advertisement