You type https://yourdomain.com and the site loads. You type https://www.yourdomain.com and the same site loads, identical content. Both return 200. It looks fine, but to Google’s deduplication and to anything counting your backlinks, you have two sites with identical content competing against each other.
Fastest fix: pick one hostname as canonical, then make the other return a 301 redirect to it at the host/CDN level (not just an HTML <link rel="canonical"> tag). A canonical tag tells crawlers your preference; a 301 actually moves real visitors and backlink credit onto one URL. Confirm the fix with one command:
curl -sI https://www.yourdomain.com | grep -i -E "http|location"
You want to see 301 and a Location: header pointing at your canonical host. If you see 200, the redirect is not in place yet.
This is the harder cousin of www vs root redirect: there, one version never resolves; here, both already work, so you also have to clean up indexing and backlinks after wiring the redirect.
Why this actually matters (it is not cosmetic)
yourdomain.com and www.yourdomain.com are different hostnames, so search engines treat them as different URLs unless you tell them otherwise. Without a 301:
- Backlinks split between the two hosts, so neither accumulates full authority.
- Google picks its own canonical (it may not be the one you want — see Google’s canonicalization troubleshooting guide), and reporting in Search Console gets murky.
- Analytics, cookies, and any same-site auth can behave inconsistently across the two hosts.
Which bucket are you in?
Run the two curl checks below, then match the result to the cause.
| What you observe | Most likely cause | Where to fix |
|---|---|---|
Both hosts return 200 directly from your host | Both added as separate domains, no redirect set | Host dashboard (Vercel / Netlify / Firebase) |
Both 200, server is behind Cloudflare (proxied) | Both DNS records proxied, no redirect rule | Cloudflare Redirect Rules |
Both 200, HTML has a canonical tag | Canonical tag set but no HTTP 301 | Add the 301 at host/CDN level |
Both 200, self-hosted | One nginx/Apache server_name serves both | Add a redirect server block |
One returns 301, the other 200 | Redirect already correct — finish indexing cleanup | Search Console + internal links |
Diagnostic commands:
curl -sI https://yourdomain.com | head -5
curl -sI https://www.yourdomain.com | head -5
HTTP/2 200 on both means no redirect. HTTP/2 301 with a Location: header on one means that side is already redirecting.
Common causes
Ordered by hit rate, highest first.
1. Both versions added to the host without a redirect
You added both yourdomain.com and www.yourdomain.com as separate domains on Vercel/Netlify. The host serves both happily and does not set up a redirect by default.
How to spot it: Host dashboard → Domains → both look like equal “primary” entries. You want exactly one primary and one redirect.
2. CDN proxies both directly to origin
If Cloudflare (or another CDN) has both records as proxied A/AAAA/CNAME, both reach origin and serve content. The CDN does not redirect unless you add a rule.
How to spot it: both curl -sI checks above return 200. In the Cloudflare DNS tab both records show the orange “Proxied” cloud.
3. Host supports both bindings but will not infer a primary
Some hosts let you add both names but require you to manually pick the primary. They do not assume which one you want.
How to spot it: the host docs say “add both, then set one as primary” — and you stopped after adding both.
4. Canonical tag set but no HTTP redirect
You added <link rel="canonical" href="https://yourdomain.com/..."> on every page. The tag is a hint for Google, but visitors still see the host they typed, and raw backlinks still point at the non-canonical host.
How to spot it: both URLs return 200 (not 301). A canonical tag never redirects.
5. Self-hosted nginx/Apache serving both names
Older shared hosting or a hand-written config may have one server_name yourdomain.com www.yourdomain.com; block with no redirect rule. Both names work, and you have a duplicate-content problem.
How to spot it: SSH in and read the config. If server_name lists both names in one block with no separate redirect server block, that is the cause.
Shortest path to fix
Step 1: Pick the canonical host
Either choice is SEO-neutral — Google has confirmed there is no ranking difference. Pick on technical grounds:
- Apex (
yourdomain.com) for shorter URLs, if your DNS provider supportsALIAS/ANAME/flattened-CNAME at the apex. The DNS spec forbids a plainCNAMEon an apex record, which is why some hosts steer you toward www. - www (
www.yourdomain.com) for the simplest CDN setup, becausewwwis a normal subdomain and takes a plainCNAME. As of June 2026, Vercel explicitly recommends www as primary for exactly this reason (more CDN control over incoming traffic).
Decide once, write it down, and keep every internal link, sitemap entry, and canonical tag consistent with it.
Step 2: Configure the redirect at the host/CDN
Vercel — Project → Settings → Domains:
- Add both
yourdomain.comandwww.yourdomain.com(adding the apex auto-suggests its www counterpart). - Click Edit on the non-canonical domain, open the Redirect to dropdown, and select the canonical host.
- Vercel issues a
308/301-class permanent redirect automatically. (Vercel uses308by default, which preserves the method and is treated as permanent by search engines just like301.)
Netlify — Site configuration → Domain management → Domains:
- Add both names.
- Set the canonical one as primary domain; the other becomes a domain alias.
- Netlify auto-redirects the alias to the primary. This automatic behavior covers apex ↔ www only; other subdomains need manual redirect rules.
Firebase Hosting — when you add the second domain in the console, choose the “Redirect to an existing site/domain” option and point it at the canonical. For config-as-code, set a catch-all redirect in firebase.json on the non-canonical site and deploy with firebase deploy --only hosting:
{
"hosting": {
"redirects": [
{ "source": "**", "destination": "https://yourdomain.com", "type": 301 }
]
}
}
Cloudflare — Page Rules are legacy; use Redirect Rules. Dashboard path: Rules → Templates → “Redirect from WWW to Root” (or “Redirect from Root to WWW”) → Create a Rule. To build it by hand, go to Rules → Redirect Rules → Create rule and use a wildcard:
When incoming requests match: https://www.yourdomain.com/*
Then redirect to URL (dynamic): https://yourdomain.com/${1}
Status code: 301
Preserve query string: On
Note the modern token is ${1} (the older Page Rules used $1). Deploy the rule, and keep the matching DNS record proxied (orange cloud) so the rule actually runs.
Self-hosted nginx — split the redirect into its own server block:
server {
listen 443 ssl;
server_name www.yourdomain.com;
return 301 https://yourdomain.com$request_uri;
}
Then reload with nginx -t && systemctl reload nginx. Apache equivalent: a Redirect 301 / mod_rewrite rule scoped to the www VirtualHost.
Step 3: Verify the redirect
curl -sI https://www.yourdomain.com | head -5
You want:
HTTP/2 301
location: https://yourdomain.com/
308 from Vercel is also correct. A 200 means the redirect is not live yet. Also test a deep path so the redirect preserves it, not just the homepage:
curl -sI https://www.yourdomain.com/some-article/ | grep -i location
# expect: location: https://yourdomain.com/some-article/
Step 4: Make the HTML canonical tag agree
Your template’s canonical must point at the canonical host on every page:
<link rel="canonical" href="https://yourdomain.com/your-article/" />
Never the alternative host. A redirect plus a contradicting canonical tag sends mixed signals.
Step 5: Fix Search Console (the modern way)
If you verified the two hosts as separate URL-prefix properties, the cleanest fix is to add a single Domain property for yourdomain.com. A Domain property automatically consolidates http/https, www, and non-www, and all subdomains into one unified report, so you stop stitching numbers across two properties. Verify it once via the DNS TXT record Google gives you.
Keep the old URL-prefix properties if you like (handy for watching the non-canonical host drain), but treat the canonical host as primary.
Step 6: Confirm Google picked the right canonical
Open Search Console → URL Inspection, paste a non-canonical URL (e.g. https://www.yourdomain.com/your-article/), and check “User-declared canonical” vs “Google-selected canonical”. After the 301 is crawled, Google-selected should converge on your canonical host. Google explicitly notes it may pick a different canonical than you declared, so this check is the real proof — not the redirect alone.
Consolidation is gradual: over roughly 2–4 weeks Google re-crawls and moves link equity onto the canonical. In Search Console → Indexing → Pages, the non-canonical URLs should drift into the “Alternate page with proper canonical tag” / “Page with redirect” buckets.
How to confirm it is fully fixed
curl -sIon the non-canonical host returns301/308with the rightLocation:(root and a deep path).- The canonical host returns
200directly (it must not redirect to itself — that would loop). - URL Inspection shows Google-selected canonical = your chosen host.
- Over 2–4 weeks, indexed non-canonical URLs trend toward zero.
When it is not on you
A few host quirks are real: Firebase’s per-site model, Cloudflare’s apex-vs-subdomain proxy handling, and DNS providers that lack ALIAS/ANAME at the apex. If the host’s behavior contradicts its own docs, open a support ticket with your exact curl -sI output attached.
Easy to misdiagnose as
Setting the <link rel="canonical"> tag alone does not stop dual serving — both hosts still answer 200. Only the 301/308 at the host/CDN level consolidates real traffic and backlinks. If you “added a canonical tag” and both URLs still load, you have not finished the fix.
Prevention
- Decide www vs apex on day one of any new domain.
- Always set the redirect at the host/CDN level, not just in a canonical tag.
- After any DNS or hosting change, re-verify with
curl -sIthat one host301s to the other. - Use a single Search Console Domain property from the start so consolidation is automatic.
- For team-managed domains, record the canonical choice in a
DOMAIN.mdfile.
FAQ
- Is www or apex better for SEO? No ranking difference; Google has said so directly. Pick on technical grounds (apex needs
ALIAS/ANAME; www takes a plainCNAME). - My host returns
308, not301— is that wrong? No.308is a permanent redirect that also preserves the HTTP method. Vercel uses it by default and search engines treat it like301for consolidation. - Do I still need the canonical tag if the
301is live? Yes. The301handles visitors and crawlers that hit the wrong host; the canonical tag reinforces your choice and covers edge cases like parameterized URLs. - How long until Google consolidates? Usually 2–4 weeks of re-crawling. Watch the Google-selected canonical in URL Inspection rather than guessing.
- Can I switch the canonical later? Yes, but it means a redirect chain (old canonical → new canonical), canonical-tag updates, and 4–8 weeks for Google to fully shift. Do not switch casually.
- Both already redirect to each other and the site is down — why? You created a redirect loop (each host points at the other). The canonical host must return
200; only the non-canonical host should301.
Related
- Root domain vs www confusion
- Duplicate domain versions indexed
- HTTPS not forced
- Canonical mismatch bilingual
Tags: #Domain #DNS #SSL #Troubleshooting #Redirect