Free tool, paste mode sends nothing anywhere, fetch mode calls one relay only when you press Fetch
Hreflang checker that quotes the rule behind every error
By Michael Lip
Paste the head of a page, a sitemap url block or plain lines of code then URL, or fetch a live page by URL. The checker reads every hreflang value against the IANA Language Subtag Registry, tells you whether the set lists the page itself and carries x-default, flags relative hrefs, mixed http and https, an underscore in place of a hyphen, duplicate codes and wrong forms such as en-UK, and prints the sentence from Google or the RFC that each finding rests on. Return links can be checked by pasting several pages or by fetching every alternate in the set.
Of the 58 homepages measured in this site's own tag census, captured 2026-09-06 by one HTTPS GET per host, 23 carry an hreflang set and 9 of those sets have no x-default entry. The figures below are read from the census file published beside this page, and none of them is typed by hand.
- 58homepages measured on 2026-09-06, one HTTPS GET per host, served HTML only
- 23of those homepages carry at least one hreflang entry
- 14carry an x-default entry
- 21list the page itself, matched on the final URL after redirects
01Check an hreflang set
Three shapes go in the box and the tool works out which one you pasted. The served HTML of a page holding <link rel="alternate" hreflang="..."> elements, a sitemap fragment holding <xhtml:link> children under each url element, or plain lines of a code followed by a URL. A Link: response header line is read too. Give the URL of the page being checked so the self reference can be matched. To check return links offline, paste more than one page and start each block with a line holding a hash and that page's URL.
Type an https URL and its served HTML is fetched through a relay, loaded into the box below and checked. The final URL after redirects fills the page URL field. Or skip this and paste the head yourself.
Paste mode runs entirely in your browser and makes no request of any kind. The one thing a browser cannot do is read another site's page, so the Fetch button and the return link button call a small relay the author of this site runs on workers.dev. It fetches exactly the URL you give over https, GET only, follows at most five redirects, keeps at most 1 MB of the body, gives up after 12 seconds, refuses private address space, and stores nothing. Every relay error is printed here word for word.
Reference data in this page is the two letter language subtags, the two letter region subtags and the four letter script subtags read from the IANA Language Subtag Registry file dated 2026-08-08, the registry W3C names as the one place every subtag is found. Counted from those embedded lists when this page loaded, that is language subtags, region subtags and script subtags, deprecated entries excluded and listed separately.
02Every rule the checker applies, and the line it comes from
Each row is one check in the box above. The right hand column is the sentence the rule is taken from, quoted, with a link to the page it sits on. Where Google and the specification say different things, the checker reports Google's rule as the error and the specification as the reason.
| Check | Passes | Fails or warns | Source line |
|---|---|---|---|
| Language part is a registered two letter code | de, en-GB | eng, english | Google, "are supported; other codes that aren't listed in those standards, such as es-419, aren't supported". W3C, "only one code is listed per language". Google, W3C |
| Region part is an assigned two letter code | en-GB | en-UK | RFC 5646, "the exception of 'UK', which is an exact synonym for the assigned" code GB. IANA registry, GB is "Description: United Kingdom". RFC 5646, IANA |
| Region is never given on its own | de-DE | US | Google, "You can't specify the country code by itself." and "Specifying the region alone is not valid." Google |
| Script part is a four letter ISO 15924 code | zh-Hant, zh-Hans | zh-Hanx | Google, "You can also specify the script itself explicitly using ISO 15924". ISO 15924, "Alphabetical list of four-letter script codes". ISO 15924 |
| Subtags run language, then script, then region | zh-Hant-TW | zh-TW-Hant | RFC 5646, "Script subtags MUST follow any primary and extended language" subtags and "Region subtags MUST follow any primary language, extended" language or script subtags. RFC 5646 |
| Subtags are joined by a hyphen | en-US | en_US | RFC 5646, subtags are separated from "other subtags in a tag by a hyphen". RFC 5646 |
| A three digit region is not an ISO 3166-1 alpha 2 code | es-MX | es-419 | Google, "are supported; other codes that aren't listed in those standards, such as es-419, aren't supported". Google |
| Script part that adds nothing is flagged | en-GB | en-Latn-GB warns | IANA registry, "Suppress-Script: Latn" under the en record. W3C, the "golden rule is to keep your language tag as short as possible". W3C |
| The set lists the page itself | Set contains the URL you gave | Set omits it | Google, "Each language version must list itself as well as all other language versions." Google |
| Every href is absolute and carries a scheme | https://example.com/de/ | /de/, //example.com/de/ | Google, "Alternate URLs must be fully-qualified, including the transport method (http/https)". Google |
| http and https are not mixed in one set | All entries https | Some http, some https | Google, "Don't include the HTTP version of your pages in your sitemap or" hreflang annotations. Google canonicalization docs |
| No code appears twice | One entry per code | Same code, two targets | Google, the "set of links is identical for every version of the page". Google |
| x-default is present | Set carries x-default | Reported as a recommendation miss, not an error | Google, "This value is recommended for specifying the fallback page", under the heading that asks you to consider adding a fallback page for languages that match no version. Google |
| Return links, pasted or fetched | X points to Y and Y points back to X | Y has no entry for X | Google, "If two pages don't both point to each other, the tags will be ignored." Google |
| Sitemap urlset declares the xhtml namespace | xmlns:xhtml="http://www.w3.org/1999/xhtml" on urlset | urlset without it | Google, "Specify the xhtml namespace as follows" xmlns:xhtml="http://www.w3.org/1999/xhtml". Google |
| Reserved codes are called out | en-GB | en-EU, en-UN warn | Google lists EU, UN and UK among codes reserved for something else, which "doesn't have an effect on Google Search". Google |
| Deprecated subtags are called out | he-IL, id-ID | iw-IL, in-ID, en-YU warn | The IANA Language Subtag Registry marks each one Deprecated in the file dated 2026-08-08. IANA |
| Case is reported as a style point, never an error | en-GB | EN-gb gets a note | RFC 5646 records that ISO 639-1 "recommends that language codes be written in lowercase" and ISO 3166-1 "recommends that country codes be capitalized". RFC 5646 |
03What hreflang looks like on big homepages
The numbers below come from this site's own tag census, one direct HTTPS GET of the homepage of each of the 83 hosts in the 2026-08-24 robots census on this site, redirects followed, captured 2026-09-06, with 58 hosts returning HTTP 200 with served HTML and therefore measured. Every figure is read from the published file by code and none of it is typed into this page. An hreflang entry is counted as a link element with rel alternate and an hreflang attribute, and a code counts as invalid when it does not match language, optional script, optional region, or x-default.
| Measure | Hosts |
|---|---|
| Homepages measured, hosts that returned HTTP 200 with served HTML | 58 |
| Carry at least one link rel alternate hreflang entry | 23 |
| Carry an x-default entry | 14 |
| Set includes the page itself, matched on the final URL after redirects | 21 |
| Have hreflang entries but no x-default | 9 |
| Have hreflang entries that do not include the page itself | 2 |
| Carry at least one value that fails the syntax check | 1 |
| Declare the same code more than once | 1 |
Set sizes are lopsided. Among the 23 measured homepages that carry any hreflang, the median set holds 16 entries, the largest single set on one homepage holds 157 entries, and the census holds 918 entries across every measured homepage, all captured 2026-09-06 by one HTTPS GET per host. So the two mistakes worth checking first are the ones that scale with the set. A missing self reference costs one entry on every page in the set, and a missing return link costs the pairing on both ends.
The raw machine readable file behind every figure here is published beside this page at data/homepage-tag-census-2026-09-06.json, with its capture date, its instrument, its method and its limits inside the file.
04Common questions
Whether x-default is required
No. Google describes a fallback page for languages that match no version as something to consider adding, and calls the reserved x-default value recommended for specifying that fallback, which is a recommendation and not a syntax rule. So the checker reports a missing x-default as a recommendation miss rather than an error. Google also says there is no need to specify a language code for the x-default value, because that page is targeted to users whose language settings match nothing on the site, so the language of the page is irrelevant. In the census, 9 of the 23 measured homepages that carry hreflang have no x-default entry, captured 2026-09-06 by one HTTPS GET per host.
hreflang and canonical together
They do different jobs and Google keeps them apart. A rel canonical annotation that carries an hreflang, lang, media or type attribute is ignored for canonicalization, so an alternate link is not read as a canonical suggestion. Google also states that for canonicalization purposes it prefers URLs that are part of hreflang clusters, which is a second reason to get the reciprocal set right. Point each language version's canonical at itself, and let the hreflang set do the language targeting.
Header, link element or sitemap
Google documents three carriers for the same annotation. One link element for each page variant including the page itself, placed in the head element of every variation. HTTP response headers, which Google notes are useful for non HTML files such as PDFs. Or a sitemap, where the xhtml namespace is declared on the urlset element as xmlns:xhtml="http://www.w3.org/1999/xhtml" and each url element lists every alternate version of the page, including itself. The self reference rule is the same in all three. The checker reads all three shapes because the mistake usually survives the move from one carrier to another.
Why return links matter
Google lists missing return links first among the common hreflang mistakes, where page X links to page Y but page Y does not link back to page X, and states plainly that if two pages don't both point to each other the tags will be ignored. A one way annotation is not a weak signal, it is a discarded one. Paste every page in the set into the box above and the checker prints the exact pairs that fail, in the direction they fail. Or press the return link button after a check and the relay fetches each alternate, up to 25 of them, and reports whether it points back.
What this page sends anywhere
In paste mode, nothing. The code lists, the rules and the matching all live in this page, and the text you paste never leaves the browser tab. Fetch mode and the return link button send the URLs you asked for to the relay named above, and nothing else, and only when you press the button. That matters more than it used to, because the Search Console International Targeting report, which is where hreflang errors used to be reported, has been deprecated, while Google says it will continue to support and use hreflang tags on your pages. The reporting went away and the rules did not, so the check has to happen on your side now. Worth knowing as well, Google states that it does not use hreflang or the HTML lang attribute to detect the language of a page and uses algorithms instead. hreflang tells Google which version to show a given user, not what language a page is in.
Read before acting on any verdict above
05What this checker cannot tell you
The tool answers one narrow question, whether an hreflang set follows the rules Google and the registry publish. It does not answer any of these.
- LIMITPaste mode fetches nothing. It reads only the text you paste, so it cannot confirm that a target URL answers, that it carries its own hreflang set, or that it is reachable at all.
- LIMITFetch mode reads served HTML through the relay, before any script runs, so an hreflang set injected by JavaScript is not seen. A page over 1 MB is cut at the cap, and the relay reads only https.
- LIMITThe return link button checks at most 25 alternates per press, one fetch each, in order. A set larger than that is reported as checked up to the cap, and the rest are listed as unchecked, never as passing.
- LIMITIn paste mode, return links are checked only between the pages you paste. A target you did not paste is reported as unchecked, and never as passing.
- LIMITCodes are matched against the IANA Language Subtag Registry file dated 2026-08-08 that is embedded in this page. A subtag registered after that date reads as unknown here until the page is rebuilt.
- LIMITThe checker reports what the documentation says about the annotation. It says nothing about whether Google chose to use it, and it cannot tell you that from your side.
What the census is not
- LIMITA fixed list of 83 large, well resourced hosts, not a random sample of the web, and homepages only, which are the least typical page of any site.
- LIMITOne fetch per host from one network location with a desktop browser user agent, served HTML only, nothing rendered by script, so tags injected by JavaScript are not seen.
- LIMIThreflang codes are checked by syntax, not against the ISO tables, and reciprocity across the alternate pages was not fetched. The tool on this page does check codes against the registry, so the census figure for invalid codes is the looser of the two.
- LIMITThe top term density is a homepage figure under one stop word list and says nothing about ranking. Text figures count only hosts whose served HTML held at least 200 words, because a homepage that renders by script serves almost no text.
- LIMITA host that did not return HTTP 200 is listed in the file and excluded from every share, which is why the measured host count is the denominator for every figure above.
06Where these numbers come from
By Michael Lip, who fetched and published the census on this page and wrote the checker above.
Every census figure on this page is recomputed by code from the dataset file published beside the page, with the capture date and the instrument stated in the same sentence as the figure. A value that could not be fetched is held as null and rendered as unknown, never defaulted to something flattering. The code lists in the tool are parsed straight out of the IANA Language Subtag Registry file dated 2026-08-08, and the counts printed under the tool are counted from those embedded lists in your browser when the page loads, not typed by hand.
I run four small utility sites through Search Console and publish their impression and click counts on this site rather than a forecast. I read crawler traffic in raw server logs, where a request claiming to be Googlebot has to be checked against Google's published IP range files, because the user agent string is free to forge. The host list behind the census above is the one I fetched robots.txt from on 2026-08-24 and re-tested days later, which is where the observation that a handful of hosts give Googlebot a different answer from the star group came from. Same list, same method, new tag.
- SPECGoogle, tell Google about localized versions of your page, for the self reference, the fully qualified URL, the return link, x-default, the supported code standards and the reserved codes.
- SPECRFC 5646, BCP 47, for the hyphen, the subtag order, the UK exclusion and the case conventions.
- DATAIANA Language Subtag Registry, file dated 2026-08-08, for the embedded code lists, the deprecated subtags and the suppressed scripts.
- SPECW3C, choosing a language tag and ISO 15924 code list, for the one code per language rule, the shortest tag rule and the script list.
- DATAThe census file, every figure in section 03, captured 2026-09-06 and published unmodified.
This page was built by the pipeline it sells
The tool and the census on this page are what the pipeline produces. It refuses a keyword already saturated by an AI Overview, it will not let a page state a number that code did not compute, and it blocks a page that only restates what already ranks. It runs on your machine, with no hosted service and no account.
Nothing about traffic, rankings or indexation is promised here or anywhere else on this site.