Skip to content

Visitors pass through several redirects before the page

Warning Whole domain Security

General instructions. Open this article from your PageCheck report to see it filled in with the redirect chains found on your site and the rule for your hosting (Cloudflare, Plesk, cPanel, Apache or nginx).

What it is

A website has four root addresses: with and without www, over http:// and over https://. Visitors type any of them, old links and search results point to any of them. Only one serves the page; the other three should send the visitor there with a single permanent (301) redirect, straight to the https:// address and never through http:// on the way.

Every extra redirect is a full round trip to the server before the page can even start to load, and Google asks for no more than one. A hop from https:// back to http:// puts a first-time visitor on an unencrypted connection that anyone on the same network can read or redirect.

What is wrong

One or more of the root addresses take two or more redirects to reach the page, pass through plain http:// on the way, use a temporary redirect, end on another website or never reach a page at all.

How to fix

1. Decide the one final address and make sure HTTPS works on every name. The page is served at https://example.com, so that is the address every other one should point to. Before adding any redirect, open https:// on the other name (www.example.com) in a browser: it must show no certificate warning. Let's Encrypt and Cloudflare's certificates cover both names when both are listed; if one is missing, add it to the certificate first, or every redirect from that name will start with a warning.

2. Set one permanent redirect from every other root address straight to the final one. Use the rule for where your site answers (your host can tell you): one rule that handles the scheme and the www in the same step, not two rules one after the other. Use a 301, never a 302 or 307, and keep the path and the query string.

Apache or LiteSpeed (also Plesk and cPanel hosts with Apache): in the .htaccess file in the site's main folder, above the "# BEGIN WordPress" line

RewriteEngine On
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} ^www\.example\.com$ [NC]
RewriteRule ^ https://example.com%{REQUEST_URI} [R=301,L]

nginx: the site's server blocks

server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;
    return 301 https://example.com$request_uri;
}
server {
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name www.example.com;
    # the certificate must cover www.example.com
    return 301 https://example.com$request_uri;
}

Cloudflare, if the site is behind it: Rules → Redirect Rules → Create rule

When incoming requests match (custom filter expression):
    http.host eq "www.example.com"

Then: Dynamic redirect, status code 301, preserve query string:
    concat("https://example.com", http.request.uri.path)
  • Plesk: Websites & Domains → Hosting Settings: set "Preferred domain" to the form you chose (https://example.com) and tick "Permanent SEO-safe 301 redirect from HTTP to HTTPS". Plesk then sends every other root address to the final one in one step.
  • cPanel: Domains → Redirects: a permanent (301) wildcard redirect from the other name to the final address, "Redirect with or without www" — or the .htaccess rule above.
  • If a CDN or load balancer terminates HTTPS in front of the server, the server sees plain http:// and the .htaccess rule above loops. Test on the "X-Forwarded-Proto" header instead of %{HTTPS}, or set the redirect at the CDN as with Cloudflare.
  • Remove every other redirect rule for these addresses afterwards (an older "force HTTPS" plugin, a second control-panel redirect): two rules are what produce two hops.

3. Tell browsers to use https:// from the start. Once https:// works on both names, send the header Strict-Transport-Security: max-age=31536000; includeSubDomains on both of them. A browser that has visited once then never tries http:// again, so the http:// hop disappears for returning visitors. Add "preload" and submit the domain at hstspreload.org only when every subdomain works over HTTPS.

4. Check it. Ask each root address for its first answer; every one except the final address must answer 301 with the final address in "location", and the final address must answer 200:

In a terminal

curl -sI http://www.example.com/ | grep -i '^HTTP\|^location'
curl -sI https://www.example.com/ | grep -i '^HTTP\|^location'
curl -sI http://example.com/ | grep -i '^HTTP\|^location'
curl -sI https://example.com/ | grep -i '^HTTP\|^location'

Then run this check again: it follows all four addresses and lists every hop.

Make every root address of my website reach the page in one permanent redirect: http://www.example.com/, https://www.example.com/ and http://example.com/ must each answer 301 straight to https://example.com (same path and query), never via http:// on the way, and https://example.com/ must answer 200.
The site is not known to be behind a CDN.

Steps:
1. Make sure the certificate covers example.com and www.example.com (no warning on https:// for either name).
2. Replace all existing redirect rules for these addresses with ONE rule that handles scheme and host in the same step: on Cloudflare a Single Redirect `http.host eq "www.example.com"` → `concat("https://example.com", http.request.uri.path)` (301, preserve query string) with Always Use HTTPS left on; on Apache/LiteSpeed a RewriteCond %{HTTPS} off [OR] / RewriteCond %{HTTP_HOST} ^www\.example\.com$ / RewriteRule ^ https://example.com%{REQUEST_URI} [R=301,L] block above # BEGIN WordPress; on nginx a port-80 server block for both names and a port-443 block for www.example.com, each `return 301 https://example.com$request_uri;`. Behind a TLS-terminating proxy test X-Forwarded-Proto, not %{HTTPS}.
3. Remove the other rules (control panel redirects, force-HTTPS / force-www plugins) so no address takes two hops.
4. Send `Strict-Transport-Security: max-age=31536000; includeSubDomains` on both names once https:// works on both.
5. Verify with curl -sI on all four root addresses: three answer 301 with location https://example.com/… in one hop, the final one 200; show me the output.
Tell me exactly which files or settings you changed.

Resources:
- Google Search Central, redirects and Google Search: https://developers.google.com/search/docs/crawling-indexing/301-redirects
- Cloudflare, Single Redirects: https://developers.cloudflare.com/rules/url-forwarding/single-redirects/

Check your site to see whether it has this problem. Check a website