Too Many Redirects in WordPress: zo doorbreek je de ERR_TOO_MANY_REDIRECTS-lus

Een redirect-lus maakt je WordPress-site onbereikbaar. Dit artikel benoemt de vijf echte oorzaken op volgorde van waarschijnlijkheid en lost ze stuk voor stuk op met een controle die je zelf in de browser kunt checken.

Je opent je WordPress-site en in plaats van een pagina zie je ERR_TOO_MANY_REDIRECTS, of de browser meldt "Deze pagina werkt niet. jouwsite.nl heeft je te vaak doorgestuurd." De voorkant is onbereikbaar. Soms werkt wp-admin nog wel, soms allebei niet. De site is niet echt "down" in infrastructuur-termen: PHP draait, de database staat aan, de server antwoordt gewoon. Hij vertelt de browser alleen om ergens anders heen te gaan, eindeloos.

Browser die de Too Many Redirects-fout toont op een WordPress-site.

Wat deze fout eigenlijk betekent

Je browser heeft een keten van HTTP-redirectresponses gevolgd (statuscodes 301, 302, 307, 308) en is tegen een limiet aangelopen die hij zelf oplegt om oneindige lussen tegen te houden. Chrome en Firefox stoppen allebei rond de 20 hops. RFC 9110 Section 15.4 definieert de 3xx-redirectklasse, en elke moderne browser legt daar nog een eigen veiligheidslimiet bovenop. Zodra die limiet wordt geraakt, stopt de browser en toont de foutmelding in plaats van eindeloos door te blijven draaien.

De lus zelf is bijna altijd een configuratieprobleem, geen bug: twee plekken in je stack zijn het oneens over de canonieke URL. De één zegt "ga naar HTTPS", de ander zegt "ga terug naar HTTP". De één zegt "voeg www toe", de ander zegt "haal www weg". De browser stuurt alleen maar heen en weer. Zoekmachines doen hetzelfde, dus zolang de lus blijft, wordt er ook niks nieuws geïndexeerd.

De vijf meest voorkomende oorzaken

Dit zijn de vijf oorzaken die ik op WordPress-sites tegenkom, op volgorde van hoe vaak het er écht eentje is:

  1. Site-adres en WordPress-adres staan verkeerd, of het protocol klopt niet. De twee URL's onder Instellingen > Algemeen staan anders dan de URL waarop de site daadwerkelijk draait. Erg gewoon direct na een migratie, een domeinwissel of een switch naar HTTPS.
  2. Cloudflare-SSL staat op "Flexible" terwijl de origin HTTPS afdwingt. Cloudflare praat dan in plain HTTP met de origin, de origin stuurt HTTP door naar HTTPS, Cloudflare vangt die redirect op en stuurt de bezoeker naar HTTPS, dat komt weer bij Cloudflare binnen, die weer plain HTTP naar de origin stuurt. Klassieke loop.
  3. Een kapotte .htaccess-rewriteregel. Meestal toegevoegd door een SSL- of cacheplugin die eigen regels naast het WordPress permalink-blok heeft geschreven, of een handmatige regel die uit een tutorial is geplakt en hier gewoon niet past.
  4. FORCE_SSL_ADMIN staat aan terwijl de site niet écht op HTTPS draait. De admin forceert HTTPS, die HTTPS-request belandt uiteindelijk weer op HTTP, en de admin blijft heen en weer stuiteren.
  5. Twee plugins forceren allebei HTTPS of een canonieke redirect. Een SEO-plugin en een "Really Simple SSL"-achtige plugin proppen allebei een wp_redirect() in template_redirect en zijn het oneens over de doel-URL. Minder vaak dan mensen denken, maar het gebeurt wel.

Als je niet op de voorkant vastloopt maar op het inlogscherm, is het probleem een ander: lees het artikel over de login-redirect-lus in WordPress voor de auth-cookie-variant die in WordPress zelf zit. Wil je de HTTPS-redirect helemaal opnieuw goed inrichten, lees dan hoe je WordPress op HTTPS forceert zonder de redirect-lus. En draait je site achter Cloudflare en weet je niet zeker of de rest van de proxyconfiguratie klopt, dan dekt de WordPress + Cloudflare-configuratiegids SSL-modus, cacheregels en de plugininstellingen die met redirects samenspelen.

Uitzoeken welke oorzaak het is

Verander nog niks voordat je deze twee checks hebt gedaan. Ze vertellen je met welke fix je moet beginnen en voorkomen dat je aan dingen zit die helemaal niet kapot zijn.

Kijk naar de redirectketen in DevTools. Open de site in een incognitovenster met DevTools open op het Network-tabblad, vink "Preserve log" en "Disable cache" aan en laad de URL. Je ziet een rij 301/302-responses voorbijkomen. Lees van elke response de Location-header. Gaat de keten van http://jouwsite.nl naar https://jouwsite.nl naar http://jouwsite.nl, dan heb je een HTTPS/HTTP-conflict (oorzaken 2, 4 of delen van 3). Blijft de keten www toevoegen of juist weghalen, dan is het bijna altijd oorzaak 1. Begint de loop zodra je /wp-admin/ aanroept, dan is oorzaak 4 de eerste verdachte.

Controleer de site-URL rechtstreeks in de database. Via phpMyAdmin in je hostingpaneel, of over SSH als je dat hebt:

SELECT option_name, option_value
FROM wp_options
WHERE option_name IN ('siteurl', 'home');

Kloppen die twee waarden niet met de echte URL in de browser (inclusief https:// en wel of geen www), dan heb je oorzaak 1 te pakken, zelfs nog voordat wp-config.php of .htaccess in beeld komen. De tabelprefix wp_ kan op jouw installatie anders zijn; gebruik wat er in wp-config.php staat.

Fix 1: zet het Site-adres en WordPress-adres goed

Open wp-config.php via SFTP of SSH en zet deze twee regels boven het /* That's all, stop editing! */-commentaar, met de exacte URL waarop je de site wilt hebben:

define( 'WP_HOME', 'https://jouwsite.nl' );
define( 'WP_SITEURL', 'https://jouwsite.nl' );

Deze constanten overrulen de waardes van siteurl en home in de database tijdens runtime, zonder dat ze de opgeslagen waardes echt aanpassen. Precies wat je wil als je niet meer in de admin kunt. Gebruik geen trailing slash achter de URL. Laat http vs https en www vs zonder www precies overeenkomen met wat je HTTPS-certificaat dekt.

Het WordPress-scherm Instellingen > Algemeen met WordPress-adres en Site-adres.

Verificatie: laad de site in een verse incognitotab. Op het Network-tabblad van DevTools moet je nu één 200 OK op het hoofddocument zien in plaats van een rij 301's. Zie je nog steeds redirects, noteer dan waar ze naartoe wijzen, draai de wijziging terug en ga door naar Fix 2.

Fix 2: corrigeer de Cloudflare-SSL-modus

Log in bij Cloudflare, kies de site en open SSL/TLS > Overview. Staat de modus op "Flexible", zet hem dan op "Full (strict)" als je origin een geldig certificaat heeft (Let's Encrypt, een commercieel certificaat of Cloudflare Origin CA), of op "Full" als het origin-certificaat self-signed is.

"Flexible" betekent dat Cloudflare in plain HTTP met je origin praat, en dat maakt gewoon een lus zodra de origin HTTP naar HTTPS stuurt. Cloudflare waarschuwt er zelf expliciet voor in de eigen documentatie. De oplossing is óf de origin op HTTPS zetten en overstappen op Full (strict), óf de origin stoppen met dat HTTP-naar-HTTPS redirecten zolang hij achter Cloudflare hangt. Die eerste is bijna altijd de goede.

Verificatie: gooi de Cloudflare-cache leeg (Caching > Configuration > Purge Everything), wacht een seconde of dertig tot de wijziging is uitgerold en laad de site opnieuw in incognito. De documentrequest hoort weer één 200 te zijn. Heb je directe toegang tot de origin, dan kan curl -sI https://jouwsite.nl vanaf de origin zelf ook dienen als dubbelcheck: daar hoort een 200 uit te komen, geen 301 naar zichzelf.

Cloudflare Flexible SSL: waarom het loopt en hoe je het definitief oplost

Oorzaak 2 verdient een eigen sectie, want Cloudflare Flexible SSL is de meest voorkomende trigger voor ERR_TOO_MANY_REDIRECTS op WordPress-sites die prima werkten tot ze achter Cloudflare werden gezet. Het patroon is specifiek en de oplossing is definitief, maar alleen als je snapt wat Flexible eigenlijk doet.

Het mechanisme

Flexible-modus betekent dat Cloudflare de verbinding tussen de bezoeker en Cloudflare's edge versleutelt, maar in plain HTTP met je origin praat. Je origin ziet nooit een HTTPS-request. Als iets op de origin (een .htaccess-regel, een nginx-rewrite, een WordPress-plugin, FORCE_SSL_ADMIN, of de "Always Use HTTPS"-instelling in Cloudflare zelf) HTTP doorstuurt naar HTTPS, komt die redirect terug bij Cloudflare's edge. Cloudflare benadert de origin opnieuw via HTTP. De origin stuurt weer door. De browser ziet een 301 naar HTTPS, krijgt weer een 301 naar HTTPS, nog een 301, en geeft het op na zo'n 20 pogingen.

De redirectketen in DevTools ziet er zo uit:

https://jouwsite.nl  →  301 Location: https://jouwsite.nl  →  301 Location: https://jouwsite.nl  → ...

Elke hop gaat naar dezelfde HTTPS-URL. Dat is het verklikkertje: een lus waarbij de Location-header identiek is aan de request-URL betekent bijna altijd dat er een proxy het protocol downgradet tussen de edge en de origin.

Waarom Flexible bestaat (en wanneer het de verkeerde modus is)

Flexible was bedoeld voor origins die helemaal geen TLS-certificaat hebben en er ook geen kunnen installeren. Gedeelde hosting in 2014. Oude servers achter firewalls. Die situatie is grotendeels verdwenen: Let's Encrypt geeft gratis certificaten uit, de meeste hosts automatiseren verlenging, en Cloudflare's eigen Origin CA geeft gratis certificaten met 15 jaar geldigheid specifiek voor het stuk tussen Cloudflare en de origin. Als je origin HTTPS kan draaien (en in 2026 kan dat gewoon), dan is Flexible de verkeerde modus. Niet omdat Flexible kapot is, maar omdat het gebouwd is voor een beperking die je vrijwel zeker niet meer hebt.

Cloudflare's eigen troubleshootinggids voor ERR_TOO_MANY_REDIRECTS noemt Flexible-modus als eerste oorzaak en adviseert om over te stappen op Full.

De fix

  1. Installeer een TLS-certificaat op de origin als dat er nog niet is. Let's Encrypt via Certbot, of een Cloudflare Origin CA-certificaat, allebei prima.
  2. Open in het Cloudflare-dashboard SSL/TLS > Overview en zet de modus van Flexible naar Full (strict). Gebruik "Full" alleen als het origincertificaat self-signed is.
  3. Staat "Always Use HTTPS" aan in Cloudflare (onder SSL/TLS > Edge Certificates), laat dat dan aan. Dit regelt de browser-naar-Cloudflare-hop. Het punt is dat de Cloudflare-naar-origin-hop nu ook HTTPS is, dus er loopt niks meer in een kringetje.
  4. Verwijder eventuele HTTP-naar-HTTPS-redirectregels op de origin die als workaround waren toegevoegd. WordPress-plugins als "Really Simple SSL" en handmatige .htaccess-rewrites doen geen kwaad als de origin echt HTTPS draait, maar ze zijn overbodig als Cloudflare de edge-redirect regelt en ze voegen een bewegend onderdeel toe dat later weer kan breken.

Verificatie

Gooi de Cloudflare-cache leeg (Caching > Configuration > Purge Everything), wacht 30 seconden en open de site in een incognitovenster met DevTools Network-tab open. Je hoort nu één 200 OK op het hoofddocument te zien. Geen redirectketen.

Vanaf de originserver zelf (via SSH):

curl -sI https://jouwsite.nl

Dit hoort een 200 terug te geven, geen 301 naar zichzelf. Krijg je toch een 301, dan staat er nog een redirectregel op de origin die nu weg mag omdat Cloudflare de HTTPS-upgrade op de edge afhandelt.

Controleer na het oplossen van de redirect-lus ook de voorkant op mixed content-waarschuwingen. Sites die een tijdje op Flexible hebben gedraaid, hebben vaak http://-URL's in de database staan (afbeeldingspaden, stylesheetsverwijzingen, geserialiseerde widgetdata). Die veroorzaken geen lus, maar ze breken wel het slotje in de browser en triggeren "Niet beveiligd"-waarschuwingen.

Fix 3: bouw .htaccess opnieuw op

Hernoem de huidige .htaccess in de WordPress-root naar .htaccess_broken en laad de voorkant. Als de site meteen terugkomt, zat de lus in dat bestand.

Om een schone versie te krijgen log je in op wp-admin (die is nu weer bereikbaar nu de kapotte regels weg zijn), open je Instellingen > Permalinks en klik je op Wijzigingen opslaan zonder iets aan te passen. WordPress schrijft dan een nieuwe standaard .htaccess met alleen het permalink-blok erin. Plak de oude file niet in één keer terug. Voeg regels die je echt nodig hebt (IP-allowlists, securityheaders, cache-control) één voor één toe en laad de site na elke regel opnieuw.

Een kapotte .htaccess is trouwens ook de meest voorkomende oorzaak van 404 Not Found op pagina's die wel in het dashboard staan. Zie je beide symptomen op dezelfde site, dan lost het fixen van .htaccess ze meestal in één keer allebei op.

Verificatie: laad de site en loop minstens drie URL's langs (home, een bericht, een archiefpagina). Alle drie horen 200 terug te geven. De oude .htaccess_broken blijft voorlopig op de server staan zodat je later kunt diffen welke regel de boosdoener was.

Fix 4: check FORCE_SSL_ADMIN

Open wp-config.php en zoek naar deze regel:

define( 'FORCE_SSL_ADMIN', true );

FORCE_SSL_ADMIN zorgt dat WordPress HTTPS afdwingt op de admin en de loginpagina's, en dat wil je ook op elke productiesite. Het probleem ontstaat als de site helemaal niet echt op HTTPS bereikbaar is: er is geen certificaat, Cloudflare staat op Flexible, of de load balancer doet wel TLS-terminatie maar praat daarna via HTTP met de origin zonder een X-Forwarded-Proto-header te zetten. WordPress ziet dan een HTTP-request, probeert die naar HTTPS te sturen, krijgt er van de proxy weer een HTTP-request voor terug, en daar begint de lus.

Heeft de site een werkend HTTPS-certificaat en is Fix 2 al op orde, laat FORCE_SSL_ADMIN dan gewoon aan staan. Doet de proxy TLS-terminatie en stuurt hij het protocol niet door, zet dan dit boven de regel require_once ABSPATH . 'wp-settings.php';:

if ( isset( $_SERVER['HTTP_X_FORWARDED_PROTO'] ) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https' ) {
    $_SERVER['HTTPS'] = 'on';
}

Dit vertelt WordPress dat hij de X-Forwarded-Proto-header van de proxy mag vertrouwen, waardoor hij stopt met een request te upgraden die al HTTPS is. Doe dit alleen als jij de proxy zelf beheert én hij die header van inkomende clientrequests strip, anders kun je het protocol spoofen.

Verificatie: gooi de cookies voor het domein weg en ga naar /wp-admin/. Je hoort meteen bij het loginformulier uit te komen, niet pas na een rij redirects. In de Network-tab zie je: één 302 naar wp-login.php, dan een 200 op de loginpagina zelf.

Fix 5: zet plugins uit en zoek het conflict

Als niks van het bovenstaande de lus heeft veroorzaakt of opgelost, zijn er waarschijnlijk twee plugins die elkaar tegenspreken over de canonieke URL. Hernoem wp-content/plugins via SFTP naar wp-content/plugins_off. WordPress behandelt dat als "geen plugins geïnstalleerd" zonder dat er iets permanent wordt gedeactiveerd of instellingen verloren gaan.

Laad de site. Werkt hij weer? Hernoem de map terug naar plugins en zet in wp-admin plugins in groepjes uit: allemaal uit, herladen, en daarna telkens vier of vijf tegelijk weer aan. Zodra de lus terugkomt, zit de boosdoener in de laatste groep die je hebt aangezet. Binnen die groep zoek je hem één voor één op. SEO-plugins, "force HTTPS"-plugins en cacheplugins zijn de gebruikelijke verdachten. Heel af en toe doet een thema het vanuit functions.php; schakel dan tijdelijk over naar een standaardthema als Twenty Twenty-Four en test nog een keer.

Verificatie: met alleen de boosdoener uit, hoort de site weer in één request te laden. Kijk of de plugin een optiepagina heeft waar je canonieke of HTTPS-redirects kunt uitzetten. Veel plugins hebben een "niet redirecten, de server regelt het al"-schakelaar die per ongeluk aanstond.

Toch nog vast: hoe je hulp vraagt

Heb je alle vijf de fixes doorlopen en zit de lus er nog steeds in, stop dan met dingen veranderen en verzamel dit voordat je je host of een WordPress-engineer inschakelt:

  • De exacte foutmelding uit de browser en welke browserversie het is.
  • De redirectketen uit DevTools, met elke Location-header in volgorde.
  • Je huidige SSL-modus in Cloudflare (of een andere proxy) plus eventuele Page Rules of Transform Rules.
  • De inhoud van .htaccess (of het vergelijkbare nginx-locationblok als je op nginx draait).
  • De waardes van siteurl en home uit de databasequery uit de diagnosestap.
  • Of FORCE_SSL_ADMIN in wp-config.php staat.
  • De actieve plugins en het actieve thema, en of alle plugins uitzetten de lus oploste.
  • Recente wijzigingen: een certificaatvernieuwing, een WordPress core-update, een plugininstallatie, een DNS-wijziging of een migratie naar een andere host.

Zo maak je van een "hij doet het niet"-ticket meteen een inhoudelijk gesprek en scheelt dat flink in de tijd tot het opgelost is. Ligt de site écht plat en loop je klanten mis, dan verdient een managed WordPress-host hier zijn geld: die kan gewoon in de serverlogs kijken en ziet vaak binnen een paar minuten welke redirectregel het doet.

Zo voorkom je dat het nog eens gebeurt

Kies één plek om HTTPS en de canonieke redirect af te handelen en maak dat ook echt de enige plek. Op een site die via Cloudflare loopt betekent dat meestal "Full (strict)" plus een "Always Use HTTPS"-page rule, waarbij de origin en WordPress zelf niks meer afdwingen. Op een directe setup betekent het één rewrite in nginx of .htaccess, en plugins die hun handen thuishouden. Schrijf voor een migratie of een certificaatwissel de vier waardes op die ertoe doen (siteurl, home, de Cloudflare-SSL-modus en of FORCE_SSL_ADMIN aanstaat), zodat je achteraf weet waar ze naartoe moeten. De meeste lussen die ik zie, komen van een goedbedoelde plugin die een tweede laag redirect bovenop een setup heeft gelegd die het eigenlijk al goed deed.

Zie je dit tegelijk met een fatal-error-scherm, dan dekt het artikel over de kritieke fout op deze website de WordPress-kant van zo'n fatal error, die soms opduikt na hetzelfde soort pluginconflict.

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.