Last updated
Why My Hreflang Is Not Working
Hreflang annotations fail when self-references are missing, alternate-language pointers are wrong, or the x-default does not exist. The result is crawlers serving wrong-market versions and engines surfacing answers in the wrong language.
Hreflang is a pact, not a declaration
Hreflang works as a mutual agreement: each variant must link to every other variant, including itself, in a closed loop. When one link is missing or wrong, the pact breaks and crawlers treat the annotations as unreliable across the entire set. This is why the most common fix — adding one annotation — often fails. The network of links must be complete to work at all.
Answer engines care because correct annotations let them serve the right language to the right user. When hreflang is broken, an engine must guess, which often produces a Spanish user seeing the German version or a French user getting cited from the English page. Confirm crawlers can reach all variants using the machine readability hub, then audit the linking network before blaming the implementation.
Six ways hreflang annotations break
Each cause below disrupts the mutual-agreement at a different point. Most multilingual sites carry several at once, which is why single-annotation fixes rarely succeed.
A page does not link to itself in hreflang
The self-reference is the anchor that completes the loop. Every page in the set must announce which language and region it serves, including announcing itself. A missing self-reference tells crawlers the page’s own language is unknown, which invalidates the entire network.
Add a self-referencing hreflang on every variant, even where it feels redundant. The loop cannot form without it.
What this looks like: The German variant links to English and French but not to Germany.
Hreflang targets point to canonicals that do not point back
Crawlers check whether the target page reciprocates the link. When the target points elsewhere, the relationship is one-way and therefore invalid. Engines then discard both links as unreliable.
Before adding any hreflang, confirm the target page declares a canonical pointing back. Build the complete loop on paper before editing templates.
What this looks like: The French variant links to en-GB but the British page canonicalises to en-US instead.
The x-default exists but points to an unservable variant
X-default is the fallback for users whose language or region does not exactly match any variant. The target must be a page that can actually serve to anyone without special conditions. An x-default pointing to a geofenced page defeats the purpose.
Route x-default to a page any user can access: a content-negotiated homepage, a language-selection page, or the strongest general-audience variant.
What this looks like: X-default links to a page that requires geolocation to load or sits behind a paywall.
Sitemap hreflang is shadowed by conflicting head annotations
When both exist, crawlers read head annotations and ignore the sitemap entry. A page updated to use head hreflang while the sitemap still carries old entries creates conflicting truth, and the conflict usually wins.
Use one method consistently. If you switch from sitemap to head hreflang, update both simultaneously and verify the live page, not the file.
What this looks like: The XML sitemap declares hreflang, but the page head carries different hreflang entries that crawlers prioritize.
Subdomain and subdirectory variants mix annotation methods
Hreflang must cover every variant in the set consistently. A mix of annotated and unannotated pages leaves the network incomplete, and crawlers treat the entire set as unreliable.
Audit all variants in your multilocal structure and ensure every one declares its language and links to its siblings. Consistency matters more than perfection.
What this looks like: The en.example.com variant uses hreflang while de.example.com doesn't, breaking the network.
Language codes are incorrect or inconsistent across variants
Language codes must follow the standard (de, de-AT, de-CH, not deutsch or german). Inconsistent codes break the linking network because crawlers cannot tell whether two different codes refer to the same language.
Use BCP 47 codes consistently: base language, then region if needed. Audit all pages for typos and non-standard codes.
What this looks like: One page declares hreflang lang=de, another declares de-DE, and a third uses German.
How hreflang resolves to language selection
Crawlers follow the network of links to decide which variant to serve for each user. Knowing where the network breaks tells you which link to fix.
From hreflang network to served variant
- 01Crawler fetches all variant annotations
- 02Validates that all variants form a closed loop
- 03Maps user language and region to the best match
- 04Serves the variant annotated for that locale
- 05Treats broken networks as individual pages
| Error type | Detection clue | How to find it | Verification |
|---|---|---|---|
| Missing self-reference | One page's hreflang set does not include itself | Audit each page's annotations | Add hreflang hreflanghrefg="self-lang"> |
| Unreciprocated link | A page links to target that does not link back | Fetch both pages, compare annotations | Ensure both declare each other |
| Bad x-default target | X-default points to geofenced or paywalled page | Check x-default can load without login | Route to universally accessible page |
| Conflicting methods | Both sitemap and head hreflang declare different targets | Compare page source against sitemap | Keep only one, update both files |
| Inconsistent codes | Same language declared as de, de-DE, and deu | Extract all language codes from all pages | Standardize to BCP 47 codes |
| Broken loop | Not all variants declare each other | Map variant→target for every entry | Close the loop, no missing edges |
Localization health sits with the rest of the crawl stack on SearchDock technical SEO, because language routing and access both happen on the same requests.
Signs the hreflang network is broken
Each item is checkable by fetching the pages themselves. Do not rely on reports; read the annotations directly.
SIGNS CHECKLIST
0 / 8 checked
How to build a working hreflang network
Build on paper first, then verify the live pages. A correct loop is the goal, not a quick fix.
Map the variant set
List every language and region variant you serve
Result: You know exactly which pages must link to each other.
- Enumerate every language you publish in
- For each language, list every regional variant
- Write the canonical URL for each (de, de-AT, de-CH, etc.)
- Include x-default if you serve a language-agnostic default
Draw the annotation network on paper
Result: Missing links and broken reciprocals become visible.
- For each variant, write which other variants it should link to
- Ensure every variant links to itself
- Verify every target links back to the source
- Check x-default, if present, is universally reachable
Example complete loop for three variants:
DE (de-DE):
hreflang de → https://www.example.com/de/
hreflang en → https://www.example.com/en/
hreflang fr → https://www.example.com/fr/
hreflang x-default → https://www.example.com/
EN (en-US):
hreflang de → https://www.example.com/de/
hreflang en → https://www.example.com/en/
hreflang fr → https://www.example.com/fr/
hreflang x-default → https://www.example.com/
FR (fr-FR):
hreflang de → https://www.example.com/de/
hreflang en → https://www.example.com/en/
hreflang fr → https://www.example.com/fr/
hreflang x-default → https://www.example.com/
Every variant names every other variant plus itself.
Implement and verify
Add hreflang to one template at a time
Result: Each variant declares its complete link set.
- Edit the template for the first variant to emit the full network
- Deploy and fetch the page to confirm the annotations appear
- Move to the next variant only after the first is verified live
- Do not deploy all variants at once or assume they all match
<!-- Example hreflang in page head -->
<link rel="alternate" hreflang="de" href="https://www.example.com/de/" />
<link rel="alternate" hreflang="de-AT" href="https://www.example.com/de-at/" />
<link rel="alternate" hreflang="en" href="https://www.example.com/en/" />
<link rel="alternate" hreflang="fr" href="https://www.example.com/fr/" />
<link rel="alternate" hreflang="x-default" href="https://www.example.com/" />
<!-- Include self-reference -->
<link rel="alternate" hreflang="de" href="https://www.example.com/de/" />
Audit the complete network with a fetch loop
Result: Every variant verifies it links to every other variant as expected.
- Fetch each variant and extract all hreflang entries
- Compare each variant's set against the plan from step 2
- Flag any missing, broken, or incorrect links
- Retest after any template change
#!/usr/bin/env bash
# Audit hreflang network: fetch each variant and extract its links.
VARIANTS=(
"https://www.example.com/en/"
"https://www.example.com/de/"
"https://www.example.com/fr/"
)
for url in "${VARIANTS[@]}"; do
echo "=== $url ==="
curl -sSL "$url" | grep -oP 'hreflang="\K[^"]+|href="\K[^"]+(?=" />)' \
| paste -d' ' - - | sed 's/^/ /'
done
Handle x-default explicitly
Result: Users in unmatched regions are served a sensible fallback.
- Decide whether x-default points to a language-selection page, the strongest general variant, or geolocation-routed content
- Ensure the target is reachable without login or geofencing
- Verify x-default appears on every variant's annotation set
- Test by accessing from a region with no matching variant
Remove conflicting sitemap hreflang if present
Result: Head annotations are the single source of truth, never shadowed.
- Check whether the sitemap contains hreflang entries
- If present, remove them and keep only head annotations
- Purge the sitemap cache so crawlers see the update
- Verify the sitemap no longer declares language variants
Monitor which variant serves for each region
Result: You confirm the network is working by watching which page gets cited.
- Test topic queries from different languages and VPNs
- Record which variant is quoted for each location
- Check whether answers appear in the expected language
- Re-audit if any variant drifts to the wrong market
A correct closed loop is provable. Verify the paper network matches the live pages before you judge whether the annotation worked.
Hreflang and the visibility score
VISIBILITY INSIGHT
A broken hreflang network depresses every region's score equally
AI visibility is computed per language and region, and wrong-language citations or mismatched variants reduce every market's numbers. SearchDock helps by tracking which engine mentions which variant for your topics, so you can see whether the network routes users to the right region and whether citations appear in the expected language.
Check which language engines cite for your topicsThe network must form a closed loop. Incomplete loops read as broken annotations, not as preference hints.
Related localization and crawl diagnostics
Hreflang sits next to canonical logic and duplicate handling. These spokes isolate each layer so the fix targets what is actually broken.
Close the loop, then watch the network route traffic
Hreflang is a mutual agreement where every variant must declare every other variant including itself. One missing link breaks the pact for the entire set. Draw the network on paper, verify the live pages match, add the missing links, then remove any conflicting sitemap entries. Once every page reciprocates, crawlers can reliably route to the right variant and answer engines can serve answers in the user’s language.
See which engine variants and languages cite your topicsFrequently asked questions
What does hreflang actually do for AI search?
Hreflang tells crawlers which page represents which language and market. When annotations are correct, an answer engine serving a Spanish user can fetch the Spanish variant and quote it. When annotations are missing or wrong, the engine must guess which version to serve, often surfacing the wrong language or citing a variant nobody asked for.
Do I need hreflang if I use different domains per language?
Yes. Even separate domains need hreflang because crawlers fetch all of them and need to know which language each serves. Without annotations, an engine may cite the .de version for a user in France, or list both variants as duplicate content. Hreflang is not about SEO only; it is about disambiguation.
Is x-default required?
Not strictly, but it is strongly recommended. X-default tells crawlers which version to serve when no language or region exactly matches the user's preference. Without it, the engine guesses, which often produces a poor experience. Most multilingual sites benefit from an x-default pointing to either a geolocation-sensible version or a fallback language.
Why does hreflang in the sitemap not work?
Sitemap hreflang is a fallback parsed only when no head annotations exist on the page. If the page carries link rel=alternate annotations, the sitemap entry is ignored entirely. When you switch between methods, the old one can shadow the new one for months if cached. Use one method consistently and verify the live page, not the sitemap file.
Can hreflang annotations point to different canonicals?
No. All hreflang entries on a page must point to canonicals that reference back to each other forming a complete loop. If the French variant canonicalises to itself but its hreflang points to Germany, the contradiction breaks the relationship and engines ignore both.
How long does hreflang correction take to show results?
Recrawl usually takes a few weeks, and bigger sites take longer. Judge success by monitoring which version is cited for each user location rather than by ranking movement. A fixed annotation shows up in crawl logs immediately but takes longer to change which variant an engine prefers.
Do I need hreflang for subdirectories vs subdomains?
Yes. Whether you use /en/, /de/, or en.example.com, de.example.com, crawlers still need explicit annotations to know which variant serves which language and region. The URL structure you choose does not substitute for the annotation itself. Hreflang works the same way and requires the same complete, reciprocal linking across subdirectories, subdomains, and fully separate domains alike.