403 Forbidden
Access denied without any path to authenticate is communicated through the 403 Forbidden status code. The server refuses the request and offers no Authentication scheme to gain access.
Usage
When a 403 Forbidden error arrives, the client does not have sufficient permissions to access the resource. This is a common and general error telling the client the request is not allowed. This status differs from 401 Unauthorized because the error persists even after the client re-authenticates and re-submits the request. The more specific 405 Method Not Allowed status indicates the resource is available but the specific HTTP method is not permitted.
403 vs 401
403 Forbidden answers a request the server understands and refuses on permission grounds, while 401 answers a request arriving without a usable identity. The distinction rests on whether different credentials change anything. A 403 stands for the requester whatever credential the requester supplies, so the server offers no Authentication challenge and the client gains nothing by retrying with a new token.
401 responses carry a WWW-Authenticate header naming an accepted scheme. 403 responses carry no such header, and adding one contradicts the meaning of the status.
The terminology runs against intuition. 403 Forbidden is the authorization outcome, covering permission, and 401 Unauthorized is the authentication outcome, covering identity. The word "unauthorized" sitting on the identity code accounts for most of the confusion between the two.
Typical 403 conditions include a signed-in user reaching an admin-only path, an API key on a plan lacking the feature, a request blocked by an IP or region rule, and a WAF decision. In each, no credential the requester holds changes the outcome, which is what separates them from the 401 cases.
Serving 403 where 401 applies conceals a working path to access, leaving clients with a permanent refusal for a recoverable condition.
Example
The client requests a protected resource and the server responds with 403 Forbidden to indicate the client lacks access. The response body explains the restriction.
Request
GET /tech-news/confidential.pdf HTTP/1.1
Host: www.example.re
Response
HTTP/1.1 403 Forbidden
Content-Type: text/html
Content-Length: 150
<html>
<head>
<title>Access Denied</title>
</head>
<body>
<p>Permission to access this resource is
restricted.</p>
</body>
</html>
How to fix
A 403 Forbidden means the server understood the request but refuses to authorize the action.
Verify file and directory permissions on the server. On Linux, check ownership and permission bits with
ls -la. The web server process (typically running aswww-dataornginx) needs read access to the requested file. Standard permissions:755for directories,644for files. Fix recursively:find /var/www/html -type d -exec chmod 755 {} \; find /var/www/html -type f -exec chmod 644 {} \; chown -R www-data:www-data /var/www/htmlnginx also requires execute permission on every parent directory in the path from
/to the served file.Check
.htaccessor server configuration for deny rules. ApacheRequiredirectives, nginxdenyrules, or similar access controls block specific paths or IP ranges. In Apache, look forRequire all deniedorDeny from allin.htaccessor<Directory>blocks. In nginx, look fordeny all;insidelocationblocks. Review the relevant configuration files and check the error log for the specific deny reason.Confirm the request IP is not blocked. A firewall, web application firewall (WAF), or geo-blocking rule rejects requests from restricted addresses. Check the server's access logs for deny entries. Cloudflare, AWS WAF, and mod_security all produce 403 responses when rules trigger. Review the WAF dashboard or audit log to identify the blocking rule.
Ensure the authenticated user has the required role or scope. Even with valid Authentication, the account needs the correct permission level. Verify role assignments in the application's access control system. API endpoints frequently return 403 when the token lacks required OAuth scopes.
Check directory index settings when requesting a folder. Requesting a directory without a default index file (e.g.,
index.html) returns 403 when directory listing is disabled. Add an index file or enable listing. In nginx:location /files/ { autoindex on; }In Apache, add
Options +Indexesto the directory configuration. Enabling directory listing on production servers poses a security risk.Check SELinux or AppArmor policies. On RHEL/CentOS systems, SELinux denies web server access to files outside expected paths even when Unix permissions allow the read. Run
sestatusto check the SELinux mode and review/var/log/audit/audit.logfordeniedentries. Relabel files withrestorecon -Rv /var/www/htmlor set the correct context withchcon.Inspect SSL/TLS client certificate requirements. Servers configured for mutual TLS return 403 when the client does not present a valid certificate. Check the nginx
ssl_verify_clientdirective or the ApacheSSLVerifyClientdirective.
Code references
.NET
HttpStatusCode.Forbidden
Rust
http::StatusCode::FORBIDDEN
Rails
:forbidden
Go
http.StatusForbidden
Symfony
Response::HTTP_FORBIDDEN
Python3.5+
http.HTTPStatus.FORBIDDEN
Java
java.net.HttpURLConnection.HTTP_FORBIDDEN
Apache HttpComponents Core
org.apache.hc.core5.http.HttpStatus.SC_FORBIDDEN
Angular
@angular/common/http/HttpStatusCode.Forbidden
See also
- RFC 9110: HTTP Semantics
- Google: HTTP status codes and network errors
- 401 Unauthorized
- 404 Not Found
- 405 Method Not Allowed
- Authentication
- HTTP status codes