Hreflang Validation: Catching the Errors That Quietly Split Rankings
Daniel Kim
Senior SEO & Content Systems Analyst
Hreflang errors rarely announce themselves. The page loads, the language switcher works, and rankings in the wrong market erode slowly. The protocol has strict reciprocity requirements, and a single missing return tag can cause Google to ignore the annotation entirely. Validation is mechanical, which is good news: a crawl and a set of checks catch nearly every failure.
The rules that matter
Each annotated page must list all language versions, including itself. If page A points to B, page B must point back to A. Missing reciprocity invalidates the pair.
x-default marks the fallback for unmatched languages and should appear on exactly one URL per cluster, typically the global or language-selector page.
Language codes follow ISO 639-1; region codes follow ISO 3166-1 Alpha 2. en-GB is valid; en-UK is not. Script subtags are allowed (zh-Hans), and using them inconsistently across a cluster is a common error.
Hreflang can be implemented in HTML <link> tags, HTTP headers, or the sitemap. Mixing methods across a cluster is allowed but increases the chance of a mismatch. Pick one method per cluster.
Validate reciprocity at scale
Crawl every URL in the international cluster and extract its hreflang annotations. Build a map of source URL to declared alternates, then check two directions: every target exists in the crawl, and every target declares the source back.
The failures cluster into three types: a language added to the selector but not annotated on existing pages, a page removed without updating its siblings, and a canonical tag pointing to a different language version. The third is the most damaging because it tells Google two conflicting things about which URL should rank.
Check that each alternate URL returns 200. A 301 in an hreflang cluster passes no signal and is treated as an error.
Sitemap pitfalls, and the user-facing behaviour
Sitemap hreflang requires xhtml:link entries with rel="alternate", hreflang, and href for every version, including self-reference. Relative URLs are not allowed; they must be absolute.
A common bug: the sitemap lists alternates but the pages also carry HTML hreflang tags that disagree. Google may pick either. Choose one source of truth.
For large sites, generate sitemap hreflang programmatically from the same data that renders the language switcher. Two independent lists will diverge.
Technical validation does not catch a broken switch. Click through the selector on every locale and confirm it lands on the equivalent page, not the homepage. Confirm that a cookie or IP-based redirect does not override the hreflang target; automatic redirects are a frequent cause of "Google sees the wrong version".
Check that the <html lang> attribute matches the hreflang value. A mismatch is a weak signal on its own, but it compounds with others.
A maintenance loop, and building the cluster map
Run the crawl monthly and after every locale launch. Keep the cluster map in version control so a new language is a reviewed change rather than a manual edit on twenty pages. Track three numbers: reciprocity failures, non-200 alternates, and clusters missing x-default. Those three cover the errors that actually affect international rankings.
Start from the sitemap or the language selector data, not from a crawl of every URL. Each locale version of a page belongs to one cluster, and the cluster is the unit of validation.
Represent it as a map: cluster ID to an array of {hreflang, url}. Generate the annotations from this single structure for HTML, headers, and sitemap. Any second source of truth will drift.
A cluster with more than twenty locales is common in the EU. Validate the whole cluster in one pass, because a missing return tag in any member invalidates the annotations.
Canonical and hreflang interaction, plus language detection and redirects
Each localized page should self-canonical, not canonicalize to the primary language. A common mistake during translation rollouts is copying the English template's canonical tag, which points every locale at the English URL and removes all of them from their local indexes.
Check that the canonical URL is one of the cluster's alternate URLs. A canonical that appears in no hreflang annotation is a contradiction.
Automatic IP-based redirects to a locale version conflict with hreflang and with user intent. A crawler from the US that requests the German URL should receive the German page, not a redirect to English. Serve the requested locale and offer a suggestion banner instead of redirecting.
If a redirect is unavoidable, use a 302 and exclude the redirecting URL from the cluster. A 301 in the cluster is an error.
Measuring the result, and the common false alarms
Track impressions and clicks per country in Search Console for each locale cluster. A correctly configured cluster shows impressions in the target country within weeks. If the German pages earn impressions only in Germany from English URLs, the locale pages are not being served.
A crawl tool reporting "missing return tag" often crawls a URL that redirects or is blocked by robots. Confirm the URL returns 200 and is the canonical member before fixing code.
CDN variations in trailing slashes and capitalization create duplicate URLs that appear as broken clusters. Normalize URLs before comparing.
The new-locale launch checklist, and removing a locale
Add the locale to every page in the cluster, update the sitemap, verify return tags, and confirm the language switcher routes to the equivalent page.
A launch that updates only the new pages breaks reciprocity for the whole cluster.
Remove its annotations from every sibling and redirect the URL. Leaving stale alternates creates 404s in the cluster.
Language versus region, and alternate tags that agree with the canonical
en-GB and en-US are different targets, but en alone is a valid fallback for both. Mixing a generic and a regional tag for the same page confuses the selection.
Pick one pattern per site: either regional variants with an x-default, or a single language tag. Switching patterns halfway through a cluster produces the conflicts this audit reports.
Each language version should canonicalize to itself and list the whole cluster as alternates. Pointing every version at one canonical collapses the cluster into a single page.
Check both tags in the same pass. An audit that validates alternates without reading the canonical misses the most damaging configuration error.
Related Guides & Reviews
Redirect Chain Audits: Finding the Loops, Hops, and Lost Equity
How to crawl and classify redirect chains, fix the ones that waste crawl budget, and avoid the migration mistakes that create them.
Reading Core Web Vitals Field Data Without Guessing From Lab Tests
How to pull real-user Core Web Vitals from CrUX and Search Console, interpret the 75th percentile, and separate lab regressions from field problems.
