A 403 error: what it means (and doesn’t)
A 403 Forbidden means the server understood the request but refuses to allow it. Your site is reachable; it’s a “you can’t enter” response, not “the building is gone.” That makes it different from a 404 (missing page) or a 500 (server error). It also doesn’t automatically mean you were hacked—though security tools can trigger 403s when they suspect something risky.
The refusal usually comes from a rule or permission check: file and folder permissions, a server config rule, a security plugin, a CDN or WAF block, hotlink protection, or an IP restriction. The practical difficulty is that several layers can return the same 403, so fixing the wrong layer can waste time or break access further.
First triage: is it one page or everything?
You’re trying to load a page and suddenly get 403. Before changing anything, check the blast radius. Open the homepage, a random blog post, an image file, and if you can, the admin area (for example /wp-admin/). If only one URL or one directory is failing, you’re likely dealing with a path-specific rule (a bad rewrite, a deny rule for a folder, hotlink protection on /uploads/, or a missing index rule on a directory). If everything is 403, think broader: a security layer blocking your IP, a site-wide rule in .htaccess or Nginx, or permissions that changed on the whole web root.
Do one quick “different network” test: try from mobile data. If the 403 disappears, the site may be fine and your IP is blocked upstream. Capture evidence now: exact URLs, time, your IP, and any request ID shown on the error page.
File and folder permissions that lock you out
A common “nothing changed” cause of 403 is that file or folder permissions quietly shifted during a plugin install, a migration, a restore, or a deploy. The web server user needs read access to files and read/execute access to folders to traverse paths. If a folder loses execute permission, the server can’t enter it, even if the files inside look fine. You’ll often notice this when images under something like uploads go 403, or when wp-admin fails but the public homepage still loads.
On many Linux hosts, a safe baseline is folders at 755 and files at 644, with ownership set to the account or service user your host expects. Don’t “fix” this by setting 777 everywhere; it can create security risk and some hosts will block it anyway. If you’re on managed hosting and can’t see ownership, grab the failing path list and ask support to verify permissions and owner/group for those directories.
Rules that deny access: .htaccess, Nginx, and ACLs

You’ll also see 403s when the server is following a rule, not a permission. On Apache (common on shared hosting), those rules often live in .htaccess. A single line like “Deny from all,” an allowlist that doesn’t include your IP, or an overzealous hotlink rule can block wp-admin, /wp-json/, or whole folders like /uploads/. If the 403 started right after changing permalinks, installing a security plugin, or migrating, temporarily renaming .htaccess (for example to .htaccess.bak) is a safe test: if pages load again, you’ve narrowed it to rules, not files.
On Nginx (common on VPS and many managed stacks), equivalent blocks live in server config, not .htaccess, so you may only fix it via your host or a control panel. Look for location blocks, “deny all,” basic auth, missing index settings for directories, or rules that block dotfiles. Some hosts also apply ACLs (Access Control Lists) on top of normal permissions; they can deny access even when 755/644 looks correct. The catch is you can’t always view ACLs without shell access, so escalate with the exact paths and timestamps.
Security layers causing 403: WAFs, CDNs, and IP blocks
You load the site from one connection and get 403, but it works from mobile data. That pattern usually points to a security layer in front of your server: a CDN, a WAF, or an IP block at the host. These tools can deny requests that look like attacks (lots of login attempts, unusual query strings, /wp-json/ calls, XML-RPC traffic, or admin access from a new country), and they often return their own branded 403 page or a request ID. Save that ID and the exact time; it’s the fastest way for support to find the block event.
Check whether the 403 happens only on sensitive paths like /wp-admin/, /wp-login.php, or /wp-json/. If yes, review recent changes: enabling “Bot Fight” or managed rules, tightening country or ASN blocks, turning on hotlink protection at the CDN, or adding a firewall rule after a suspicious login alert. The practical constraint is that disabling the WAF or switching the site “off proxy” can restore access, but it also reduces protection and can break caching; prefer temporary allowlisting your IP and rolling back the last security change first.
A practical fix sequence (from safest to riskiest)

You usually want the smallest reversible change first, because a 403 is often protecting something (even if it’s doing it poorly). Start by confirming scope again: test a public page, a static file, and the admin path, then repeat from a second network. If it’s only your connection, allowlist your current IP in the CDN/WAF or hosting firewall, and stop there. If it’s everyone, pause any ongoing deploys or restores so you’re not chasing a moving target, then note the exact time the 403 began.
Move from outer layers inward. Check the CDN/WAF dashboard for recent blocks and temporarily relax only the specific rule involved (or set a short-lived bypass for your IP) rather than turning protection off. If you’re on WordPress and admin is blocked, disable security/caching plugins by renaming their folders via file manager or SFTP, then re-test. If the site is still 403, do the safe rule isolation: rename .htaccess and regenerate permalinks later. Only after that should you adjust permissions, and do it narrowly on the failing directories, not site-wide.
The riskiest steps are the ones that change many files at once: recursive chmod, bulk ownership changes, switching the entire site off proxy, or removing firewall rules “just to see.” If you’re about to do any of those, it’s usually better to escalate with evidence: affected URLs and paths, timestamps, your IP, error page request IDs, and any relevant log snippets your host provides.
Preventing future 403s after changes and deploys
The pattern behind “sudden” 403s is usually a change that didn’t get tracked: a deploy overwrote .htaccess, a restore changed ownership, or a security rule tightened without a rollback plan. Treat access control as a release artifact. Keep .htaccess and server rules in version control, and record CDN/WAF changes with timestamps and the person who made them. After each deploy or plugin/security update, run a quick smoke test list: homepage, one deep URL, a file under uploads, /wp-admin/, and /wp-json/ if you use it.
Build a safe escape hatch before you need it: a separate admin allowlist method (temporary IP allowlisting at the edge, or hosting panel access), and a documented way to disable security plugins without wp-admin. The practical cost is a bit of process overhead, but it pays off when you can roll back one change instead of running risky recursive permission fixes. When escalating, include the exact start time, affected paths, your IP, and any request ID shown on the 403 page.