Hreflang is one of the easiest technical SEO features to get slightly wrong. The tags look simple, but every page in a set has to agree with every other page, and a single typo in a code silently breaks it. There’s no error message, just the wrong version showing up in search.
This guide covers how hreflang works, the five mistakes that break it most often, and how to find them across a whole site.
How does hreflang work?
Hreflang tells Google that several URLs are versions of the same content for different languages or regions. In HTML, each version includes a <link> for every version:
<link rel="alternate" hreflang="en" href="https://example.com/en/" />
<link rel="alternate" hreflang="en-GB" href="https://example.com/uk/" />
<link rel="alternate" hreflang="vi-VN" href="https://example.com/vi/" />
<link rel="alternate" hreflang="x-default" href="https://example.com/" />
Google’s guide to localized versions sets the rules:
- Hreflang can be set in HTML, in HTTP headers, or in an XML sitemap.
- Language codes use ISO 639-1, with an optional region in ISO 3166-1 Alpha 2, separated by a dash:
en,en-GB,vi-VN. - “If two pages don’t both point to each other, the tags will be ignored.”
- “Each language version must list itself as well as all other language versions.”
- The reserved value x-default is used “when no other language/region matches the user’s browser setting.”
Nearly every hreflang error breaks one of those rules.
The 5 most common hreflang errors
1. Invalid language or region codes
The classic mistake is en-UK. The ISO code for the United Kingdom is GB, and Google says using EU, UN or UK in hreflang has no effect. Other frequent ones:
- a region on its own, like
GB, with no language - language names instead of codes, like
english - three-letter language codes where a two-letter one exists
- an underscore instead of a dash, like
en_GB
Fix: use a two-letter ISO 639-1 language code, optionally followed by a dash and a two-letter ISO 3166-1 country code. Scripts are allowed between them where needed, like zh-Hant-TW.
2. Missing return links
Page A lists page B as its German version, but page B doesn’t list page A. Google ignores one-way annotations, so the pair doesn’t count. This usually happens when one market’s template is updated and another’s isn’t, or when a page is translated into only some languages.
Fix: generate hreflang for all versions from one shared source, like a CMS field or translation table, so every page outputs the same full set.
3. Alternates that aren’t indexable
The alternate URL redirects, returns an error, is noindexed, or has a canonical pointing somewhere else. That breaks the set, because the URL you named isn’t the one that can be indexed.
Fix: point hreflang only at the final, indexable, self-canonical URL of each version. After a migration or URL change, update hreflang at the same time as the redirects.
4. No self-reference
A page lists its alternates but not itself. Google’s rule is that each version must list itself as well as all the others.
Fix: include the page’s own URL with its own language code in the set. A shared template that outputs the full list on every page handles this automatically.
5. No x-default
Without x-default, Google has no instruction for users whose language or region matches none of your versions. It isn’t required, but it’s the recommended fallback.
Fix: add hreflang="x-default" pointing to a language selector or your main international version.
How do you find hreflang errors across a site?
Checking source code page by page works for a handful of URLs. For a whole site, a crawler has to collect every annotation and check each pair against the others. Crawlens reads <link rel="alternate" hreflang> tags from every crawled page and runs five checks:
| Check | What it flags | Severity |
|---|---|---|
| Invalid hreflang codes | Values that aren’t valid language(-script)(-region) codes, such as en-UK |
Warning |
| Hreflang without return links | Alternates that don’t link back to the page | Warning |
| Hreflang points to non-indexable URLs | Alternates that redirect, error, are noindexed or canonicalised elsewhere | Warning |
| Hreflang set without a self-reference | Pages that don’t list themselves | Notice |
| Hreflang set without x-default | Pages whose set has no x-default | Notice |
One limitation to know: Crawlens checks hreflang in the HTML. If your site declares hreflang in HTTP headers or an XML sitemap instead, check those with a tool that reads them.
Checklist
- Every code is ISO 639-1 language, optional ISO 3166-1 region (
en-GB, noten-UK) - Every page lists every version, including itself
- Every alternate links back
- Every alternate URL is final, 200, indexable and self-canonical
- An x-default points to a selector or main version
- Hreflang generated from one shared source for all markets
- Hreflang updated together with redirects after URL changes
Frequently asked questions
What is hreflang?
Hreflang is an annotation that tells search engines which pages are language or regional versions of each other, so Google can show the right version to each user. It can be set in the HTML, in HTTP headers or in an XML sitemap.
Why is en-UK an invalid hreflang code?
Region codes use ISO 3166-1 Alpha 2, where the United Kingdom is GB, not UK. Google states that using EU, UN or UK in hreflang annotations has no effect. Use en-GB instead.
What is a hreflang return link?
If page A lists page B as an alternate, page B must also list page A. Google says that if two pages don't both point to each other, the annotations are ignored.
Do I need x-default?
It's not required, but recommended. x-default tells Google which page to show users whose language or region doesn't match any of your versions, typically a language selector or your main version.
Should a page include itself in its hreflang tags?
Yes. Google says each language version must list itself as well as all other language versions.