Skip to the journal
Search Engine Optimization Directory

Hreflang Tag: Complete Guide

  • Filed November 10, 2026
  • Migrations and international sites, guide 1 of 4

Hreflang annotations tell Google which URLs are language or regional versions of the same content, so it can show the right version to a searcher. They do not make a page rank in a country, they do not tell Google what language a page is in, and they are ignored when they are not reciprocal. Google’s documentation on localized versions sets the rules precisely (Google’s guide to localized versions), and the errors described below each trace back to a departure from one of them.

What hreflang does and does not do

Does: helps Google swap in the appropriate language or regional URL among versions it already considers equivalent.

Does not:

  • detect language. Google states it “doesn’t use hreflang or the HTML lang attribute to detect the language of a page; instead, we use algorithms to determine the language”.
  • create ranking in a region. A Spanish page for Mexico still has to be relevant and competitive for searches in Mexico.
  • make translated pages duplicates or prevent duplication. Google says localized versions “are only considered duplicates if the main content of the page remains untranslated”.
  • replace Search Console country targeting, which Google retired. Its help page says the International Targeting report “has been deprecated” and that country targeting is “no longer supported”, while hreflang continues to be supported (Google’s International Targeting deprecation note).

Codes: language, optional region

The value is a language code, optionally followed by a region code: en, en-GB, es-MX, de-AT.

Google’s rules:

  • Languages use ISO 639-1 codes; regions use ISO 3166-1 Alpha 2 codes. Codes outside those standards, “such as es-419”, are not supported.
  • “Specifying the region alone is not valid”. hreflang="US" does nothing.
  • Using EU, UN or UK in annotations “doesn’t have an effect on Google Search”. The United Kingdom’s ISO code is GB, so en-GB is correct and en-UK is not.

The x-default value

x-default names the fallback URL for users whose language or region matches none of the listed versions. Google describes it as designed for language selector pages, and its guide recommends a fallback page for unmatched languages, “especially on language/country selectors or auto-redirecting home pages”.

Three equivalent methods

Google supports three ways to declare alternates and says “The three methods are equivalent from Google’s perspective”:

  1. HTML <link> elements in the <head>.
  2. HTTP headers, useful for non-HTML files such as PDFs.
  3. XML sitemaps, useful for large sites where editing every page head is impractical.

Use one method per set of pages. Mixing methods makes errors harder to find.

The rules implementations break

  • Self-reference. “Each language version must list itself as well as all other language versions”.
  • Reciprocity. “If two pages don’t both point to each other, the tags will be ignored”.
  • Absolute URLs. “Alternate URLs must be fully-qualified”. Alternates may be on different domains.
  • Canonical alignment. Each language version should be its own canonical (near-identical same-language regional pages are the exception discussed below). Pointing the canonical of the German page to the English page tells Google the German page is a duplicate, which contradicts the hreflang annotation.
  • Indexable targets. Every URL in the set should return 200, be indexable and not redirect.

Google allows one relaxation: if maintaining a complete bidirectional set becomes difficult, some languages can be omitted on some pages, and Google “will still process the ones that point to each other”, though newly expanded language pages should be linked bidirectionally to the originating language.

Annotation examples by method

Example 1: one language, three regions, plus a selector (HTML). On each of the three pages and the selector page, the same block appears:

<link rel="alternate" hreflang="en-US" href="https://www.example.com/us/" />
<link rel="alternate" hreflang="en-GB" href="https://www.example.com/uk/" />
<link rel="alternate" hreflang="en-AU" href="https://www.example.com/au/" />
<link rel="alternate" hreflang="x-default" href="https://www.example.com/" />

Each page lists itself and all others, so the set is self-referencing and reciprocal.

Example 2: language without region. A site with one Spanish version for all Spanish speakers uses hreflang="es". If it later adds a Mexico-specific version, the set becomes es (general Spanish) and es-MX, and users in Mexico are served es-MX while other Spanish speakers get es.

Example 3: sitemap method.

<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
        xmlns:xhtml="http://www.w3.org/1999/xhtml">
  <url>
    <loc>https://www.example.com/de/preise/</loc>
    <xhtml:link rel="alternate" hreflang="de" href="https://www.example.com/de/preise/" />
    <xhtml:link rel="alternate" hreflang="fr" href="https://www.example.com/fr/tarifs/" />
    <xhtml:link rel="alternate" hreflang="x-default" href="https://www.example.com/pricing/" />
  </url>
  <url>
    <loc>https://www.example.com/fr/tarifs/</loc>
    <xhtml:link rel="alternate" hreflang="de" href="https://www.example.com/de/preise/" />
    <xhtml:link rel="alternate" hreflang="fr" href="https://www.example.com/fr/tarifs/" />
    <xhtml:link rel="alternate" hreflang="x-default" href="https://www.example.com/pricing/" />
  </url>
  <url>
    <loc>https://www.example.com/pricing/</loc>
    <xhtml:link rel="alternate" hreflang="de" href="https://www.example.com/de/preise/" />
    <xhtml:link rel="alternate" hreflang="fr" href="https://www.example.com/fr/tarifs/" />
    <xhtml:link rel="alternate" hreflang="x-default" href="https://www.example.com/pricing/" />
  </url>
</urlset>

The urlset element declares both the sitemap namespace and the xhtml namespace, and each URL in the set has its own <url> entry listing the same three alternates, so the file is a complete sitemap and the set is reciprocal.

Example 4: HTTP header for a PDF.

Link: <https://www.example.com/de/katalog.pdf>; rel="alternate"; hreflang="de", <https://www.example.com/fr/catalogue.pdf>; rel="alternate"; hreflang="fr"

The header is sent as a single line with the entries separated by commas, which is how Google’s syntax line gives it; Google’s worked example shows the same header wrapped across lines.

These examples are illustrative; adapt URLs to the real site and validate each set.

Diagnosing errors

Symptom Likely cause Check
Wrong regional page shown Missing return links or region-only codes Confirm every page lists every other page; check codes
Annotations ignored Non-reciprocal set or relative URLs Fetch each URL in the set and read its annotations
Version not indexed Canonical points to another language or the URL redirects URL Inspection: Google-selected canonical
Same-language pages competing Near-identical content for different regions without hreflang Pick a preferred version and use canonical and hreflang together
Invalid code warnings in third-party tools <!–INLINECODE19–>, <!–INLINECODE20–>, region alone Correct to ISO 639-1 and ISO 3166-1 Alpha 2

Google notes that third-party hreflang testing tools “are not maintained or checked by Google”, so treat their output as findings to verify.

Same-language regional duplicates

When two regional pages are in the same language and very similar (for example, example.de/ and example.com/de/), Google’s multi-regional guide recommends picking a preferred version “and use the rel=”canonical” element and hreflang tags to make sure that the correct language or regional URL is served to searchers” (managing multi-regional sites). Hreflang alone does not make near-duplicates distinct.

A worked two-URL decision. Suppose https://www.example.de/preise/ and https://www.example.com/de/preise/ both show a German pricing page. The first question is whether anything on the pages differs for their audiences.

  • They differ for their audiences (for example, euro prices and German delivery terms on one, Swiss franc prices and Swiss delivery terms on the other). These are regional variations. Keep each URL as its own canonical and annotate both in one reciprocal set:
<link rel="alternate" hreflang="de-DE" href="https://www.example.de/preise/" />
<link rel="alternate" hreflang="de-CH" href="https://www.example.com/de/preise/" />

This follows the pattern of Google’s own example for pages with “substantially the same content, but with regional variations”, where each regional URL is listed in the hreflang set (Google on localized versions).

  • Nothing differs for any audience. Pick one preferred URL, for example https://www.example.de/preise/, and point the other URL’s canonical to it, as the multi-regional guide describes:
<!-- on https://www.example.com/de/preise/ -->
<link rel="canonical" href="https://www.example.de/preise/" />

In our reading, the preferred URL is then the one to list for German-speaking users in any hreflang set, so the canonical and the annotations point to the same page.

Verification for either choice: URL Inspection on both URLs shows the Google-selected canonical. If Google selects a different canonical from the one declared, the pages are probably more alike than the plan assumed, and the regional differences need to be visible in the main content.

Related decisions outside hreflang

  • Automatic redirects by language. Google’s guide advises against automatically redirecting users from one language version to another; let users choose.
  • IP-based content changes. Google says, “Don’t use IP analysis to adapt your content”.
  • Site structure. Choosing ccTLDs, subdomains or subfolders for international versions is a separate decision; hreflang works with any of them.

Hreflang is bookkeeping: a complete, reciprocal, correctly coded list of equivalent pages. When that list is accurate, Google can swap in the right version. Where a page breaks the list, the annotations it affects are ignored and Google falls back to its own choice for those pages.