Table of contents
- Quick summary
- Why two live hosts split what an agent indexes
- Step 1: Pick one canonical host
- Step 2: Add the redirect, on your stack
- nginx
- Cloudflare
- Vercel
- Netlify
- Next.js (self-hosted)
- WordPress
- Step 3: Verify it worked
- With AIScan
- By hand with curl
- Step 4: Add HSTS last
- Step 5: Align everything that names the host
- Common mistakes
- Keep it working
- Your next action
Type http://www.example.com/pricing into a terminal and count the hops it takes to reach the page. On a clean setup the answer is one, a single 301 straight to the canonical address. On many sites it is two or three, and on some it is zero because the page simply answers from a second host. This guide walks you through getting every variant of your address (http or https, www or apex) to land on one URL in a single permanent redirect, with copy-ready rules for nginx, Cloudflare, Vercel, Netlify, Next.js and WordPress. It takes about 20 minutes and one curl loop to confirm.
Agents and crawlers do not guess which of your two hosts is the real one. They index whatever they were handed, so a duplicate host means every page exists twice and every citation can point at either copy. AIScan's E4 check tests exactly this, and our 696-host study found 266 hosts serving a full copy from both the bare domain and the www host. That post is the adoption count. This one is the fix, host by host.
Quick summary
| If you want to... | Do this | Check it with | Time |
|---|---|---|---|
| Stop serving two copies | Pick one host, 301 the other to it | curl -sIL on both hosts | 10 min |
| Upgrade plain HTTP | One site-wide 301 to https:// | curl -sI http://... shows 301 | 5 min |
| Avoid chains | Send every variant straight to the final URL | hop count of 1 | 5 min |
| Pin HTTPS in browsers | Add Strict-Transport-Security after the redirects work | header present on the final response | 2 min |
Expert recommendation: Google's guidance on duplicate URLs says to "use permanent redirects to tell Google that a redirected URL is a worse version than the URL it redirects to".
Best for most sites: a redirect at the edge (CDN, host or load balancer) rather than inside the app, so every app behind it inherits the rule.
Why two live hosts split what an agent indexes
Think of your domain as a street address. example.com and www.example.com are two doors to the same building. A person walks in either one and never notices. A crawler that finds a link to each door files two buildings, then has to work out which is the original. Google says it will make that call for you, using redirects, rel="canonical" tags and sitemap entries as signals. An AI agent gets no such second chance: it fetches the URL it was given, and that URL is what it cites.
Three things go wrong when both doors stay open:
- Duplicate crawl budget. Every page is fetched twice, once per host.
- Ambiguous citations. An answer engine may quote the www URL while your sitemap lists the apex.
- Chains that cost time.
http://wwwtohttps://wwwtohttps://is two round trips before the first byte of content.
We probed 14 well-known domains on 11 October 2026 from one datacenter IP, starting from http://, http://www. and https://www. and following redirects. None served a second copy that we could see (canva.com answered 403 to the www request, so its row shows only what was observable). Chains are the common finding: the worst starting variant took two or more hops on 9 of the 14.
| Site | Worst-case hops | Final host | First-hop status seen |
|---|---|---|---|
| aiscan.site | 1 | apex | 301 (http), 302 (www) |
| cloudflare.com | 1 | www | 301 |
| anthropic.com | 1 | www | 301 |
| shopify.com | 1 | www | 301 |
| openai.com | 1 | apex | 301, 308 |
| stripe.com | 2 | apex | 301 |
| vercel.com | 2 | apex | 308 |
| nextjs.org | 2 | apex | 308, 307 |
| wordpress.org | 2 | apex | 301 |
| linear.app | 2 | apex | 301 |
| allbirds.com | 2 | www | 301 |
| netlify.com | 2 | www | 301 |
| canva.com | 2 | www | 301, 403 |
| notion.so | 3 | notion.com | 301, 307 |
Two details stand out. Both nextjs.org and notion.so answer a www HTTPS request with a 307, which is a temporary redirect, and www.aiscan.site answers with a 302. A temporary status tells a crawler the move may be undone, so it weakens the signal you are trying to send. Use 301 or 308. We found that on our own host, and it is on the list of things we fix.
Step 1: Pick one canonical host
Either choice works. The rule is to choose once and write it down.
| Choose | When | Watch out for |
|---|---|---|
Apex (example.com) | New site, short URLs, no CDN CNAME needs | Some DNS hosts cannot put a CNAME on the apex |
www (www.example.com) | You use a CNAME-based CDN or host | Printed material and links often omit the www |
Vercel's own domain documentation recommends www as primary with a redirect from the apex to it. Our probe shows large sites split both ways, so pick the host your platform makes easiest and stay with it.
Action: whichever you pick, make sure both hostnames have a valid TLS certificate. A redirect cannot fire if the browser stops at a certificate error first.
Step 2: Add the redirect, on your stack
All snippets below send the www host to the apex. Swap the two names to go the other way.
nginx
# Port 80: both names jump straight to the final HTTPS URL
server {
listen 80;
listen [::]:80;
server_name www.example.com example.com;
return 301 https://example.com$request_uri;
}
# Port 443: only the host you are retiring needs a redirect
server {
listen 443 ssl;
server_name www.example.com;
ssl_certificate /etc/ssl/www.example.com.pem;
ssl_certificate_key /etc/ssl/www.example.com.key;
return 301 https://example.com$request_uri;
}
The port 80 block is what makes http://www.example.com take one hop instead of two. $request_uri keeps the path and query string. Your real server block for the apex on port 443 stays as it is. The certificate paths above are placeholders.
Cloudflare
- Open the zone, then SSL/TLS > Edge Certificates and turn on Always Use HTTPS.
- Open Rules > Redirect Rules (menu labels shift slightly between dashboard versions) and choose to create a rule with a wildcard pattern.
- Set Request URL to
https://www.*, Target URL tohttps://${1}, Status code to301, and enable Preserve query string.
That is the pattern in Cloudflare's www-to-root example, which only matches HTTPS requests. Always Use HTTPS handles the plain-HTTP half, so http://www still takes two hops (HTTP to HTTPS, then www to apex). To make it one, add a second wildcard rule on http*://www.* with target https://${2}, then confirm with the hop count in the verification step. Cloudflare recommends against redirecting at the origin as well, because that can cause redirect loops.
Vercel
- Open the project, then Settings > Domains.
- Select Edit on the domain you want to redirect from.
- In the Redirect to dropdown choose the canonical domain.
In our probe vercel.com answers with 308, a permanent redirect that keeps the request method.
Netlify
Netlify adds both the apex and the www name when you assign either one. Put these lines in a _redirects file in your publish folder. The ! forces the rule even if a file exists at that path, and HTTP and HTTPS need separate lines unless you force SSL:
http://www.example.com/* https://example.com/:splat 301!
https://www.example.com/* https://example.com/:splat 301!
http://example.com/* https://example.com/:splat 301!
Netlify documents this pattern as domain-level redirects.
Next.js (self-hosted)
// next.config.js
module.exports = {
async redirects() {
return [
{
source: '/:path*',
has: [{ type: 'host', value: 'www.example.com' }],
destination: 'https://example.com/:path*',
permanent: true,
},
]
},
}
permanent: true makes Next.js send a 308. Do this at the edge if you can, since a redirect inside the app adds a full request to your server.
WordPress
WordPress normally redirects other hostnames to the address saved under Settings > General. Set WordPress Address (URL) and Site Address (URL) to the same canonical form (for example https://example.com), save, then test both hosts. If your host or a caching layer also redirects, make sure the two agree, or you will build a loop.
If you manage SEO from a plugin, ThinkRank is the one we recommend here: it writes canonical tags, the sitemap and robots meta from one place, and it migrates from Rank Math, Yoast, AIOSEO and SEOPress without re-entering settings. Yoast and Rank Math also write canonical tags and sitemaps well. None of them replaces the server redirect, which is what E4 grades.
Step 3: Verify it worked
With AIScan
Run npx aiscan-cli example.com or paste the address at aiscan.site. It is free and needs no account. E4 reports four facts: the final origin, whether plain HTTP upgrades, whether the other host redirects to the canonical one, and whether HSTS is set. The same scan also covers D1 (robots.txt, which should advertise a Sitemap URL on the host you just chose) and D2 (the sitemap itself). Success looks like "http:// upgrades to https" and "redirects to the canonical host".
What the scan cannot see: it checks the homepage, so it will not catch a deep path that redirects to the wrong place. Use the manual loop for that.
By hand with curl
If you would rather check by hand, this loop prints every hop for each variant:
for u in http://example.com/ http://www.example.com/ https://www.example.com/ \
"http://www.example.com/pricing?utm_source=test"; do
echo "== $u"
curl -sIL -o /dev/null -w '%{num_redirects} hops -> %{url_effective} (%{http_code})\n' "$u"
curl -sI "$u" | grep -i -E '^(HTTP|location)'
done
Pass criteria:
- Every variant ends at the same
url_effectivewith200. num_redirectsis1for each variant. Two is acceptable, three is a chain to fix.- The first status is
301or308, never302or307. - The path and query string survive. In our run of seven large sites,
?utm_source=xreached the final URL on all seven.
Add a control: request https://example.com/nope-123 and confirm you get a real 404, not a redirect to the homepage. A catch-all redirect would make every check above look like it passes.
Step 4: Add HSTS last
HSTS tells browsers to use HTTPS for your host without asking first. MDN documents the header as Strict-Transport-Security: max-age=<seconds>, with optional includeSubDomains and preload. A year is max-age=31536000. Preload needs at least that value plus includeSubDomains.
Add it only after the redirects work. Cloudflare warns that if you turn HSTS on before your site fully supports HTTPS, visitors lose access for the length of the max-age. Start with a short value such as max-age=300, then raise it. In the dashboard it lives under SSL/TLS > Edge Certificates > HTTP Strict Transport Security (HSTS).
HSTS does not replace the redirect. The E4 study found hosts that pass without it, because the redirect is what removes the duplicate.
Step 5: Align everything that names the host
After the redirect works, make the other signals agree. Canonical tags, sitemap entries, og:url and internal links should all use the canonical host. Mixed signals are how an old host keeps surfacing. Our sitemap guide covers the sitemap side, and the Link header guide shows another place a host name can leak.
Common mistakes
- Redirecting to a path, not a host.
www.linear.applands on/homepagein our probe while the apex serves/. Redirect the host and keep the path. - Dropping the query string. Campaign tags vanish and analytics split.
- Redirecting in two places. The CDN and the origin both add a rule and the browser reports too many redirects.
- Using 302 or 307 for a permanent move. The signal is weaker.
- Forgetting the certificate on the redirecting host.
Keep it working
Re-scan after every DNS, CDN or hosting change, since these are the moments a rule gets dropped. Our monitoring guide shows how to schedule it.
Your next action
Run the scan on your own domain and read the E4 line, then the D2 line. If either is partial, apply Step 2 for your stack and re-run. The full list of discoverability checks is on the checks page, and more fix guides are in /guides.
Frequently asked questions
Should I redirect www to the apex domain or the other way round?
Either works. Google's canonicalization documentation asks you to pick one URL variant and redirect the others to it, and it does not prefer a host. Choose the one your platform makes easiest (Vercel recommends www as primary, many CDNs need a CNAME that favors www) and keep it everywhere: sitemap, canonical tags, internal links.
Which status code should the redirect use, 301 or 308?
Either is a permanent redirect. 301 is the classic choice and 308 is the stricter version that preserves the request method, which is what Vercel and Next.js send. Avoid 302 and 307, which mean temporary. In our 11 October 2026 probe, www.aiscan.site, nextjs.org and notion.so each answered a www HTTPS request with a temporary code.
My browser says 'too many redirects'. What happened?
Two layers are redirecting in opposite directions, usually a CDN rule and an origin rule, or WordPress pointing at www while the CDN sends www to the apex. Turn one off. Run curl -sIL on the URL and read the Location lines to see where the loop starts. With Cloudflare, do the redirect there and not at the origin.
The scan says the alternate host serves its own copy. What do I fix?
That is the E4 duplicate-origin result: the other host answers 200 with a full page instead of redirecting. Add a permanent redirect from that host to the canonical one, using the snippet for your stack above. An unreachable alternate host is fine, because E4 only penalizes a second host that serves content.
curl shows the right final URL but three redirects. Is that a problem?
It still passes E4, but it is a chain, and each hop adds a round trip before content. Usually the HTTP and www fixes are separate rules. Add a rule that matches the plain-HTTP www variant and sends it straight to the final HTTPS URL.
My redirect works in a browser but curl shows a 200 on the www host. Why?
Browsers remember HSTS and old 301s in their cache, so they can jump to HTTPS or the apex without asking the server. curl asks every time. Trust the curl result, and test in a private window to confirm.
Do I need HSTS if the redirects already work?
No. The E4 study found 187 of 696 hosts passing without HSTS, because the redirect is what removes the duplicate. HSTS adds protection against downgrade attacks on later visits. Add it after the redirects work, starting with a short max-age.
Will the redirect hurt my search rankings or my analytics?
A permanent host redirect is the method Google lists first for consolidating duplicate URLs, and it keeps the path and query string if your rule includes them. Analytics can briefly show a traffic shift between hostnames, and campaign tags are lost if the rule drops the query string, so test that with a utm parameter before you ship.
Related guides
What a Failing AIScan Check Really Says: 2,961 Fail Lines Audited
A failing check on a scan report is supposed to be an instruction. The site owner reads the line, knows what the scanner asked for, knows what came back, and knows what to change. We audited whether…
Rate-limit AI crawlers without blocking them
Most advice on rate limiting AI crawlers stops at "add a limit". The part that costs you is where the limit applies and what it answers. A limit that covers /robots.txt and /llms.txt makes your own…
Which Agent-Readiness Checks Travel Together: 739 Sites, Three Bundles
Fix one agentreadiness check and a second one often moves with it. Fix another and nothing else changes. A scan report lists every check as its own line, so the reader cannot see which lines are…
Platform League Table: WordPress, Next.js, Astro and Shopify Across 728 Sites
Every few weeks someone asks which platform produces the most agentready sites. WordPress, Next.js, Astro and Shopify all have fans, and a ranked table is the answer people expect. We have the data…
