/ โ† HTTP Error Fixes / 403 Forbidden
In this guide
  1. What a 403 actually tells you
  2. Finding the layer that refused
  3. Permissions and ownership
  4. Configuration rules that refuse requests
  5. Firewalls, bot protection and crawlers
  6. The fix, step by step
  7. Platform notes
  8. Keeping 403s from coming back
  9. Questions and answers

What a 403 actually tells you

A 403 is a decision, not a crash. The server received the request, knew what was being asked for and chose not to serve it. That makes it different from its neighbours:

CodeWhat it saysWhat the visitor can do
401 UnauthorizedYou need to log in first. The response should ask for credentials.Sign in and try again.
403 ForbiddenI know what you want and I will not give it to you, even if you log in.Nothing, unless the site owner changes a rule.
404 Not FoundThere is nothing here, or I am not telling you whether there is.Check the address.
429 Too Many RequestsSlow down; you have sent too many requests.Wait and retry later.

Because a 403 is a deliberate refusal, the fix is always to find the rule or setting that made the decision. Almost every 403 comes from one of five layers, and each has its own tell-tale sign:

  1. The file system. The web server process is not allowed to read the file or enter the folder. Every file under that folder usually fails the same way.
  2. The web server configuration. A Require, Deny or deny directive, or a folder with no index file and directory listing turned off.
  3. The application. WordPress, Laravel or a similar app returns 403 itself, often for a failed security token, a blocked user role or a plugin rule.
  4. A web application firewall. ModSecurity, Imunify360, Wordfence or similar rules match something in the request, such as a query string or user agent.
  5. The CDN or edge. Cloudflare, a load balancer or a hosting firewall blocks the request before it reaches your server at all.

Working from the outside in, starting with the CDN and ending with the file system, is quicker than guessing, because the outer layers leave obvious fingerprints in the response.

Finding the layer that refused

Start with the response itself. Request the failing URL from a terminal and look at the headers and the body, not just the status code.

curl -sI https://www.example.co.uk/brochure/price-list.pdf
curl -s https://www.example.co.uk/brochure/price-list.pdf | head -30

Then check whether the refusal depends on who is asking. Many 403s in an audit only happen to automated clients.

# As a normal browser
curl -s -o /dev/null -w "%{http_code}\n" -A "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" https://www.example.co.uk/services/
# As a bare script
curl -s -o /dev/null -w "%{http_code}\n" https://www.example.co.uk/services/
# Claiming to be Googlebot
curl -s -o /dev/null -w "%{http_code}\n" -A "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)" https://www.example.co.uk/services/

If the browser string gets 200 and the others get 403, a bot rule is responsible. Note that a request claiming to be Googlebot from your own machine is often blocked on purpose, because good firewalls verify that Googlebot really comes from Google. That is correct behaviour, so test from the crawler's point of view with the URL Inspection tool in Search Console instead.

Log lines worth recognising

Log messageMeaning
AH01630: client denied by server configurationAn Apache Require or older Deny from rule refused the request.
(13)Permission denied with AH00132 or AH00035Apache could not read the file or search a parent folder.
pcfg_openfile: unable to check htaccess fileApache could not read an .htaccess file, usually because of folder permissions.
AH01276: Cannot serve directory ... No matching DirectoryIndexA folder was requested, there is no index file, and listing is off.
directory index of "/var/www/..." is forbiddenThe nginx version of the same problem.
open() "..." failed (13: Permission denied)nginx cannot read the file.
access forbidden by ruleAn nginx deny directive matched.
ModSecurity: Access denied with code 403A ModSecurity rule matched. The line includes the rule id.

If the web server log has no entry at all for the request, it never reached the server and the block is upstream, at the CDN, the load balancer or a network firewall.

Permissions and ownership

On Linux hosting, the web server runs as a particular user, and it can only serve files that user is allowed to read. It also needs the execute bit on every folder along the path, which is what allows a process to pass through a folder. A single parent folder set to 700 can make everything beneath it forbidden.

A common and safe starting point for a typical PHP site is folders at 755 and files at 644, with the files owned by the site's own user. Some managed hosts use tighter settings, such as 750 on the web root with a shared group, so follow your host's documentation where it differs.

# Show the permissions on every folder from the root down to the file
namei -l /var/www/example/public/brochure/price-list.pdf

# Reset folders to 755 and files to 644 inside the web root
find /var/www/example/public -type d -exec chmod 755 {} +
find /var/www/example/public -type f -exec chmod 644 {} +

# Give the files back to the site user if an upload or root copy changed them
chown -R exampleuser:examplegroup /var/www/example/public
โš ๏ธ Never "fix" a 403 with chmod 777. It lets any process on the server change your files, and some hosting setups refuse to run PHP from world-writable locations, so it can swap a 403 for a 500.

Configuration rules that refuse requests

Access rules are meant to refuse some requests. The problem is a rule that matches more than intended. Look for these patterns in the server configuration and in every .htaccess file from the web root down to the failing folder, because Apache applies them all.

# Apache 2.4: refuses everything in this folder and below
Require all denied

# Older Apache 2.2 syntax that still appears in copied snippets
Order deny,allow
Deny from all

# A narrow rule that only protects dotfiles such as .env and .git
<FilesMatch "^\.">
    Require all denied
</FilesMatch>

A Deny from all block copied into the wrong folder, such as an uploads folder that also holds public PDFs, will forbid every file in it. Mixing the old Order and Deny syntax with the Apache 2.4 Require syntax in the same place can also behave in surprising ways, so rewrite older snippets in the 2.4 form.

The nginx equivalents live in the server block. A location that is too broad, such as one meant to hide dotfiles, can catch real pages:

# Too broad: any path containing a dot after a slash, including /.well-known/
location ~ /\. { deny all; }

# Better: keep /.well-known/ open for certificate checks and similar files
location ^~ /.well-known/ { allow all; }
location ~ /\.(?!well-known) { deny all; }

Folders with no index file

If someone visits /services/ and there is no index.html or index.php in that folder, the server can either list the files or refuse. On most hosts listing is turned off, so the visitor gets a 403. The fix is to add an index file, to point the link at the real page, or to add a redirect. Do not turn directory listing back on to make the error go away; it exposes every file in the folder.

Hotlink protection and referrer rules

Rules that block images or files unless the referrer is your own domain will return 403 to anyone who opens the file directly, to social networks building previews and to search engine image crawlers. Allow empty referrers and the crawlers you care about, or remove the rule if bandwidth is not a real concern.

Firewalls, bot protection and crawlers

Web application firewalls block requests that look like attacks. They are useful, but generic rule sets are cautious and sometimes refuse normal traffic. Typical false positives include search pages with unusual characters in the query string, form posts containing code snippets or HTML, long tracking parameters and uncommon user agents.

Why this matters for search

Google does not index a URL that returns 403, and a site-wide 403 for Googlebot looks like the whole site has disappeared. Google also advises against using 403 or 404 to slow its crawling; if you need to reduce crawl load temporarily, it recommends 429 or 503 responses, which it treats as a signal to back off rather than as a refusal. Allow verified search engine crawlers by checking reverse DNS or the IP ranges they publish, not by trusting the user agent, which anyone can fake.

๐Ÿ’ก If only one crawler is refused, check for a named rule. Rules added to stop AI crawlers or aggressive SEO tools are sometimes written with a wildcard that also catches Googlebot or Bingbot.

The fix, step by step

Step 1

Confirm the 403 and who sent it

Take a failing URL from the HTTP Error Audit and request it with curl -sI, then look at the body as well. A cf-ray header or a CDN-branded page means the edge refused it; a firewall reference number points to ModSecurity or a similar tool; a plain Apache or nginx refusal means the server configuration or file system. Repeat with a browser user agent to see whether only automated clients are blocked.

Step 2

Read the matching log line

Search the web server error log for the path at the time of the request. client denied by server configuration or access forbidden by rule means a deny rule, Permission denied means file access, No matching DirectoryIndex or directory index is forbidden means a missing index file, and a ModSecurity line gives a rule id. No line at all means the block happened upstream at the CDN or a network firewall.

Step 3

Correct ownership and permissions

Run namei -l on the full file path to see every folder above it, and make sure each has the execute bit for the web server. Set folders to 755 and files to 644 unless your host documents something tighter, and give ownership back to the site user if files were copied in as root. Never use 777. On SELinux servers, restore the file contexts with restorecon as well.

Step 4

Fix index files and directory listing

If the refused address ends in a slash and points at a folder, check that the folder contains an index.html or index.php and that DirectoryIndex or the nginx index directive lists that file name. Add the missing file or redirect the folder address to the real page. Leave directory listing switched off, because turning it on exposes every file in the folder to anyone.

Step 5

Narrow the deny rule that caught it

Open every .htaccess file from the web root down to the failing folder, plus the virtual host or nginx server block, and find the Require all denied, Deny from all or deny all that matches. Rewrite it so it only covers what must stay private, such as dotfiles or a config folder, keep /.well-known/ open, and convert old Apache 2.2 syntax to the 2.4 form.

Step 6

Allow real crawlers through the firewall

In the CDN security events, the ModSecurity log or the security plugin's block list, find the rule that matched the audit or the search engine crawler. Add a narrow exception for that rule and path, or allow verified crawlers by reverse DNS or their published IP ranges rather than by user agent. Check country blocks and rate limits too, since a fast crawl can trip them.

Step 7

Retest as a browser and as a crawler

Purge any CDN cache for the address, then request it again with curl using both a browser user agent and a plain one, and confirm a 200 each time. Use URL Inspection in Search Console to run a live test as Googlebot. Finally, re-run the HTTP Error Audit so every URL that shared the same cause is checked, not only the one you tested.

Platform notes

Keeping 403s from coming back

Questions and answers

1. Why do I get 403 Forbidden on my own website?

Something between you and the file has refused the request on purpose. On your own site the usual causes are files or folders the web server is not allowed to read, often after an upload as root, a deny rule in .htaccess or the server configuration that matches more than intended, a folder with no index file, or a firewall or security plugin rule. The response body and the error log line for that request tell you which one it is, so check them before changing anything.

2. What permissions should my website files have to avoid 403 errors?

On typical Linux hosting, folders at 755 and files at 644, owned by the site user, is a safe starting point. The web server also needs execute permission on every parent folder of a file, so check the whole path with namei -l, not just the file itself. Some managed hosts use tighter settings with a shared group, so follow their documentation when it differs. Do not use 777, which is unsafe and can cause other errors.

3. Is a 403 error bad for SEO?

Yes, if it affects pages you want in search. Google cannot index a page that returns 403, and pages that keep returning it are eventually dropped. A 403 on a private admin area is fine and expected. The real risk is a firewall or bot rule that refuses Googlebot or Bingbot across the site, which can look like the whole site has vanished. Check with URL Inspection in Search Console that Google can fetch your key pages.

4. Why does my page work in the browser but show 403 in the audit?

The audit is an automated client, and many firewalls, CDNs and security plugins treat automated requests differently from a person browsing. Bot protection, rate limits, user agent rules and country blocks can all refuse a crawler while letting your browser through. Compare the response for a browser user agent and a plain one with curl. If only automated requests fail, check the firewall or CDN event log for the rule that matched, then decide whether search crawlers are caught too.

5. What is the difference between 401 and 403?

A 401 means the server needs you to authenticate and is asking for credentials, as with a password-protected staging site. A 403 means the server knows what you asked for and refuses to serve it, and logging in will not change that. If a page should require a login, 401 or a redirect to a login page is more accurate. If a page should be public and returns 403, a rule or permission setting is wrong and needs correcting.

6. Should I switch on directory listing to fix a 403 on a folder?

No. The 403 appears because the folder has no index file and listing is turned off, which is the safe default. Turning listing on would show every file in that folder to anyone, including backups, exports and files you never meant to publish. Instead add an index page to the folder, redirect the folder address to the real page it should show, or fix the internal link that points at the bare folder address.

7. Can Cloudflare cause 403 errors on my site?

Yes. Cloudflare can return 403 from its own edge because of WAF managed rules, custom rules you wrote, Bot Fight Mode, country or IP access rules, or a hotlink setting. You can tell because the response has a cf-ray header and the request never appears in your server logs. Open the security events log in Cloudflare, search for that Ray ID, and adjust or add an exception to the specific rule rather than disabling protection for the whole zone.

Find every 403 on your site

The HTTP Error Audit requests every URL in your crawl scope, records the status code and response time, follows redirects and flags anything outside the 200 range, so pages refused with 403 show up alongside every other failure.

Open HTTP Error Fixes โ†’
๐Ÿ’ฌ Got a problem?
Related Guides: All HTTP Error Fixes  ·  HTTP Errors in Plesk and cPanel  ·  AI Crawler Access  ·  500 Internal Server Errors  ·  Learning Hub

About aiwebpageseo

aiwebpageseo.com is a data-driven SEO and AEO (Answer Engine Optimisation) platform providing a free suite of technical SEO tools. Rather than relying on AI-theorised assumptions, the platform analyses live URL performance, delivering objective diagnostics, page speed metrics, CLS debugging, and site crawl data alongside actionable technical tutorials.