HREFLANG RECIPROCITY CHECK · RUNS IN YOUR BROWSER

Do your hreflang alternates actually link back?

Paste a page's HTML and check its <link rel="alternate" hreflang="en" href="https://example.com/en/"> tags for the misconfigurations Google's own hreflang documentation names directly: a missing reciprocal link back from the alternate page, an invalid or malformed language/region code (en-uk is not valid — the correct code is en-GB), a missing x-default fallback, a missing self-reference, and duplicate or conflicting hreflang values.

Nothing is uploaded. The HTML you paste is parsed in this browser and never leaves your device — see "Why can't the browser just check this itself?" below for what an automatic-fetch attempt can and can't do.

1. Check a page

Prefer a CLI, or want this as a CI gate?

The CLI fetches the page and every alternate it names over real HTTP — no cross-origin restriction, because it isn't a browser:

node check.mjs https://example.com/en/ --json
node check.mjs https://example.com/en/ --timeout 15000
node check.mjs https://example.com/en/ --max-alternates 20

Get check.mjs, fetch-page.mjs, and engine.mjs from the repo — plain Node 18+, nothing to install. It only ever talks to the target URL and the alternate hrefs that page's own tags name — nothing goes through this site. Exit code 1 when a danger-severity finding is produced, the target can't be fetched, or an alternate can't be fetched (unverified reciprocity is not the same as confirmed-clean).

What's checked

CheckWhat it flagsSeverity
ReciprocityPage A links to page B with hreflang, but B has no hreflang link back to ADanger
Invalid codeLanguage subtag not in ISO 639-1, or region subtag not in ISO 3166-1 (e.g. en-uk)Danger
Non-canonical casingA validly-coded tag written with the wrong case, e.g. EN-us instead of en-USNotice
Missing x-defaultTwo or more language/region variants declared, no hreflang="x-default" fallbackNotice
Missing self-referenceA page with hreflang tags does not include itself among its own alternatesDanger
Duplicate / conflictingThe same hreflang value declared twice — once harmlessly (same URL) and once dangerously (different URLs)Notice / Danger

Only the two-part language[-region] shape is validated against the full ISO 639-1 and ISO 3166-1 lists. A script subtag (zh-Hans-CN) or a numeric UN M49 region (en-419) is recognized but not further validated — named as unvalidated rather than guessed at. More: why Google requires hreflang reciprocity, and the most common ways it breaks. See also: how this differs from Merkle's hreflang Tags Testing Tool, and this tool vs. checking hreflang tags by hand.

Common questions

What does "hreflang reciprocity" mean?

Google's Search Central documentation for hreflang says the links have to be reciprocal: if page A has a link rel=alternate hreflang tag pointing at page B, page B must have a matching tag pointing back at page A. If the return link is missing, Google's documentation says the annotation may be ignored — so a one-way hreflang link on a page you don't control the alternate for is effectively invisible to Google.

Why is en-uk invalid? It looks correct.

hreflang region subtags are ISO 3166-1 country codes, and "UK" was never assigned one — the United Kingdom's actual ISO 3166-1 code is "GB", inherited from its formal name (Great Britain and Northern Ireland). The correct tag is en-GB. This is one of the most common real-world hreflang mistakes because "UK" is the everyday abbreviation everyone actually uses.

Why can't the browser page just fetch the other language pages itself?

It tries to, but most sites will refuse to let a page running on a different origin read the response: unless the target server sends an Access-Control-Allow-Origin header naming this tool's origin (or *), the browser's Cross-Origin Resource Sharing policy blocks the page from reading what came back, even though the request itself often reaches the server. That is not a bug in this tool, it is the same origin-isolation protection that stops any website from silently reading another site's pages on your behalf. When a fetch is blocked this way, paste that page's HTML manually and the check runs exactly the same way. The zero-dependency CLI has no such restriction because it is not a browser tab.

Is this a full SEO audit?

No. It checks five specific, well-documented hreflang misconfigurations from Google's own documentation — reciprocity, code validity, x-default, self-reference, and duplicate/conflicting values. It is not a ranking guarantee, not a crawl of your whole site, and not a determination that your international SEO is otherwise correct.