403 Forbidden in WordPress

Een 403 Forbidden op een WordPress-site betekent dat de server het verzoek wél begrijpt, maar hem bewust weigert. Dit artikel legt uit wat de vijf echte oorzaken zijn, hoe je uitzoekt welke het is en hoe je ze per stuk oplost.

Je opent je WordPress-site en in plaats van de pagina toont de browser "403 Forbidden". Soms is het maar één URL. Soms elke pagina op de site. Soms ligt een specifieke afbeelding of CSS-file eruit terwijl de HTML eromheen prima laadt. Het verzoek is bij je server aangekomen, je server besloot hem niet uit te voeren, en dat deed hij met opzet.

Waar dit artikel wel en niet over gaat

Dit artikel behandelt 403 Forbidden aan de publieke kant van een WordPress-site: bezoekers, een specifieke URL, een afbeelding, een hele sectie of de front-end in het algemeen. Verschijnt de 403 alleen als je wp-admin of wp-login.php probeert te openen, terwijl de rest van de site gewoon werkt? Dan is dat een ander diagnosepad, en dat staat in 403 Forbidden bij wp-admin. De vijf oorzaken hieronder overlappen met die variant, maar de admin-only smaak heeft een eigen volgorde van waarschijnlijkheid en een eigen walkthrough.

Wat een 403 eigenlijk betekent

RFC 9110 §15.5.4 definieert een 403 als: "the server understood the request but refuses to authorize it." In gewone taal: de server snapt wat je wilt, maar weigert mee te werken. Die zin sluit meteen twee dingen uit. De URL is niet stuk, dus dit is geen 404. De applicatie is niet gecrasht, dus dit is ook geen 500. Iets in de keten van browser naar PHP heeft welbewust besloten "nee, niet jij, niet dit, niet nu".

Op een WordPress-site is "iets in de keten" bijna altijd één van vijf dingen: een web application firewall die het verzoek blokkeert, bestandsrechten die te streng staan waardoor de webserver-user het bestand niet kan lezen, een .htaccess-regel die toegang weigert, Apache of nginx die een directory niet wil tonen omdat er geen indexbestand is, of een hotlink-regel die een asset tegenhoudt. De volgorde waarin ik ze hieronder behandel is belangrijk. In 2026 is de WAF verreweg de meest voorkomende oorzaak op live WordPress-sites, en daar begint de lijst dus mee.

Veelvoorkomende oorzaken, op volgorde van waarschijnlijkheid

1. Een WAF of ModSecurity-regel blokkeert het verzoek

Dit is de topoorzaak op elke WordPress-site die achter een beveiligingslaag draait, en in 2026 geldt dat voor de meeste. ModSecurity geeft standaard een 403 Forbidden terug zodra een regel afgaat, en Cloudflare, Sucuri, Wordfence Central en de meeste managed hosting WAF's doen hetzelfde. De blokkade gaat niet altijd over jou: de OWASP Core Rule Set scoort elk verzoek op talloze patronen, en een legitiem verzoek dat toevallig bepaalde woorden in een parameter heeft, een lange query string, of gewoon qua vorm op een bekende aanval lijkt, kan over de drempel schieten. Typische symptomen: de 403 verschijnt op een specifieke URL of bij een formulier-submit, de foutpagina ziet er generiek uit en komt niet van WordPress, het verzoek werkt wel vanaf een ander netwerk of apparaat, en de rest van de front-end is gezond.

2. Bestands- of maprechten (zie WordPress-bestandsrechten voor de volledige referentie) kloppen niet

Als de webserver-user een bestand niet mag lezen, kan hij het niet serveren, en geeft Apache of nginx een 403 terug. De WordPress file permissions-documentatie noemt 755 voor mappen, 644 voor bestanden en 440 of 400 voor wp-config.php. Een migratie die de verkeerde eigenaar meenam, een hardening-script dat alles op 600 zette of een handmatige chmod 700 op wp-content/uploads/ levert een 403 op voor alles wat de server niet meer kan lezen. Symptoom: de 403 verschijnt op één specifiek bestand of op een hele map, niet op een WordPress-URL-patroon, en in de error log van de server staat Permission denied.

3. Een .htaccess-regel weigert toegang (alleen Apache)

Op Apache of LiteSpeed kan .htaccess expliciet toegang tot een pad verbieden. De Apache-directive Require all denied geeft iedereen die binnen het blok valt een 403 terug, en hetzelfde geldt voor het oudere Deny from all, voor RewriteRule ... [F] regels en voor custom <Files> of <FilesMatch>-blokken die een plugin of security-tool heeft neergezet. De versie die ik het vaakst zie: een maintenance-plugin die een deny-blok toevoegde en het daarna nooit heeft opgeruimd, of een migratie die .htaccess heeft gekopieerd vanaf een ander domein waar bepaalde paden bewust dicht stonden. Symptoom: de 403 is chirurgisch (één pad, één file-patroon) en verdwijnt meteen als je .htaccess hernoemt. nginx leest .htaccess niet, dus deze oorzaak kun je op nginx overslaan.

4. De directory heeft geen indexbestand en indexing staat uit

Dit is de meest voorspelbare 403 van de lijst. Als een bezoeker rechtstreeks een URL als https://jouwsite.nl/wp-content/uploads/2026/03/ aanroept en er staat geen index.html of index.php in die map, dan geeft Apache met Options -Indexes een 403 Forbidden terug in plaats van de mapinhoud te tonen. Op nginx gebeurt hetzelfde als autoindex uit staat, wat de default is. Dat is privacy-technisch gezien correct gedrag. Het voelt alleen als een fout omdat de bezoeker iets zinnigs verwachtte. Symptoom: een 403 die uitsluitend verschijnt op URL's die eindigen op een slash en waar geen indexbestand bestaat, meestal op paden waar een mens normaal gesproken niet komt.

Laadt je site een afbeelding, font of PDF en komt daar voor juist dat bestand een 403 terug? Dan is de oorzaak vaak een hotlink-protectieregel die naar de Referer-header kijkt en verzoeken afwijst die niet van je eigen domein komen. Die regel zit in .htaccess, in een CDN-dashboard, in een security-plugin of in je hostingpaneel. Hij is bedoeld om andere sites te beletten jouw plaatjes te embedden. Hij blokkeert per ongeluk je eigen site als de regellijst te strikt is, als je net een nieuw domein of subdomein hebt toegevoegd, of als een browser een lege Referer meestuurt omdat de gebruiker vanaf een HTTPS-origin met strict referrer policy klikte. Symptoom: de HTML laadt prima, maar specifieke assets geven 403 in het netwerk-tabblad van de devtools.

Uitzoeken welke oorzaak het is

Loop deze checks op volgorde door. Ze zijn niet-destructief en isoleren welke van de vijf oorzaken het is vóórdat je ook maar iets aanpast.

Check 1: wat is de precieze scope van de 403? Is het één URL, één bestandstype, één map, de hele front-end of alleen bepaalde assets op een pagina die verder gewoon laadt? Noteer de URL die 403 geeft en één die het wel doet. De scope alleen al sluit de meeste oorzaken uit. Een 403 op één bestand komt bijna nooit van een WAF. Een site-brede 403 komt bijna nooit van een ontbrekende directory-index. Je weet dat deze check klaar is als: je de exacte set URL's kunt benoemen die 403 geven en de exacte set die laden.

Check 2: ziet de 403-pagina er generiek of custom uit? Open de falende URL en kijk naar de HTML. Een Cloudflare-blokpagina, een Sucuri-blokpagina, een Wordfence-blokpagina of een simpele "ModSecurity Action"-pagina wijst rechtstreeks op oorzaak 1. Een kale Apache- of nginx 403-pagina (geen branding) wijst meestal op oorzaak 2, 3 of 4. Een pagina die één afbeelding niet laadt terwijl de rest prima is, wijst op oorzaak 5. Je weet dat deze check klaar is als: je de herkomst van de 403-pagina kunt benoemen.

Check 3: lees de error log van de server. Open de error log in je hostingpaneel of via SSH. Een Permission denied-regel die een bestand noemt is oorzaak 2. Een client denied by server configuration of Options ExecCGI is off is oorzaak 3. Een directory index forbidden-regel is oorzaak 4. Een ModSecurity: Access denied-regel met een rule-ID is oorzaak 1. Op nginx staat dit in /var/log/nginx/error.log volgens de nginx-documentatie. Op Apache meestal in /var/log/apache2/error.log of /var/log/httpd/error_log. Je weet dat deze check klaar is als: je de precieze logregel kunt citeren die bij het tijdstip van de 403 hoort.

Check 4: probeer de URL vanaf een ander netwerk of apparaat. Verdwijnt de 403 als je overschakelt naar mobiele data of een andere browser, dan kijk je vrijwel zeker naar oorzaak 1 met een WAF die jouw IP op een blocklist heeft gezet, een geo-regel of een rate limit. Geeft elke verbinding exact dezelfde 403, dan gaat het niet om wie jij bent en worden oorzaken 2 tot en met 5 waarschijnlijker. Je weet dat deze check klaar is als: je met zekerheid kunt zeggen "de URL laadt vanaf mijn telefoon" of "de URL geeft 403 op elk apparaat dat ik heb geprobeerd".

Check 5: hernoem op Apache het .htaccess-bestand en test opnieuw. Verdwijnt de 403 zodra .htaccess hernoemd is, dan is oorzaak 3 bevestigd. Gebeurt er niks, zet het bestand dan terug en streep oorzaak 3 door. nginx negeert .htaccess, dus sla deze stap daar over. Je weet dat deze check klaar is als: de URL weer laadt met .htaccess aan de kant, of nog steeds 403 geeft en je oorzaak 3 kunt uitsluiten.

Oplossingen per oorzaak

Oorzaak #1: de WAF-regel opsporen en bijstellen

Is de 403-pagina herkenbaar (Cloudflare, Sucuri, Wordfence)? Noteer dan de rule name of het rule-ID dat erop staat. Die plugins en diensten zetten de regel standaard in de blokpagina. ModSecurity zet het rule-ID in de audit log (meestal /var/log/apache2/modsec_audit.log of te vinden in je hostingpaneel), en de default status is 403 tenzij de regel zelf iets als deny,status:403 afdwingt zoals beschreven in de reference manual hierboven. Met een concreet rule-ID in de hand heb je drie opties, in oplopende moeite:

  1. Zet je eigen IP op de allowlist voor de falende URL in het WAF-paneel, als de blokkade over wie jij bent gaat. Dit is de juiste fix voor een blocklist-entry of een rate limit, niet voor een false positive op het verzoek zelf.
  2. Laat je host een regeluitzondering maken voor precies dat rule-ID op precies dat pad, niet op de hele site. Eén gerichte uitzondering is veiliger dan de hele WAF uitschakelen.
  3. Is de WAF een WordPress-plugin die je zelf hebt geïnstalleerd (Wordfence, All-in-One Security, iThemes Security)? Open dan de firewall log in wp-admin, zoek het geblokkeerde verzoek op en klik op "allowlist" naast die regel. Elke serieuze plugin heeft die knop.

Schakel de WAF niet globaal uit "om te kijken of dat het fixt". Een tijdelijke bypass is prima voor tien minuten om de oorzaak te bevestigen. Een permanent uitgeschakelde WAF is een groter probleem dan de 403.

Verificatie: de falende URL laadt, in de WAF-log zie je een allow waar eerst een block stond, en de fix is gericht op een specifiek rule-ID of IP, niet op het uitzetten van de bescherming.

Oorzaak #2: bestandsrechten herstellen

De meeste hostingpanelen hebben een bestandsbeheerder waarmee je rechten kunt bekijken en aanpassen. Open de bestandsbeheerder, navigeer naar het bestand of de map die in de error log wordt genoemd, en controleer de permissiewaarde. De WordPress file permissions-documentatie beveelt 755 aan voor mappen, 644 voor bestanden en 440 of 400 voor wp-config.php. Zie je iets restrictiever (zoals 600 of 700), pas het dan aan naar de aanbevolen waarde. Veel bestandsbeheerders laten je rechten recursief toepassen op een hele mappenstructuur, wat handig is als een hele map zoals wp-content/uploads/ geraakt is.

Op sommige shared hosts zijn 750 voor mappen en 640 voor bestanden de waarden die werken, omdat PHP daar als een andere user draait dan de eigenaar. Geeft 644 nog steeds 403, probeer dan 640. Zet niks op 777. De WordPress-docs zijn daar expliciet over: world-writable permissies zijn gevaarlijk, en een 403 is geen rechten-probleem dat je oplost met méér rechten, maar met de juiste rechten.

Zit de 403 alleen op één map zoals wp-content/uploads/2026/03/, begin daar dan voordat je de hele boom aanpakt.

Als je SSH-toegang hebt:

find . -type d -exec chmod 755 {} \;  # mappen
find . -type f -exec chmod 644 {} \;  # bestanden
chmod 440 wp-config.php               # wp-config.php gehardened volgens WordPress docs

Verificatie: de falende URL of asset laadt weer, de permissies in de bestandsbeheerder van je hostingpaneel (of via ls -l over SSH) tonen minimaal leesrechten voor de webserver-user, en de error log bevat geen Permission denied-regels meer voor dat pad.

Oorzaak #3: de weigerende directive verwijderen of aanpassen (alleen Apache)

Liet check 5 zien dat .htaccess hernoemen de 403 oploste? Open het bestand en zoek naar het blok dat toegang weigert. Typische patronen om op te zoeken:

  • Require all denied binnen een <Files>, <FilesMatch>, <Directory> of <Location> blok
  • Deny from all (de Apache 2.2-syntax, die nog steeds in kopieer-plak-snippets opduikt)
  • RewriteRule-regels die eindigen op [F], wat een 403 teruggeeft
  • Een custom blok dat is genoemd naar een security- of maintenance-tool

Verwijder het blok dat jouw falende pad afdekt, sla op en test. Herken je het blok niet, maak dan eerst een kopie van het bestand zodat je het kunt terugzetten. De veiligste manier om een schone WordPress-.htaccess te krijgen is door WordPress hem zelf te laten regenereren: ga in wp-admin naar Instellingen → Permalinks en klik op Wijzigingen opslaan zonder iets te veranderen. WordPress schrijft dan een vers blok volgens het standaard WordPress rewrite-blok. Dat werkt alleen als .htaccess beschrijfbaar is voor de webserver-user. Is dat niet zo, dan maak je het bestand zelf aan met dat standaardblok en upload je het.

Verificatie: de falende URL laadt, .htaccess bevat de weigerende directive niet meer en je WordPress-permalinks werken nog (de mooie URL's lossen op).

Oorzaak #4: een indexbestand toevoegen of de 403 accepteren

Komt een bezoeker rechtstreeks op een directory-URL uit (wp-content/uploads/2026/03/), dan is de schoonste fix een leeg index.html of index.php in die map zetten. WordPress zelf levert in veel mappen standaard al een leeg index.php mee, precies om deze reden: het geeft een blanco pagina terug in plaats van een 403 en voorkomt tegelijk dat de mapinhoud getoond wordt. Gaat het om een map waar bezoekers überhaupt niet terecht horen te komen, dan is de 403 juist het goede antwoord en laat je hem staan. De vraag is of een bezoeker ooit op die URL moet landen. Zo ja: indexbestand toevoegen. Zo nee: de 403 laten en repareren wat je site op een directory-URL laat linken in plaats van op een specifiek bestand.

Zet Options +Indexes op Apache of autoindex on; op nginx niet aan als "fix". Daarmee stel je de mapinhoud bloot aan iedereen, en dat wil je op een WordPress-site vrijwel nooit.

Verificatie: de directory-URL geeft je indexbestand terug (of bewust nog steeds 403), en geen enkele echte link op de site verwijst naar een directory-URL die op Indexes rekent.

Vind eerst de regel. Die zit in .htaccess (zoek naar een RewriteCond %{HTTP_REFERER} blok), in een CDN-dashboard (bij Cloudflare heet dat "Hotlink Protection"), in een security-plugin of in de asset protection-sectie van je hostingpaneel. Heb je hem te pakken, voeg dan je eigen domein toe aan de allowed referrers lijst (inclusief www, zonder www en alle subdomeinen die je gebruikt), en sta lege referrers toe als je site een strict referrer policy heeft of als je naar assets linkt vanaf HTTPS-pagina's die het volledige referrer-pad verbergen. Een .htaccess hotlink-blok dat daadwerkelijk voor je eigen site werkt, ziet er ongeveer zo uit:

RewriteEngine On
RewriteCond %{HTTP_REFERER} !^$                          [NC]
RewriteCond %{HTTP_REFERER} !^https?://(www\.)?jouwsite\.nl [NC]
RewriteRule \.(jpg|jpeg|png|gif|webp|svg|pdf)$ - [F]

De eerste RewriteCond is de belangrijkste. Die staat lege referrers toe, en dat is precies wat moderne browsers vaak sturen vanaf HTTPS-pagina's. Zonder die regel kunnen je eigen CSS- en HTML-verwijzingen naar afbeeldingen je hotlink-regel bij een verkeerd bezoek alsnog laten afgaan.

Verificatie: de asset laadt op je eigen pagina's in het netwerk-tabblad van de devtools (200-respons), en een embed-poging vanaf een extern domein geeft nog steeds 403.

Wanneer hulp inschakelen

Lossen 20 minuten diagnose het niet op? Geef het dan door aan je host of een developer, met dit lijstje klaar. Dat stuurt het ticket in één keer naar de juiste engineer:

  • De exacte URL die 403 geeft en één URL op dezelfde site die wél laadt.
  • De scope: één URL, één map, een bepaald soort asset of de hele front-end.
  • De 403-pagina zelf: generieke Apache/nginx, Cloudflare, Sucuri, Wordfence, een security-plugin of een ModSecurity-blokpagina.
  • Je stack: Apache of nginx, PHP-versie, WordPress-versie, of de site achter een CDN of WAF draait.
  • De matchende regels uit de error log van de server (Apache, nginx) of uit de WAF-audit log, met timestamps.
  • Of dezelfde URL wél laadt vanaf een ander netwerk of apparaat.
  • Wat er in de laatste 48 uur is veranderd: plugin-updates, theme-updates, core-updates, WAF-regelupdates, rechtenwijzigingen, migraties, DNS-wijzigingen.
  • Op Apache: of .htaccess hernoemen iets verandert.

Is de 403 alleen op wp-admin? Begin dan niet met dit artikel. Volg in plaats daarvan de wp-admin-variant van dit diagnosepad, want de volgorde van waarschijnlijkheid en de fixes zijn daar anders. Kom je wel op de URL uit maar lukt inloggen niet? Dan zit het onderliggende probleem waarschijnlijk in de familie van niet kunnen inloggen op WordPress.

Hoe je voorkomt dat het terugkomt

Drie gewoontes houden 403's zeldzaam op een gezonde WordPress-site:

  • Behandel WAF-uitzonderingen als gerichte patches, niet als brede bypasses. Elke keer dat een WAF iets legitiems blokkeert, maak je een gerichte uitzondering op dat rule-ID en dat pad, en log je waarom je hem hebt toegevoegd. Een WAF met tien chirurgische uitzonderingen is sterker dan een WAF die iemand uit frustratie heeft uitgezet.
  • Zet je .htaccess in versiebeheer als je hem met de hand bewerkt. Een .htaccess die door Instellingen → Permalinks is gegenereerd kun je altijd terughalen. Een handmatig bewerkte versie met custom deny-regels die door een plugin is overschreven niet. Of je commit hem, of je laat een plugin de eigenaar zijn zodat een reinstall hem weer herstelt.
  • Zet na elke migratie expliciet de rechten recht. Controleer en corrigeer de rechten in de bestandsbeheerder van je hostingpaneel (of draai de chmod-commando's hierboven via SSH) en controleer of wp-config.php op 440 of 400 staat. Een migratie die succesvol leek maar de rechten scheef heeft gezet, veroorzaakt later 403's op willekeurige assets, en dat zijn de lastigste om achteraf terug te vinden.

Een 403 op een gezonde WordPress-site is bijna altijd een bewuste beslissing die de server genomen heeft en vergat door te geven. De vijf fixes hierboven traceren die beslissing terug naar de laag die hem heeft gemaakt.

Wil je dat dit niet steeds jouw probleem is?

Als storingen blijven terugkomen, is de 'fix' vaak consistent beheer: updates, backups en monitoring die niet versloffen.

Bekijk WordPress onderhoud

Doorzoek deze site

Begin met typen om te zoeken, of blader door de kennisbank en blog.