How to Audit Hreflang at Scale

A repeatable, tool-driven process for auditing hreflang across a large site — pulling every annotation from all three implementation methods, reading cluster graphs and reciprocal matrices, and prioritizing fixes by damage, not frequency.

First published: Jul 2, 2026 · Last updated: Jul 25, 2026 · Advanced
demand #4 in Hreflang#14 in International SEO#360 on the site
1 evidence signal on this page

Auditing hreflang at scale is a graph-validation problem, not a tag-validation problem: you check whether every page in a cluster points back to every other page, not whether one page has a tag. Pull every annotation from all three implementation locations (HTML head, HTTP headers, XML sitemap) with a crawler — Google gives you no validator and GSC's International Targeting report was removed Sept 22, 2022 — then build the reciprocal-tag matrix. Spot-check a cluster visually with my free returntag - hreflang checker graph and matrix, or use Ahrefs Site Audit and Screaming Frog for full-site coverage. Triage by damage: missing return tags first (they break the whole pair), then wrong language/region codes and non-canonical targets, then missing x-default last (most common at 56.3%, least harmful). In my Brighton SEO 2023 study of 374,756 domains, over 67% using hreflang had at least one error.

TL;DR — A scaled hreflangHreflang is an annotation (in HTML, HTTP headers, or XML sitemaps) that tells search engines which language and optional region a page targets, and which alternate versions exist. It only works when every page in the cluster references all the others. audit is graph validation, not tag validation. Step 1: pull every annotation from all three legal locations (HTML head, HTTP Link headers, XML sitemapAn XML sitemap is a UTF-8 file listing the canonical URLs on your site (with optional lastmod) so search engines can discover and prioritize them. It's a discovery and diagnostic aid, not a guarantee of indexing — and Google ignores its priority and changefreq tags.) with a crawlerA crawler — also called a spider or bot — is an automated program that fetches web pages, extracts their links, and queues new URLs to visit. Search engines use crawlers to discover and download content for their index. configured for your ccTLDCountry-code top-level domain like .de or .co.uk — a strong geotargeting signal./subdomain setup — GSCA free Google service that reports how a site performs in Google Search and surfaces problems with how Google crawls, indexes, and serves it. It's first-party data straight from Google — but you don't need it to appear in results. can’t do this (International Targeting removed Sept 22, 2022, and even before that it only reported the canonical member of a cluster). Step 2: build the reciprocal-tag matrix — every URL in a cluster × every other, does A→B exist, does B→A. Read it in my returntag - hreflangHreflang is an annotation (in HTML, HTTP headers, or XML sitemaps) that tells search engines which language and optional region a page targets, and which alternate versions exist. It only works when every page in the cluster references all the others. checker cluster graph/matrix for a focused check, or use Ahrefs and Screaming Frog for site-wide crawlingCrawling is how search engines use automated bots (like Googlebot and Bingbot) to discover URLs and download pages. A page has to be crawlable to be indexed, but crawling on its own isn't a ranking factor.. Step 3: classify into four patterns — missing return tags, wrong codes, non-canonical targets, mixed absolute/relative URLs. Step 4: prioritize by damage, not frequency — return tags first (they break the whole pair), then codes, then x-defaultx-default is the reserved hreflang value that points to a fallback URL — the page Google shows when a user's locale doesn't match any of your other hreflang tags. It is optional and does not mean \"English.\" last (most common at 56.3%, least harmful). Step 5: re-verify against the indexedStoring a crawled page in the search index so it can appear in results. Crawled is not the same as indexed — Google selects what to keep, and indexing isn't guaranteed. URL, not the declared canonical.

This article is the hreflang-specific companion to my broader International SEO Audit, which treats hreflang as one of six audit areas. Here I’m going one level deeper on the hreflang-only methodology at scale. For fundamentals — what hreflang is, the three ways to implement it, the reciprocal rule — see the HreflangHreflang is an annotation (in HTML, HTTP headers, or XML sitemaps) that tells search engines which language and optional region a page targets, and which alternate versions exist. It only works when every page in the cluster references all the others. hub and, for the fallback tag, x-defaultx-default is the reserved hreflang value that points to a fallback URL — the page Google shows when a user's locale doesn't match any of your other hreflang tags. It is optional and does not mean \"English.\".

Evidence for this claim A complete audit needs to inspect HTML, HTTP Link headers, and XML sitemaps because Google supports hreflang in all three locations. Scope: Google Search-supported hreflang delivery methods. Confidence: high · Verified: Google: Localized versions

The core reframe: this is a graph problem

Here’s the mental shift that makes scaled auditing tractable. You are not checking “does this page have a hreflang tag.” You’re checking “does every page in this page’s cluster point back to it, and does every URL in the cluster resolve to a 200, canonical, indexable page.”

Google’s own documentation is the reason:

“If page X links to page Y, page Y must link back to page X. If this is not the case for all pages that use hreflang annotations, those annotations may be ignored or not interpreted correctly.”

Evidence for this claim A hreflang audit must verify return links because Google says non-reciprocal annotations may be ignored or interpreted incorrectly. Scope: Google Search hreflang reciprocity guidance; impact is stated as possible, not guaranteed cluster-wide invalidation. Confidence: high · Verified: Google: Hreflang guidelines

Read that carefully. One missing return link can cause the affected annotations to be ignored or interpreted incorrectly. That’s why a single-page view is structurally incapable of auditing hreflang: the failure lives in the relationship between pages, not on any one page. You need a crawl that records every cluster member and cross-references them.

Scope matters here too: the ignored annotations are the ones in the broken pair, not automatically every relationship in a larger cluster. A five-page cluster with one missing return typically keeps processing its other complete pairs normally — that’s exactly what my returntag - hreflang checker screenshot below shows: nine reciprocal pairs intact, one missing return flagged. Don’t assume one broken edge nukes the whole cluster; go check every pair, because the tool has to check every pair to tell you that.

And it gets harder as the site grows — which is exactly Google’s own explanation for why big sites are the ones with errors. On Search Off the Record, Gary Illyes described the errors as emerging when a site has many properties, each with its own URL structureURL structure is how the parts of a web address — scheme, domain, path, query string, and fragment — are organized and formatted. It mostly affects crawling, usability, and how engines understand a page, not rankings directly. — as soon as you have to vary the pattern across properties, that’s where the errors come in, with Lizzi Sassman adding that it’s harder to sync them up when you’re localizing URLs and then making typos. That’s the signature of an enterprise setup: multiple ccTLDs, each on a slightly different publishing convention. So a good audit segments findings by property/domain group, because that’s where the errors actually cluster operationally.

Step 1 — Pull every hreflang annotation site-wide

The three places hreflang lives

Google accepts hreflang in three equivalent locations, and you must check all three:

  1. HTML <link> tags in the <head> — the common case.
  2. HTTP Link: response headers — used for non-HTML files like PDFs.
  3. xhtml:link entries in an XML sitemapAn XML sitemap is a UTF-8 file listing the canonical URLs on your site (with optional lastmod) so search engines can discover and prioritize them. It's a discovery and diagnostic aid, not a guarantee of indexing — and Google ignores its priority and changefreq tags. — common at scale because it centralizes the annotations in one file instead of templating them onto every page.

A crawlerA crawler — also called a spider or bot — is an automated program that fetches web pages, extracts their links, and queues new URLs to visit. Search engines use crawlers to discover and download content for their index. that only reads the HTML head will silently miss header- or sitemapA sitemap is a file that lists the pages, images, videos, and other files on your site so search engines can discover them. It helps discovery, but submitting a sitemap doesn't guarantee crawling or indexing.-declared alternates. It won’t flag them as broken — it just won’t see them, which is worse, because you’ll think a page has no hreflang when it actually has a full set delivered via sitemap. Configure the crawl to read all three before you trust a single number.

Configuring the crawler for your structure

  • Screaming Frog: enable Configuration > Spider > Crawl Hreflang (this also picks up sitemap and header hreflang when you point it at them). For ccTLDs/subdomains that reference each other, add the sibling domains under Config > CDNs — otherwise cross-domain hreflang links are simply not validated, not flagged as broken. This is the single most common blind spot at scale, because enterprise sites are the ones most likely to use ccTLDs, and ccTLDs are exactly what needs this extra step.
  • Ahrefs Site Audit: make sure the sibling domains are inside the project scope for the same reason. Then use Page Explorer to filter pages by hreflang issue type at scale before you drill into individual cluster graphs.

Why GSC can’t do this for you

Two reasons, and the second is the one most people miss:

  1. The report is gone. The GSC International Targeting report — which used to flag some hreflang issues — was deprecated and removed (announced August 2022; removed after September 22, 2022). Nothing replaced it directly.
  2. Even when it existed, it only ever showed the canonical. On Search Off the Record, Illyes explained that Search ConsoleGoogle's free tool for monitoring crawling, indexing, and search performance. only reports on canonicals — for most similar-language hreflang clusters, the alternates aren’t canonical, so you were effectively blind to what was happening on the non-canonical members of a cluster, because Google stores them in the duplicate cluster without keeping the alternate details. That’s a structural reason GSC was never a complete hreflang audit tool, not just “the report got removed.” It’s the direct justification for going crawler-first.

Google also just doesn’t ship a validator. On the same podcast, Illyes said Google has never provided an hreflang validator — they had some underused reporting and then removed it — and now points people to external tools like Aleyda Solis’ tool, Bill Hunt’s hreflang checker, and Merkle’s tool. Take that as permission to lean on third-party crawlers for the job GSC can’t do — but not as an endorsement. Google’s own documentation is explicit that it doesn’t maintain or check third-party hreflang debugging tools, so treat any tool’s output, mine included, as diagnostic evidence you still have to reason about, not an official verdict. When a finding actually matters, confirm it against the raw artifact — the HTTP response, the sitemap XML, or the rendered HTML — rather than stopping at the tool’s parsed summary.

Step 2 — Build the reciprocal-tag matrix

Normalize what you pulled

Before you build the matrix, get everything into one consistent shape. For every declared hreflang relationship, record the source URL, the target URL, the locale value, the source method (HTML head, HTTP header, or sitemap), and — critically — the target’s status code, redirect chainA → B → C instead of A → C. Each hop loses link equity and adds latency., indexability, canonical target, and whether the crawl saw it in raw HTML or the rendered DOM. Different crawlers export this differently; normalizing it into directed URL-to-URL edges with that context attached is what makes the matrix, and every classification in Step 3, reliable instead of a pile of disconnected rows.

What the matrix represents

Conceptually, for each cluster you build a table where the rows and columns are every URL in that cluster, and each cell answers a yes/no question: does a hreflang link exist from the row URL to the column URL? A correct cluster is symmetric — if A→B is present, B→A is present. Every asymmetric cell (a link that exists in one direction only) is a missing return tag.

You don’t literally hand-build this spreadsheet at scale — the tools build it for you. But holding the matrix in your head is what lets you read the tool output correctly. My returntag - hreflang checker tool draws the matrix as a graph and also exposes the underlying cells; Screaming Frog’s “Missing Return Links” filter pulls the asymmetric cells into a list, and Ahrefs Site Audit provides another at-scale cluster view. Same relationship check, different presentations and crawl scopes.

Reading it as a graph: my returntag - hreflang checker cluster validator

For a focused cluster check, my free returntag - hreflang checker tool renders the declared locale relationships as a graph and a reciprocal matrix. Every locale is a node, every declared hreflang annotation is an edge, and the issue list identifies the exact URL that fails to link back. The screenshot below is a sitemap-only run: it reads what the sitemap declares and deliberately does not fetch page head tags or HTTP Link headers. Use Page URL mode when you need the full three-source picture for a page’s cluster.

How to read it:

  • A clean cluster is a fully-connected mesh — every node linked to every other node, both directions.
  • A one-way edge is your asymmetric cell: page X points to Y but Y doesn’t point back. That’s the return-tag error, seen instead of read.
  • An orphaned node — a URL that appears in the cluster but doesn’t link back into it — is an unlinked hreflang URL.

The practical win is triage speed and stakeholder communication: instead of handing a developer an abstract spreadsheet row, you show the one-way relationship and the exact missing return-tag error together. For hundreds or thousands of clusters, keep Ahrefs Site Audit or Screaming Frog in the workflow for complete crawl coverage; returntag - hreflang checker is the fast way to inspect and explain a specific cluster.

TIP See the broken relationship

Turn a hard-to-read hreflang cluster into a graph, matrix, and exact fix with my free returntag - hreflang checker Free

  1. Run Page URL mode for a page-level cluster or Sitemap mode for declared sitemap relationships.
  2. Switch between Graph and Matrix, then open the exact missing-return issue.
  3. Use Ahrefs Site Audit or Screaming Frog when you need exhaustive site-wide crawl coverage.
The five-node graph keeps the wider locale cluster visible while isolating the one missing return from `fr-FR` to `en-US`.

The returntag - hreflang checker sitemap-only result reads five URLs and 24 annotations across en-US, en-GB, fr-FR, de-DE, and x-default. It reports nine reciprocal pairs, one missing return, and zero broken targets. The graph shows the otherwise connected five-node cluster and highlights the one-way relationship from en-US to fr-FR. The issue states that https://example.com/fr-fr/ does not link back to https://example.com/en-us/, so the return tag is missing. The tool notes that sitemap-only mode does not fetch page head tags or HTTP Link headers.

Reading it as a spreadsheet: the Screaming Frog filters

If you’re in Screaming Frog, the matrix surfaces as a set of filters (after you run Crawl Analysis post-crawl to populate the return-link data). Work them in roughly this order, because it maps to the priority order in Step 4:

  • Missing Return Links — the asymmetric cells; your highest-priority findings.
  • Inconsistent Language & Region Return Links — a return link exists but with a different code than the outbound one (A says B is fr-FR, B says A is en-GB when A is really en-US) — a subtler pair-breaker.
  • Non-Canonical Return Links — the return link points at a URL that’s canonicalized elsewhere, so the signal chain breaks even though a tag exists.
  • NoindexNoindex is a directive that tells search engines to keep a page out of their index, so it won't appear in search results. It works only on pages a crawler can actually fetch — a page blocked in robots.txt can never be noindexed. Return Links — the return target is noindexed, so it can’t carry the annotation.
  • Non-200 Hreflang URLs — the target is a redirectA redirect sends browsers and crawlers from a requested URL to a different one. An HTTP redirect specifically is a 3xx status code paired with a Location header; meta refresh and JavaScript redirects achieve a similar navigation without being a 3xx response themselves. Permanent redirects (301/308) are Google's signal the target should be canonical; temporary ones (302/303/307) aren't. or an error page.
  • Unlinked Hreflang URLs and Incorrect Language & Region Codes — orphaned nodes and code-validation errors.

Export the whole set via Reports > Hreflang. (For the full filter-by-filter walkthrough at the summary level, the Screaming Frog hreflang tutorial is excellent — I’m not going to re-type their config steps here.)

Step 3 — Classify what you find into four error patterns

Your crawl output will be noisy. Sort every finding into one of four buckets — these are the patterns that repeat across the 374,756-domain study. (I’m pulling only the two figures that anchor the priority argument; the full nine-type error table is already in the International SEO Audit article — no point re-pasting it.)

1. Missing return tags — the pair-breaker

The asymmetric cells from your matrix. 15.3% of hreflang-using domains have these. As I put it in the study writeup: “As I mentioned, hreflang tags work in pairs. If both pages don’t reference each other, they can’t establish the connection and swap properly in the search results.” This is the category that invalidates the whole pair’s signal per Google’s docs, which is why it’s first in the priority order — even though it’s not the most common error.

2. Wrong language/region codes — the quietly-forgiving one

Use ISO 639-1Two-letter language codes used in hreflang (en, es, de). for language and ISO 3166-1 alpha-2Two-letter country codes used in hreflang region targeting (us, gb, au). for region. The classic breakers: jp instead of ja for Japanese, the typo js for ja, three-letter codes like gbr instead of gb, la (Laos) misused for “Latin America.”

One more distinction worth building into your audit: BCP 47 (the underlying language-tag spec) permits a much broader set of values than Google’s hreflang implementation actually acts on — script subtags and other BCP 47-legal constructs that Google’s own hreflang documentation doesn’t confirm as recognized values. A code can be perfectly well-formed BCP 47 and still not be something Google’s hreflang guidance documents as supported. Validate against Google’s documented language/region/x-default rules specifically, not generic BCP 47 well-formedness — a syntactically valid tag can still be functionally invisible to Google.

But here’s the nuance that cuts against naive prioritization: Google silently corrects some of these and not others. Its documentation states that if you use codes reserved for something else, “Google Search ignores that part of the annotation (for example, using EU, UN, or UK in hreflang annotations doesn’t have an effect on Google Search).” So UK is effectively dropped (you want GB), but it doesn’t nuke the rest of the annotation — whereas a code that’s simply wrong (jp for ja) does break that pair. An audit needs to distinguish “technically wrong but Google handles it” from “wrong and actually breaks the pair,” because they don’t get the same urgency.

3. Non-canonical URLs in hreflang — the invisible one

This is the pattern that looks fine in a tag export and breaks anyway. A key distinction I drew at Pubcon 2019: hreflang is about the indexed version, not the canonical. If your hreflang points to a URL that’s canonicalized away from what’s actually indexed, the signal chain breaks even though the tag itself is “valid.” This only surfaces when you cross-reference the crawl export against indexingStoring a crawled page in the search index so it can appear in results. Crawled is not the same as indexed — Google selects what to keep, and indexing isn't guaranteed. status — most hreflang tutorials skip it because they treat hreflang as an isolated tag check instead of part of the indexing pipeline. (More on verifying this in Step 5.)

There’s a same-language alignment check worth adding here too. When several near-duplicate URLs could plausibly serve as the canonical for a locale, Google’s own canonicalizationHow search engines pick one canonical URL among duplicates and consolidate signals onto it. guidance favors a same-language (or best-substitute) URL, and gives some preference to a page that’s part of a complete reciprocal hreflangIf page A lists page B as an alternate, B must list A back — or Google ignores the pair. cluster over one that isn’t. That’s a reason to keep hreflang targets pointed at same-language canonical candidates rather than letting them drift onto a different-language duplicate. None of this is something a crawler or checker can prove outright, though — it can show you the configured signals (canonical tagsA rel=\"canonical\" annotation — in the HTML <head> or an HTTP Link header — that tells search engines which URL is the preferred version of duplicate or near-duplicate content., hreflang edges, cluster membership), not Google’s actual final selection. Treat crawl output as diagnostic evidence, not confirmation.

4. Mixed absolute/relative URLs — the templating bug

Google is explicit: “Alternate URLs must be fully-qualified, including the transport method (http/httpsHTTPS is the encrypted version of HTTP — it uses TLS to authenticate the server and protect data in transit between a browser and a website. Google announced it as a lightweight ranking signal in 2014 and today conditionally prefers HTTPS pages as canonical; Chrome marks plain HTTP pages 'Not Secure.'), so: https://example.com/foo, not //example.com/foo or /foo.” At scale this is almost never a one-off typo — it’s a templating bug that hits thousands of URLs at once because the hreflang block is generated from a partial URL pattern. That’s why crawlers flag it as a systemic issue: find one, and you’ve usually found a whole template’s worth.

Step 4 — Prioritize: return tags first, codes next, x-default last

The single most important idea in this whole article: error severity is not proportional to error frequency. Sort your findings by damage, not by how many rows the tool returned.

TierError patternWhy here
1 — fix firstMissing return tags; inconsistent return-link codesBreaks the entire pair’s signal per Google’s docs. Highest damage.
2 — fix nextWrong codes that Google doesn’t silently fix (jpja); non-canonical / broken targetsBreaks individual relationships; some are silently handled, some aren’t — triage accordingly.
3 — batchMixed absolute/relative URLs, missing self-referenceReal hygiene issues, usually template-wide, but not always cluster-breaking.
4 — lastMissing x-defaultx-default is the reserved hreflang value that points to a fallback URL — the page Google shows when a user's locale doesn't match any of your other hreflang tags. It is optional and does not mean \"English.\"Most common, least damaging.

Why x-default goes last despite being everywhere: it’s the single most common finding in every study — 56.3% in my 374,756-domain study, and 47.95% in Dan Taylor’s independent 18,786-domain SALT.agency study (two studies, very different scales, same headline: most sites are missing it). But as I wrote in the study: “Setting an x-default is not required. But it is recommended if you need a fallback page for users whose language settings don’t match any of your localized versions.” Google’s own team treats it as a UX fallback, not an indexing-critical signal — on Search Off the Record, Illyes described x-default as annotating a fallback page for when there’s no matching language for a user, and noted it can even be another language page rather than a dedicated selector. Fix it, but fix it after the things that actually break clusters.

Self-reference sits in tier 3 for the same reason: even Illyes, who worked on Google’s hreflang implementation, said on record he doesn’t fully remember why self-reference is required and is fairly sure clusters would work without it — he framed it mainly as making clusters easier to set up because you can copy/paste the same block everywhere. It’s implementation hygiene, not a functional requirement.

For the broader impact × effort matrix that spans all six international audit areas (not just hreflang), use the Frameworks lens in International SEO Audit rather than rebuilding it here.

Step 5 — Re-verify against the indexed URL, not the crawl

Your crawl validates the tags. It doesn’t validate that the URL the tag points to is the one Google actually indexed. Because hreflang follows the indexed version (Step 3, pattern 3), a tag that points at a URL that’s been canonicalized away — or that redirects, or is noindexed downstream — still breaks the signal even after your bulk fix pass reports “clean.”

So after the fixes ship, spot-check the highest-value clusters with URL Inspection in Search Console: confirm the URL Google reports as indexed is the same URL your hreflang references. This is the step that catches canonical-chain drift, which is invisible in a plain hreflang-tag export. You don’t do it for every URL — you do it for your money pages in each market, after the crawl says you’re done.

A one-line note on Bing

Don’t expect Bing Webmaster ToolsMicrosoft's free portal for monitoring and improving how a site appears in Bing search — the peer to Google Search Console, plus IndexNow instant indexing, richer backlink data, and keyword volumes. Because Bing's index also feeds Microsoft Copilot, it doubles as a window into AI-search visibility. to validate any of this. Bing treats hreflang as a much weaker signal than Google does and removed its GeoGenerative Engine Optimization — visibility inside AI answer engines. Targeting feature back in 2020 — it leans on the Content-Language header instead. A hreflang-at-scale audit is fundamentally a Google-facing exercise; check Content-Language for Bing separately (covered in International SEO Audit).

Add an expert note

Pin an expert quote

New person? Create their unclaimed profile at /admin/experts/ → Pin a quote first.