Pick www.example.com or example.com, serve the site on that one host, and permanently redirect the other with the path and query intact. Either choice works; the setups that cause trouble serve both hosts, or redirect between them inconsistently. What should decide it is how your DNS provider handles the apex, what your hosting platform recommends, how you scope cookies, and how far you plan to take HSTS.
What 12 sites actually do
On 26 September 2026 we requested http:// and https:// on both the apex and www of 12 sites, 11 well-known ones plus our own, from a workstation in South Korea. The run started at 14:42 UTC and was repeated at 14:43 UTC. Each hop was a separate curl -sI (a HEAD request, without -L), so every status code and Location header was recorded. The two runs matched, apart from one transient HTTP/2 error on www.microsoft.com that returned 200 on retry. Preload status comes from the hstspreload.org status API, queried at 14:44 UTC.
| Site | Canonical host | Status codes seen | From http:// on the other host |
HSTS on the canonical page | Preload API status |
|---|---|---|---|---|---|
| github.com | apex | 301 | 2 hops, via https://www |
max-age=31536000; includeSubdomains; preload |
preloaded |
| google.com | www | 301 | never reaches HTTPS | none | unknown |
| cloudflare.com | www | 301 | 1 hop | max-age=31536000; includeSubDomains |
preloaded |
| vercel.com | apex | 308 | 2 hops, via https://www |
max-age=31536000; includeSubDomains; preload |
preloaded |
| netlify.com | www | 301 | 2 hops, via the https:// apex |
max-age=31536000; includeSubDomains; preload |
preloaded |
| stripe.com | apex | 301 | 2 hops, via https://www |
max-age=63072000; includeSubDomains; preload |
preloaded |
| wikipedia.org | www | 301 | 2 hops, via the https:// apex |
max-age=106384710; includeSubDomains; preload |
preloaded |
| apple.com | www | 301 | 1 hop | max-age=31536000; includeSubdomains; preload |
unknown |
| microsoft.com | www | 307, 301 | 2 hops, via the https:// apex |
none | unknown |
| mozilla.org | www | 302, 301 | 2 hops, via the https:// apex |
max-age=31536000 |
unknown |
| python.org | www | 301 | 1 hop | max-age=63072000; includeSubDomains; preload |
preloaded |
| and.guide | apex | 301 | 1 hop | none | unknown |
“From http:// on the other host” counts the redirects from the plain-HTTP URL of the non-canonical host to the canonical HTTPS URL. The API returned preloaded for seven domains and unknown for the other five, none of which it lists as preloaded.
Live capture, 26 September 2026. Two ways to get from plain HTTP on the apex to https://www:
$ curl -sI http://netlify.com/
HTTP/1.1 301 Moved Permanently
Location: https://netlify.com/
Server: Netlify
$ curl -sI https://netlify.com/
HTTP/2 301
location: https://www.netlify.com/
server: Netlify
strict-transport-security: max-age=31536000; includeSubDomains; preload
$ curl -sI http://cloudflare.com/
HTTP/1.1 301 Moved Permanently
Location: https://www.cloudflare.com/
Server: cloudflare
Netlify upgrades the scheme on the apex first and attaches its HSTS policy to the apex’s HTTPS redirect. Cloudflare sends plain-HTTP visitors straight to the final URL in one step.
Live capture, 26 September 2026. The status codes other than 301 that we saw:
$ curl -sI http://www.vercel.com/
HTTP/1.0 308 Permanent Redirect
Location: https://www.vercel.com/
server: Vercel
$ curl -sI https://www.vercel.com/
HTTP/2 308
location: https://vercel.com/
server: Vercel
strict-transport-security: max-age=63072000; includeSubDomains; preload
$ curl -sI http://mozilla.org/
HTTP/1.1 302 Found
Location: https://mozilla.org:443/
What the table supports, and what it does not:
- Both choices are common. Eight sites use
wwwand four use the apex. The list is hand-picked, not a sample, so read it as an illustration rather than a statistic. Vercel’s documentation recommendswww, yet vercel.com itself runs on the apex; the recommendation is about how Vercel’s network steers traffic, not a rule. - Host changes were always permanent. Every apex-to-www or www-to-apex redirect was a 301, or a 308 at Vercel. Temporary codes appeared only on scheme upgrades: 302 at mozilla.org and 307 at microsoft.com.
- Hop counts vary. Seven sites need two hops from a plain-HTTP non-canonical URL and four need one. google.com never reached HTTPS for our client:
http://google.com/redirected tohttp://www.google.com/, which answered 200 over plain HTTP, as didhttp://www.microsoft.com/. Our requests carried no HSTS state and no preload list, so these rows show what a first-time client that does not upgrade on its own sees. - HSTS is common but uneven. Nine of the 12 sent HSTS on the canonical page and seven are preloaded. mozilla.org’s canonical policy has no
includeSubDomains.
The DNS constraint at the apex
RFC 1034 says a name that owns a CNAME record should own no other data. The apex always owns SOA and NS records, so a standard CNAME cannot live there. Many DNS providers offer a workaround, such as CNAME flattening or an ALIAS-style record that resolves the target and answers with addresses; our guide to CNAME flattening explains how they differ. Without one, the apex needs A and AAAA records that point at your platform’s addresses, while www can use a CNAME.
That constraint shapes what platforms recommend:
| Platform | What its documentation recommends |
|---|---|
| Vercel | Make www the primary domain and redirect the apex to it, so a CNAME lets Vercel’s CDN steer traffic; the reverse works too but gives Vercel less control |
| Netlify | With external DNS, make www the primary domain, because apex resolution through third-party DNS can hurt performance; with Netlify DNS, both perform equally |
| GitHub Pages | If you use the apex, also set up www; the apex takes four A and four AAAA records and www a CNAME to your github.io host |
Cloudflare Pages handles apex and subdomain custom domains differently; our Cloudflare Pages custom domain guide covers both paths. If your DNS host cannot flatten the apex and your platform wants a CNAME, www is the path of least resistance.
Cookies follow the Domain attribute, not the hostname
Cookie isolation is a classic argument for www. Under RFC 6265, the Domain attribute decides where a cookie goes:
- A cookie set without
Domainis returned only to the host that set it, so an apex site’s host-only cookies never reachstatic.example.com. - A cookie with
Domain=example.comis sent toexample.comand to every name under it, however deep, no matter which host is canonical.
The canonical host does not decide cookie scope; the attribute does. The old argument does have a basis: RFC 6265 itself warned that some user agents of its day treated a missing Domain as the current host name and sent apex cookies to www as well. If such clients still matter to you, a www host sidesteps the problem.
In practice, audit every Set-Cookie header for Domain=. Anything scoped to the registrable domain reaches every subdomain, including any you point at third-party services.
HSTS: includeSubDomains ties the two hosts together
RFC 6797 defines includeSubDomains as extending a host’s policy to that host’s subdomains, which only works downward. A policy that a browser receives from www.example.com covers www.example.com and names beneath it. It never covers example.com, api.example.com, or any other sibling. Once a browser holds a policy, it rewrites http:// URLs for the covered hosts to https:// before loading them, including when following redirects, so returning visitors to those hosts skip the plain-HTTP request entirely.
To protect the whole domain through headers, the apex must send the policy with includeSubDomains over HTTPS, and browsers must load an HTTPS URL on the apex at least once. On an apex-canonical site that happens with every page view. On a www-canonical site the apex is only ever a redirect, so the redirect itself has to carry the policy.
The preload list’s submission requirements encode exactly this. Redirect HTTP to HTTPS on the same host; serve the HSTS header on the base domain with a max-age of at least 31,536,000 seconds, includeSubDomains, and preload; and if the HTTPS site redirects elsewhere, that redirect must carry the header. For a www site, first-time plain-HTTP visitors therefore take two hops: http://example.com/ to https://example.com/ to https://www.example.com/. hstspreload.org also warns that a removal from the list takes months to reach users.
Here is what the apex told browsers on the eight www-canonical sites in our survey:
| Site | http:// apex goes first to |
HSTS on the https:// apex redirect |
|---|---|---|
| netlify.com | 301 to https://netlify.com/ |
max-age=31536000; includeSubDomains; preload |
| wikipedia.org | 301 to https://wikipedia.org/ |
max-age=106384710; includeSubDomains; preload |
| microsoft.com | 307 to https://microsoft.com/ |
max-age=31536000 |
| mozilla.org | 302 to https://mozilla.org:443/ |
max-age=60; includeSubDomains |
| cloudflare.com | 301 to https://www.cloudflare.com/ |
max-age=15780000; includeSubDomains |
| python.org | 301 to https://www.python.org/ |
max-age=315360000; preload |
| apple.com | 301 to https://www.apple.com/ |
none |
| google.com | 301 to http://www.google.com/ |
none |
Only netlify.com and wikipedia.org follow the full pattern. microsoft.com and mozilla.org upgrade on the apex first, but their apex policies either omit includeSubDomains or last 60 seconds. cloudflare.com and python.org are preloaded, yet they send plain-HTTP apex visitors straight to https://www, so being on the list is not proof that a domain meets today’s submission checks. Several sites (stripe.com, www.apple.com, and python.org) also attach HSTS headers to plain-HTTP responses; RFC 6797 tells browsers to ignore the header there, so it does nothing.
If you do not plan to preload, sending plain-HTTP visitors straight to the canonical HTTPS URL in one hop is simpler and faster. Our teardown of and.guide measured what an extra connection to a redirect host costs. For staging includeSubDomains and preload safely, see HSTS preload and subdomains.
Search engines: one host, permanent redirects, matching signals
Google treats redirects and rel="canonical" as strong canonicalization signals and sitemap inclusion as a weak one, and it prefers HTTPS over HTTP unless other signals conflict. Its redirect documentation says 301 and 308 tell the indexing pipeline that the target should be canonical, while 302, 303, and 307 do not. Google also advises against choosing a canonical with robots.txt or noindex, and against pointing different methods at different URLs.
For a host choice, that means:
- A permanent redirect (301 or 308) from every non-canonical variant, keeping the path and query.
- An absolute
rel="canonical"URL on the canonical host in every page. - Sitemaps that list only canonical-host URLs.
- Internal links on the canonical host, so crawlers and readers rarely hit a redirect.
Choosing between 301 and 308 comes down to request methods. RFC 9110 still allows a client to change a POST into a GET when it follows a 301 or 302, and points to 308 and 307 when that is undesirable. For page navigation the two behave alike; if forms or API clients might post to the non-canonical host, a 308 keeps the method and body.
Setting it up on four platforms
Cloudflare
For a zone on Cloudflare, the documented “Redirect from WWW to root” example is a Single Redirect with a wildcard pattern:
Request URL: https://www.*
Target URL: https://${1}
Status code: 301
Preserve query string: enabled
As documented, the pattern matches only HTTPS requests, so decide separately how http://www requests are upgraded.
Cloudflare’s Pages documentation uses an account-level Bulk Redirect instead, plus a proxied placeholder record so that www traffic reaches Cloudflare at all:
Source URL: www.example.com
Target URL: https://example.com
Status code: 301
Parameters: preserve query string, subpath matching, preserve path suffix, include subdomains
DNS record: A www 192.0.2.1 (Proxied)
A Bulk Redirect source without a scheme matches both http and https, so one rule takes plain-HTTP www visitors to the HTTPS apex in a single hop.
Vercel
Add both hosts to the project; adding an apex domain prompts you to add its www counterpart. Open Domains in the project settings, select Edit on the host you are leaving, and pick the canonical host in the Redirect to dropdown. Vercel says it attempts the www/non-www redirect automatically, but notes you may still want to add it explicitly. In our survey, vercel.com’s own redirects were 308s.
Netlify
Assign the host you want as the primary domain. Assigning either the apex or www as primary adds both to the Production domains panel, and Netlify automatically redirects the other one to the primary. To switch later, choose Options and then Set as primary domain next to the domain. The documentation does not state the status code; netlify.com’s own redirects in our survey were 301s.
GitHub Pages
Set the canonical host as the site’s custom domain, then publish DNS for both names:
example.com. 3600 IN A 185.199.108.153
example.com. 3600 IN A 185.199.109.153
example.com. 3600 IN A 185.199.110.153
example.com. 3600 IN A 185.199.111.153
example.com. 3600 IN AAAA 2606:50c0:8000::153
example.com. 3600 IN AAAA 2606:50c0:8001::153
example.com. 3600 IN AAAA 2606:50c0:8002::153
example.com. 3600 IN AAAA 2606:50c0:8003::153
www.example.com. 3600 IN CNAME your-user.github.io.
With records for both names in place, GitHub redirects the other name to the custom domain automatically: set www.example.com as the custom domain and the apex redirects to it, or the reverse. GitHub also warns against wildcard records such as *.example.com because they put you at risk of domain takeover. Our GitHub Pages custom domain guide covers verification and HTTPS.
A short decision table
| If this describes you | Lean | Why |
|---|---|---|
| Your DNS host cannot flatten or alias the apex, and your platform wants a CNAME | www |
A standard CNAME cannot sit at the apex |
| You host on Vercel, or on Netlify with external DNS | www |
Both platforms’ documentation recommends it |
| Your DNS supports flattening or ALIAS and you want the shortest URL | apex | The bare domain people type is the final host, with no host redirect |
| You need cookies shared across subdomains | either | The Domain attribute decides scope, not the host |
| You plan to preload HSTS | either | The apex must serve HTTPS with includeSubDomains; a www site needs the two-hop upgrade |
| One host already has years of links and rankings | keep it | Switching means redirecting every URL again |
Check your own setup
for u in http://example.com/ https://example.com/ http://www.example.com/ https://www.example.com/; do
echo "== $u"
curl -sI "$u" | grep -iE '^(HTTP/|location:|strict-transport-security:)'
done
curl -sI 'http://www.example.com/pricing?plan=pro' | grep -i '^location:'
curl -s https://example.com/pricing | grep -oE '<link[^>]*rel="canonical"[^>]*>'
Follow each Location by hand, as we did for the survey, and confirm that:
- every non-canonical URL ends on the canonical HTTPS URL, with a 301 or 308 wherever the host changes;
- the path and query string survive every hop;
- the canonical host’s HTTPS responses carry your HSTS header, and for a
wwwsite you plan to preload, so does thehttps://apex redirect, reached fromhttp://on the apex first; - the
rel="canonical"URL uses the same host your redirects end on.