403 is not 401, and not 404
401 Unauthorized means the server wants credentials, or the ones you sent were not accepted. Sending valid credentials changes the answer.
403 Forbidden means credentials are not the issue. The request was understood and refused. Logging in may not help, because whatever refused you may not care who you are.
404 is sometimes used deliberately in place of 403 to avoid confirming that a path exists. If you are hunting a 403 on one environment and a 404 on another for the same URL, that difference is a configuration choice, not a bug.
Layer 1 — your origin refused it
The plainest case. The file exists but the web server will not serve it: directory permissions that exclude the web user, a directory with no index file and listing disabled, an .htaccess or nginx deny rule, or an application that checks a role and returns 403 itself.
How to recognise it. The error page looks like your stack: an Apache or nginx default page, or your own application's styled "you do not have access" screen. Your origin access log has the request with status 403 — which is the tell, because the request reached the origin at all.
Layer 2 — a WAF rule matched
A web application firewall inspects the request and blocks it when it matches an attack signature. This is the layer that produces the confusing 403s, because the request looks perfectly innocent to the person making it.
The usual false positives are not exotic: a CMS editor saving a post that contains the word SELECT in a code sample, a form field holding a snippet of HTML, a product description with an apostrophe in a particular place. The rule sets that ship with a WAF are written to catch injection attempts, and human text sometimes looks like one.
On cdn.com.tr the WAF is ModSecurity with the OWASP Core Rule Set, and a blocked request gets a branded 403 page carrying a reference ID. That ID is the whole point: it is the request identifier written into the audit log, so you can look up exactly which rule matched and on which field, instead of guessing. The WAF log page in the panel lists blocked events with the attack category, the country, the IP and the rule that fired.
The fix that keeps you protected. Exempt the specific field on the specific path — for example the post body on the editor URL — rather than disabling a rule family everywhere or turning the WAF off for the site. A narrow exclusion costs you nothing; a broad one quietly removes protection from every other page.
Layer 3 — a country or network block
Geographic and network blocks are enforced before the request reaches your application, and they also produce 403. If you have a country blacklist, everyone from that country sees the refusal. If you block by ASN — an autonomous system number, which covers a provider's whole network — every visitor on that provider is refused, which is a much wider net than it sounds.
The trap worth knowing. Mobile carriers put millions of ordinary subscribers behind a handful of ASNs, and mobile IPs rotate. A visitor who was fine on wifi can be refused on mobile data and describe it as "the site is broken on my phone". If your 403 reports cluster on mobile networks, look at your blocks before you look at your application.
Blocks like these are worth auditing on a schedule. A rule added during an incident tends to outlive the incident.
Layer 4 — hotlink protection and IP lists
Hotlink protection refuses requests for your images and files when the Referer header is another site. It does its job, but it also refuses legitimate traffic you forgot about: your own staging domain, an email client rendering an image, an app that sends no referer at all. The symptom is specific and recognisable — pages load, images do not.
IP allow and deny lists are the bluntest layer. An allow-list on an admin path is an excellent control right up to the day your office IP changes and nobody remembers the list exists. When a 403 affects exactly one person and nobody else, this is usually why.
How to find the cause in order
Work from the outside in. It takes minutes and it beats guessing.
1. Read the error page. A branded page with a reference ID means an edge decision — a WAF rule, a geo or ASN block. A default server page or your own application styling means the origin decided.
2. If there is a reference ID, look it up. The WAF log gives you the rule ID, the matched field and the value that triggered it. This is the fastest path from symptom to cause, and it turns the conversation from "the site blocks me sometimes" into "rule 942100 matched the post body".
3. Check whether it is only you. Ask from another network or a mobile connection. If it is only you, look at IP lists. If it is everyone from one country, look at your geo blocks.
4. Check whether it is only one path. One URL refusing while the rest of the site works points at the origin's own rules or a WAF rule bound to that path.
5. Only then look at the origin. If the request never appears in your origin access log, it was refused before it got there, and nothing you change on the origin will help.
Fixing it without losing the protection
The instinct when a WAF blocks a legitimate request is to switch the WAF off for that site. It works, in the sense that the symptom disappears, and it removes protection from every other request you were not thinking about.
A better sequence: reproduce the block, read the rule ID from the log, write an exclusion for that rule on that field and that path, then reproduce again to confirm the request passes and that the rule still fires elsewhere. On cdn.com.tr this is what the delivery rules and security presets are for — the exclusion lives in configuration, gets deployed to every edge, and is visible in the activity history with the person who made it and the values before and after.
If you cannot reproduce the block, do not start writing exclusions. An exclusion for a rule that was not the cause is protection removed for nothing.
403 Forbidden FAQ
Why does the same URL work in one browser and not another?
The request is not identical. Different user agents, different cookies, and in particular different networks — one browser on wifi and one on mobile data leave from different IP addresses. If the refusal follows the network rather than the browser, look at IP, country or ASN blocks rather than at your application.
My WAF blocks my own editor when I save a post. What do I change?
Find the rule ID from the blocked event, then exempt that rule for the field the editor sends on the editor URL. Do not exempt the whole path and do not disable the rule family for the site: the same rules protect the rest of your forms, and injection attempts arrive through the same fields legitimate text does.
Can a 403 be cached?
It can, and a cached 403 is an unpleasant surprise because the cause disappears while the symptom stays. Error responses should generally be served with a short TTL or not cached at all. If you fixed the cause and visitors still see the refusal, purge the path before you keep debugging.
The reference ID on the error page — what is it for?
It is the identifier of that exact request in the audit log. A visitor can send it to you and you can look up which rule fired, on which field, with which value. Without it, a "403 sometimes" report is almost impossible to investigate.
Does a 403 hurt my SEO?
A 403 on a page you want indexed does, because the crawler is refused like any other client and will eventually drop the URL. The case to watch is an over-broad block that catches search engine crawlers — verify that the pages you care about answer 200 to a crawler, not just to your browser.