Skip to content
S-06

Redirects are wrong

ERR_TOO_MANY_REDIRECTS, pages sending you to the wrong address, or a loop.

Do this first

Your first three moves

  1. Trace the loop: curl -sIL https://yoursite.com lists every hop with its status code and Location header.
  2. Make siteurl and home identical, including https and www. Check them with wp option get siteurl and wp option get home.
  3. Behind Cloudflare? Flexible SSL plus a server HTTPS redirect loops forever. Switch to Full (strict) with a real certificate.

Diagnose it

Work out what is really wrong

What you are seeing

A redirect problem is either a loop (the browser gives up) or a wrong destination (you end up somewhere you did not mean to go). The browser messages for a loop:

  • Chrome: This page isn't working. example.com redirected you too many times. with ERR_TOO_MANY_REDIRECTS
  • Firefox: The page isn't redirecting properly
  • Safari: Safari Can't Open the Page because too many redirects occurred

Wrong destinations include: the old domain or the staging site after a migration; /wp-admin/install.php; the host’s default page; the home page instead of the page you asked for; a similarly named post; or a spam site, often only for visitors coming from Google.

The status code says what kind of redirect it is:

CodeTypeWhat to know
301PermanentBrowsers cache it, sometimes for a long time. A mistaken 301 keeps working in your browser after you fix the server.
308PermanentLike 301, but the request method (such as a form POST) must stay the same.
302TemporaryNot cached by default. Google treats it as a weak signal for which URL to index.
307TemporaryLike 302, keeping the request method. In Chrome DevTools, 307 Internal Redirect with Non-Authoritative-Reason: HSTS is the browser itself forcing HTTPS, not your server.

Confirm it in two minutes

1. See which layer sends each hop.

curl -sIL https://example.com/PAGE_PATH | grep -iE '^(HTTP|location|server|x-redirect-by|cf-ray)'

Run it on your own computer’s terminal. Replace example.com with your domain and PAGE_PATH with the page that redirects wrongly (leave it out for the home page). -L follows each redirect; -I shows headers only. The x-redirect-by header names who sent the hop: WordPress adds X-Redirect-By: WordPress, and some plugins add their own name. A hop with a different server header or a cf-ray line came from the CDN, not your server.

2. Test all four versions of the address.

for u in http://example.com http://www.example.com https://example.com https://www.example.com; do echo "$u"; curl -sIL -o /dev/null -w '  %{num_redirects} hops, ends at %{url_effective} (%{http_code})\n' "$u"; done

Run it on your own computer (macOS or Linux terminal). Replace all four example.com entries. Good: all four end at the same address with a 200, in one or two hops. Bad: different end points, a loop, or three or more hops.

3. Look for hard-coded addresses in wp-config.php.

wp config get WP_HOME
wp config get WP_SITEURL
grep -nE 'Redirect|RewriteRule' .htaccess

Run these in an SSH terminal inside the site’s folder (the one with wp-config.php). The first two print the address if wp-config.php overrides the database setting; an error saying the constant is not defined is normal. If they are defined, editing the address in Settings, General does nothing. The grep lists every redirect rule in .htaccess with its line number.

4. Rule out your own browser. Open the URL in a private window. If it works there but not in your normal window, your browser cached an old 301.

Most likely causes, in order

  1. Two layers fighting over HTTPS or www. Tell: in check 1 the hops alternate (http to https and back, or www to non-www and back), with different server or x-redirect-by headers. Fix: pick one layer to do the redirect (server or CDN) and turn off the rest. The redirect loop field guide covers the proxy cases.
  2. A cached 301 in your browser. Tell: curl shows the right result, your browser does not, and a private window works. Fix: clear that site’s data in the browser. Visitors who saw the bad 301 may need the same, so fix permanent redirects carefully.
  3. The old domain or staging URL left behind after a migration. Tell: location points to the old address. Fix: correct WP_HOME and WP_SITEURL if set, the site address in the database, and any rules in a redirect plugin.
  4. WordPress cannot find its tables. Tell: location: https://example.com/wp-admin/install.php. The database is empty or $table_prefix in wp-config.php does not match the imported tables. Fix: correct the prefix or re-import. Do not run the installer.
  5. WordPress guessing a URL. Tell: a missing page lands on a similarly named post, with X-Redirect-By: WordPress. Fix: add a proper redirect for the old URL. To turn guessing off, add add_filter( 'do_redirect_guess_404_permalink', '__return_false' ); in a small custom plugin.
  6. Leftover rules outside WordPress. Tell: the hop arrives before your server, from the registrar's domain forwarding or CDN redirect rules. Fix: remove the old forwarding or rule.
  7. A malicious redirect. Tell: only visitors from search, or on phones, are sent to an unknown domain, and you cannot reproduce it while logged in. Fix: treat it as a hack and follow the hacked site steps.

What it usually is not

  • DNS propagation. DNS does not redirect anything. The only exception is registrar URL forwarding, which shows up in check 1.
  • Something a new redirect plugin will fix. Adding another layer usually adds another hop to the loop.
  • Cookies. Clearing cookies rarely fixes a loop. It helps with login loops, which are a different problem.

What to send your host

  • The full output of checks 1 and 2.
  • The exact URL you start from and where you expected to land.
  • When it started, in UTC.
  • What changed: SSL install, CDN setup, migration, a panel "force HTTPS" option, a new plugin.
  • Whether a CDN or proxy sits in front, and its SSL mode.
  • The redirect lines from .htaccess or the server config.

The full fix

Field guides for this symptom

Search the field manual

What is going wrong?

Press / to search from any page, Esc to close