# Hreflang: The Complete Guide to Tags, Rules and Errors

> Hreflang tags explained: correct syntax, the three rules Google enforces silently, hreflang plus canonical done right, and how to check for errors.

- URL: https://missiongrowth.io/blog/hreflang
- Published: 2026-07-09 · Updated: 2026-09-24
- Author: Ömer Furkan Aktaş, Founder, Mission Growth
- Publisher: Mission Growth. Company facts: https://missiongrowth.io/llms.txt

Hreflang tells Google and other search engines which localized URL to serve for a given language and region. Get the syntax right and every reader lands on the version built for them. Get one of three specific rules wrong and Google drops the entire annotation set, no warning, no error message anywhere in Search Console.

The tag itself isn't the hard part. Three assumptions are: that self-referencing is optional, that a canonical tag cancels out hreflang, and that Google quietly corrects a reserved code like UK. None of those hold up against Google's own current documentation. This guide resolves each one against Google's dated Search Central pages directly.

In this guide:
- The 3 implementation methods, and which one to pick for your setup
- The 3 rules that fail silently, with no Search Console warning
- Which codes Google actually reads, and which ones it drops
- How hreflang and canonical tags actually work together
- A checking workflow that matches what Google's documentation says today

## What hreflang actually does (and what it doesn't)

Hreflang tells search engines which localized URL to serve for a specific language and region. It plays no role in ranking and no role in language detection.

Google's Search Central documentation is explicit about why: its own algorithms determine what language a page is written in, independent of hreflang or the HTML `lang` attribute. Hreflang's only job is routing. Given several localized versions of the same content, it tells Google which one belongs in front of which audience.

Confusing routing with detection has a real cost. Teams spend hours getting a tag onto every template while skipping the two things that actually decide whether Google honors it: a reciprocal link between every pair of localized pages, and a code Google recognizes. Both come next.

## The 3 ways to implement hreflang, and which one to pick

Hreflang can be declared three ways: an HTML link tag, an HTTP header, or an XML sitemap entry. Google treats all three as functionally equivalent.

The right choice depends on what you already control on your site, and running more than one adds no extra signal.

Here's how the same pair of pages looks in two of those formats:

```html
<link rel="alternate" hreflang="en-gb" href="https://example.com/uk/page" />
<link rel="alternate" hreflang="en-us" href="https://example.com/us/page" />
```

::figure{src="/blog/figures/hreflang-1.svg" alt="Code panels comparing an HTML link tag and an XML sitemap entry declaring the same hreflang pair, both read as equivalent by Google" caption="An HTML link tag and an XML sitemap entry for the same pair of pages; Google also accepts the same signal in an HTTP header for non-HTML files." width="720" height="262"}

For a file that isn't HTML, such as a PDF, the same signal goes in the response header instead: `Link: <https://example.com/us/page>; rel="alternate"; hreflang="en-us"`. And in an XML sitemap, the same pair sits inside the `<url>` block for each page:

```xml
<url>
  <loc>https://example.com/uk/page</loc>
  <xhtml:link rel="alternate" hreflang="en-us" href="https://example.com/us/page" />
</url>
```

Which one fits depends on what you're already managing:

| Method | Pick it when |
|---|---|
| HTML link tag | You control page templates and want the fastest rollout |
| HTTP header | The URL isn't HTML (PDFs and other non-HTML files) |
| XML sitemap | You manage many localized URLs centrally and don't want to touch every template |

Pick exactly one and stay with it. Running two or three in parallel doesn't add signal. It adds a second place for the set to drift out of sync the moment a page moves or a new locale launches, and nobody notices until traffic to that locale quietly drops.

That drift shows up most often after a URL structure changes. A sitemap-based hreflang set keeps listing the old paths while the templates already serve new ones, and nothing flags the mismatch. If a restructure is coming, rebuild the hreflang set as part of [site migration seo](https://missiongrowth.io/blog/site-migration-seo) planning, not as an afterthought once the new URLs are live.

## The 3 rules Google enforces silently

Hreflang fails silently on three specific conditions: a missing self-reference, a one-way link instead of a reciprocal one, or an invalid code.

Google drops the annotation instead of flagging it. There's no Search Console warning telling you which one broke.

The first rule: every language version has to list itself in its own hreflang set. Google's Search Central documentation is direct about it: each version must include itself alongside every other version. A widely cited claim credits Google's John Mueller with framing self-referencing as "optional, but good practice." Google's current written documentation states it as a requirement, full stop.

The second rule: reciprocity. If page A points to page B, page B has to point back to A. Skip that and Google ignores the annotation on both pages. Neither one counts as part of a verified set.

The third: an invalid code. That one causes the most damage because it's the easiest to get wrong without noticing, so it gets its own section next.

```html
<!-- on /uk/page -->
<link rel="alternate" hreflang="en-gb" href="https://example.com/uk/page" />
<link rel="alternate" hreflang="en-us" href="https://example.com/us/page" />

<!-- on /us/page -->
<link rel="alternate" hreflang="en-us" href="https://example.com/us/page" />
<link rel="alternate" hreflang="en-gb" href="https://example.com/uk/page" />
```

Because there's no error message, you can't wait for a warning to tell you something broke. Check for all three conditions on a schedule, the way the workflow near the end of this guide walks through.

## The specific mistakes that get an hreflang set ignored

Hreflang silently drops part of its set on two specific mistakes: a reserved region code, and a code Google doesn't support at all.

The first shows up as UK, EU or UN used as a region. The second shows up as es-419, reached for as shorthand for Latin American Spanish.

Google's documentation states plainly that using EU, UN or UK as a region code "doesn't have an effect on Google Search." It's tempting to assume Google's parsers correct the mistake instead. What actually happens is narrower: Google ignores that part of the annotation, and the URL it was attached to falls out of the hreflang set entirely.

Getting hreflang codes right is what keeps the rest of the set intact. Google's hreflang system recognizes exactly two code standards: language codes from ISO 639-1, paired where needed with a two-letter region code from ISO 3166-1 Alpha-2. 419 isn't one of the accepted region codes, so es-419 gets the same treatment as UK or EU: quietly dropped.

::figure{src="/blog/figures/hreflang-2.svg" alt="A table contrasting valid ISO 639-1 and ISO 3166-1 hreflang codes with reserved codes UK, EU and UN and the unsupported code es-419 that Google ignores" caption="Valid codes like en-gb and de-ch get read normally; reserved codes and es-419 are silently dropped from the hreflang set." width="720" height="369"}

Valid examples look like en-gb, de-ch or pt-br: a lowercase ISO 639-1 language code, sometimes paired with an uppercase ISO 3166-1 Alpha-2 region. Passing markup validation is not the same as Google reading every alternate. A reserved or unsupported code throws no error. It quietly removes that one URL from the set Google actually uses.

An incomplete rollout, where only some locales carry a code Google recognizes, creates the same near-duplicate risk [index bloat](https://missiongrowth.io/blog/index-bloat) covers in more depth. Running separate country domains multiplies the chances of a code mismatch across teams and templates, which is one reason [enterprise seo](https://missiongrowth.io/blog/enterprise-seo) treats domain consolidation as its own checklist.

## Hreflang and canonical tags: how they actually work together

Hreflang works alongside a self-referencing canonical tag on every localized page, and that's Google's documented normal setup for international sites. The hreflang vs canonical question only gets complicated in one specific case.

A common assumption treats hreflang and canonical tags as mutually exclusive, as though combining them means Google ignores one of the two. Google's own documentation on consolidating duplicate URLs says something narrower: a `rel="canonical"` element stops working for consolidation only when it also carries `hreflang`, `lang`, `media` or `type` attributes stacked onto it. A separate hreflang tag next to an ordinary one on the same page is unaffected.

Google also uses hreflang-cluster membership as a signal in its own right when it picks a canonical page. Its documentation gives a specific example: if de-de and de-ch reciprocally link to each other through hreflang but neither links to de-at, Google prefers de-de and de-ch over the excluded de-at page. Reciprocal cluster membership is itself something Google weighs when deciding which page to prefer.

Don't remove the tag to protect hreflang. That fix solves a problem that doesn't exist and creates a real one. Keep every localized page pointed at itself, reciprocally linked through hreflang, and let Google's cluster logic do the rest. Rel=canonical basics on their own are covered separately in our canonical tag guide.

## x-default: what it's for and when it's worth adding

x-default marks the URL Google should show when no language or region variant matches the visitor.

Setting up x-default hreflang correctly means pointing it at an actual language or country selector page, since that's where Google says it performs best. On an ordinary translated page, it adds little.

Google's own documentation confirms that x-default can technically sit on any page. It also states plainly that the tag was designed for language and country selector pages, and that it works best on those. x-default doesn't have to point at a translated variant of the current page at all. It can point at a completely different one, such as a selector screen:

```html
<link rel="alternate" hreflang="x-default" href="https://example.com/select-region" />
```

Whether it's worth adding a page just for this depends on what already exists:

| Situation | What to do |
|---|---|
| You already have a language or country selector page | Point x-default at it |
| You have a global landing page that works for any visitor | Point x-default at it |
| Neither exists | Use a plain generic-language version, such as `en`, as x-default instead of building a new page |

Building a selector page purely to give x-default a home is rarely worth it. A generic-language version handles the same unmatched-visitor case without adding a page nobody else links to.

## How to check hreflang for errors

Checking for hreflang errors starts with a crawl, using a tool that reads the annotation natively, such as Screaming Frog.

Check every questionable pair against Google's own current troubleshooting guidance, which points to third-party validators rather than a first-party report.

As of September 2026, Google's documentation for debugging hreflang names two third-party validators: Aleyda Solis's hreflang tags generator and Merkle's hreflang tag testing tool. It doesn't lead with a first-party Search Console report. Some checking workflows still open with Search Console's International Targeting report as the first step; Google's current documentation simply doesn't point there first, since tooling recommendations like this date quickly.

A crawl-based check catches the three silent-failure conditions directly:

- **Self-reference.** Every localized URL should list itself inside its own hreflang set.
- **Reciprocity.** For every pair, confirm both directions exist instead of only one.
- **Code validity.** Match language codes against ISO 639-1 and region codes against ISO 3166-1 Alpha-2, then flag anything that looks like UK, EU, UN or es-419.

A crawl won't catch one failure mode if the crawler doesn't execute JavaScript: hreflang tags injected only after client-side rendering. A tool reading the raw HTML never sees a tag that only appears once the page renders in a browser.

We migrated our own React single-page app to prerendered static HTML across 20 marketing pages for exactly this reason: AI crawlers don't execute JavaScript. The same gap catches any crawler you've pointed at the raw HTML without enabling JavaScript rendering. For the full render-strategy decision between server-side, client-side and static rendering, see [javascript seo](https://missiongrowth.io/blog/javascript-seo).

A correct hreflang implementation fails quietly on points where a specific claim and Google's own current documentation disagree. Resolving each one against Google's dated Search Central pages is what actually gets a set read correctly.

Start with a crawl of the set you already have: check self-reference, reciprocity and code validity in that order, and fix what it finds before adding another locale.

## FAQ

### How do you pronounce "hreflang"?

There's no official pronunciation. Most practitioners say the letters "H-R-E-F" followed by "lang," or spell the whole thing out. Google has never published a preferred pronunciation, so there's nothing to get wrong here, only a convention people land on differently.

### Is hreflang a ranking factor?

No. Hreflang tells Google which URL to serve to which audience; it doesn't influence rank. Google determines ranking and page language independently of whatever hreflang set is in place.

### Does hreflang have to be used on same-language pages targeting different countries, like en-us and en-gb?

Yes, when the content genuinely differs: pricing, spelling, currency. If the content is identical across both, a single generic-language page with an x-default tag covers the same case without maintaining two near-identical URLs.

### Do the alternate URLs have to be on the same domain?

No. Google explicitly allows hreflang alternates to sit on completely different domains, as long as each URL is absolute and every pair in the set links back to each other reciprocally.

### Can I skip hreflang on a small international site?

You can. Hreflang only signals a preference to Google; it doesn't behave like a hard directive. An incomplete or absent set doesn't cause lasting harm. It just means Google decides which localized URL to show, which is worth deciding directly once a site passes a handful of pages.
