How this was measured
On 2026-09-24 we fetched https://<domain>/ for 78 well-known domains spanning news, commerce, SaaS, developer tooling, social, education, finance and government. 55 returned a usable page: 34 over a direct connection and 21 over a local proxy, because a number of these domains are unreachable from our network without one.
The other 23 could not be read. 14 answered with something other than 200 โ mostly 403, one 401, one 202, one timeout โ and 20 served a bot check or an interstitial instead of a page; the two groups overlap. One is worth naming: amazon.com answers 200 with a 2 KB page whose entire content is a bm-verify meta-refresh, not a homepage. Our first pass counted it as a real page and would have recorded Amazon as a site with no canonical. Re-reading the response is what caught it, and it is why every number below was checked against the raw HTML before it was written down.
For each page we took the <link rel="canonical"> from the initial HTML, resolved it against the URL we actually landed on after redirects, and compared the two after normalising: lowercased host, www stripped, trailing slash and index.html removed. We also captured the HTTP Link header, counted how many canonical tags each page ships, and recorded whether the tag sits before </head>. Then we made a second request to each canonical URL with redirects disabled, to see whether it points at a page that exists.
Finding 1: one homepage in five declares nothing
44 of the 55 pages (80%) declare a canonical. The other 11 declare none:
reddit.com, kubernetes.io, python.org, rust-lang.org, netflix.com, wikipedia.org, mozilla.org, w3.org, archive.org, wikimedia.org, airbnb.com
Two of those need an asterisk. reddit.com and archive.org returned client-rendered shells โ 8.4 KB and 1.9 KB with no content in them โ so a canonical injected by JavaScript would be invisible to a method that reads only the initial HTML. We cannot say they have no canonical; we can only say none is served with the document.
The other nine are server-rendered and full-sized, and the absence is real. Wikipedia, Mozilla, W3C and Python.org are not sites that forgot a tag through carelessness; for a homepage that is the most-linked URL on the domain, the duplicate-selection problem canonical solves is largely solved by the link graph anyway. airbnb.com is the interesting one: it ships <meta id="english-canonical-url" content="">, a canonical slot that arrived empty.
What the omission costs is narrow but real. Without it, /, /index.html, /?utm_source=newsletter and the http variant are four separate URLs that a crawler must choose between. It is one line of HTML to remove the question.
Finding 2: you have to follow the redirect first
43 of the 55 homepages (78%) redirected at least once before serving content, and 35 of the 44 that declare a canonical (80%) did. Some are ordinary www normalisation; several land on a different host entirely:
gitlab.com → about.gitlab.com, spotify.com → open.spotify.com, notion.so → notion.com, zoom.us → zoom.com, linkedin.com → www.linkedin.cn, cnn.com → edition.cnn.com.
This is the most common way to misread your own canonical. If you compare the tag against the URL you typed rather than the URL you were finally served, every one of those six looks like a cross-domain canonical pointing somewhere suspicious. They are not โ they are self-referencing canonicals on the page that actually exists. When you audit, audit against the final URL after redirects, which is what a crawler sees.
Finding 3: six of 44 point anywhere other than themselves
38 of the 44 canonicals (86%) resolve to exactly the URL we were served. The six that do not are the whole story of this survey:
cnn.com โ served edition.cnn.com, canonical https://www.cnn.com, which returns 200. This is geo consolidation done deliberately: the regional edition defers to the global URL.
linkedin.com โ served www.linkedin.cn, canonical https://business.linkedin.com/zh-cn/zh-cn, 200. The same pattern on a different host.
tumblr.com โ served /, canonical https://www.tumblr.com/explore/trending, 200. The logged-out homepage canonicalises to the trending feed rather than to itself.
stanford.edu โ served /, canonical https://www.stanford.edu/home, which returns 404.
trello.com โ served /, canonical https://www.trello.com/home, which returns 301.
mit.edu โ served web.mit.edu, canonical https://tlecms.mit.edu/spotlight/zombie-cells: a different host, and a specific article about zombie cells. We could not reach that URL to check it โ a direct request timed out and a proxied request failed the TLS handshake โ so we report it as unverified rather than as broken. It has the shape of the classic template bug, where a homepage inherits a canonical slot filled from an article template, but we did not confirm it.
Finding 4: two canonical targets are not reachable pages
We managed to test 43 of the 44 canonical URLs. 41 returned 200 (95%). Two did not, and both belong to large, well-resourced sites.
Stanford's homepage tells a crawler that the preferred version of https://www.stanford.edu/ is a URL that answers 404. Trello's points at /home, which 301s โ and in Trello's case the bare host redirects too, so the canonical points into a redirect chain rather than at a destination.
Neither is a syntax error, and nothing warns you. The tag is well-formed, the page renders, validators pass. The failure is silent in exactly the way canonical failures always are: a crawler that cannot resolve the canonical behaves as though you had not written one, which returns you to the duplicate-selection problem you wrote the tag to avoid. One command settles it for any URL you own:
curl -sS -o /dev/null -w "%{http_code}" https://example.com/your-canonical
The answer must be 200. Anything else is a canonical that does not do its job.
Finding 5: the mechanics are cleaner than the reputation suggests
Across 44 canonicals we found zero relative hrefs โ every single one used an absolute URL. Zero http/https mismatches. Zero pages shipping two conflicting canonicals. Zero canonicals placed outside <head>.
Two near-misses are worth knowing. bbc.com ships the identical canonical tag twice, a harmless artefact of a framework rendering the head twice. moz.com is the only site in the sample to send a canonical in the HTTP Link header โ and it also has the tag in its HTML, so the header is redundant rather than load-bearing.
Read alongside the two broken targets above, this is the useful shape of the result: nobody writes malformed canonicals any more. The failures are not in the syntax, they are in what the tag points at.
Finding 6: geo-personalisation is the real design decision
Seven of the 44 canonical URLs carry a language or region segment in the path. Four are region-personalised versions of what we asked for: stripe.com/cn, coinbase.com/en-ca, squareup.com/us/en, uber.com/ca/en. Because we fetched from a Chinese IP address, those are the variants we were served โ and each of them self-canonicalises to the variant it served.
CNN made the opposite choice: it served us the regional edition and canonicalised back to the global URL. Both are defensible. What matters is that the choice is consistent, that it matches your hreflang annotations, and that one URL produces one canonical regardless of who asks. If your canonical varies with the visitor's IP, then a crawler geo-dispatched differently from your users will consolidate a different set of pages than the set your users actually see.
What to do with this
Emit an absolute, self-referencing canonical on every indexable URL. One in five famous homepages does not, and the ones that do are not doing anything clever.
Compare it against the final URL after redirects. 80% of the pages here redirected before serving content. Auditing against the URL you typed will manufacture cross-domain errors that do not exist.
Check that the canonical itself returns 200. Two of 43 did not. It is one curl command and no validator will do it for you.
Never point a canonical at a redirect. Point it at where the redirect lands.
Pick one geo policy and apply it everywhere. Consolidate globally like CNN, or self-canonicalise per locale like Stripe โ but do not let the answer depend on who is asking.
Generate the tag rather than hand-writing it. Every failure above is a value problem, not a syntax problem, and values are what templates and generators get right. The meta tag generator on this site emits the canonical alongside the rest of the head from a single URL, so the value cannot drift away from the page it describes.
Limitations
55 pages from 78 hand-picked, well-known domains โ representative of famous sites, not of the web. A random sample would look different in both directions.
The 23 unreadable pages are not a random loss. They are disproportionately large consumer and financial sites that fight crawlers โ Amazon, GitHub, the New York Times, PayPal, Target, eBay โ so the sample skews toward sites that serve their homepage to anyone who asks. That is a real bias, and it probably makes these numbers look tidier than the web as a whole.
We read only the initial HTML. A canonical delivered through JavaScript, a sitemap entry, or an HTTP header on a site that omits it from HTML is invisible here; two of the eleven "absent" pages were client-rendered shells where that caveat is live rather than theoretical.
One fetch, from one IP address, on one day. Because that address is in China we were served regional variants of several sites, which is what made Finding 6 visible โ and it also means a different vantage point would produce a slightly different set of canonicals.
Reproduce it
The script and the shared domain list ship with this site. node scripts/survey-canonical.mjs fetches and stores the raw HTML for every domain; --report re-derives every number from that stored HTML without touching the network, and --evidence prints the raw <link> tag behind each verdict. Our first robots.txt survey covers the same domain list from a different angle.