Skip to main content
4xx Client Error

403 Forbidden

The client does not have access rights to the content.

Meaning & Description

The 403 Forbidden status code indicates that the server understands the request but refuses to authorize it. Unlike 401 Unauthorized, the client's identity is known to the server, but they lack the necessary permissions or roles to access the requested resource.

Common Causes

  • Insufficient permissions or roles (RBAC)
  • IP blacklisting or WAF rules blocking the request
  • CORS preflight failures preventing cross-origin access
  • Directory index fallback is disabled on the web server

How to fix a 403 error

  1. Check the user's roles and permissions in the database or token claims.
  2. Review WAF or firewall logs to ensure the IP isn't blocked.
  3. Verify CORS configurations if making requests from a browser.
  4. Ensure the requested resource isn't globally locked or private.

Browser & SEO Behaviour

Browser Behavior

Displays the generic 403 Forbidden page or the custom error page returned by the server.

SEO Impact

Search engines will stop indexing the page. It signals that the content is permanently inaccessible to the public crawler.

CDN Behavior

May be cached if appropriate headers are set, but usually bypasses cache since it depends on the authorization state of the user.

Code Examples

Node.js (Express)
app.delete('/api/users/:id', authenticate, (req, res) => {
  if (req.user.role !== 'admin') {
    return res.status(403).json({ error: 'Only admins can delete users.' });
  }
  // Proceed with deletion
});
Python (FastAPI)
from fastapi import FastAPI, Depends, HTTPException

app = FastAPI()

def verify_admin(current_user = Depends(get_current_user)):
    if current_user.role != "admin":
        raise HTTPException(status_code=403, detail="Not enough permissions")
    return current_user

@app.delete("/system/logs")
def delete_logs(admin = Depends(verify_admin)):
    return {"message": "Logs deleted"}
Go (net/http)
func deleteHandler(w http.ResponseWriter, r *http.Request) {
    userRole := getUserRole(r)
    if userRole != "admin" {
        http.Error(w, "Forbidden: insufficient permissions", http.StatusForbidden)
        return
    }
    // Proceed
}
C# (ASP.NET Core)
[HttpDelete("data")]
[Authorize(Roles = "Administrator")]
public IActionResult DeleteData()
{
    // If the user lacks the 'Administrator' role, 
    // ASP.NET Core returns a 403 Forbidden.
    return Ok();
}
curl
curl -i -X GET https://api.example.com/admin/dashboard \
  -H "Authorization: Bearer standard_user_token"

Raw HTTP Response Example

HTTP Response
HTTP/1.1 403 Forbidden
Content-Type: application/json
Content-Length: 61

{
  "error": "You do not have permission to delete this comment"
}

Real-world Examples

AWS S3: Returns 403 when trying to access a private bucket without signed credentials.
Cloudflare: Returns a 403 page when a user triggers a Web Application Firewall (WAF) rule.
GitHub: Returns 403 when a user hits API rate limits or tries to push to a read-only repository.

Frequently Asked Questions

What is the difference between 401 and 403?

401 means you need to log in. 403 means you are logged in, but you aren't allowed to do what you are trying to do.

Why does my web server return 403 on the root URL?

This often happens when directory browsing is disabled and there is no default index file (like index.html or index.php) present in the folder.

How can I fix a 403 error on my website?

Check your file permissions, ensure you have an index file, verify your .htaccess or server config, and ensure your IP is not blocked.

Can a 403 be caused by a firewall?

Yes, Web Application Firewalls (WAFs) frequently return 403 when they detect suspicious traffic or block a specific IP address.

Should I return 404 instead of 403?

If you want to hide the fact that a resource even exists from unauthorized users, returning 404 Not Found is a common security practice.

Did You Know?

AWS S3 explicitly returns a 403 instead of 404 for non-existent objects if the requester doesn't have the `s3:ListBucket` permission, preventing bucket enumeration.

Historically, web servers returned 403 by default when a directory was accessed without an index file.

Developer Tips

  • Consider returning a 404 Not Found instead of a 403 Forbidden for highly sensitive endpoints to prevent attackers from probing your system structure.
  • Always include a clear error message in your 403 response body explaining *why* the action was forbidden (e.g., "Requires admin role").
  • Ensure your WAF or load balancer provides custom 403 error pages rather than generic server blocks, which can confuse real users.

Interview Questions

These are questions you might face in a backend or API design interview that touch on HTTP 403.

When is it appropriate to return a 404 instead of a 403 for unauthorized access?

When you want to prevent information leakage. If acknowledging the existence of a resource poses a security risk, returning 404 hides whether the resource exists or is just restricted.

How do you differentiate between 401 and 403 in a REST API?

Return 401 when the request lacks a valid authentication token. Return 403 when the token is perfectly valid and belongs to a known user, but that user lacks the specific roles or permissions needed.

Can a CORS preflight failure result in a 403?

Yes, if the server evaluates the `Origin` header and decides the domain is not allowed, it will often reject the preflight request with a 403 Forbidden.

Common Interview Mistakes

  • Stating that 403 means the user is not logged in.
  • Failing to mention that 403 is tied to authorization (permissions) rather than authentication (identity).
  • Overlooking the use case where firewalls and CDNs return 403 to block malicious traffic.