Hreflang is an HTML attribute that tells Google which language or regional version of a page to show each searcher. You add it as a set of link annotations, and every version of the page lists itself and all its alternates. On a small site, setting it up takes an afternoon. The tags break when a page leaves out a return link or uses a code Google doesn't recognise.

Your site needs hreflang when the same content exists at more than one URL, in different languages or for different regions. A shop with English pages for the US and the UK fits that rule, even though the text barely changes between the two. So does a software company that translates its pricing page into German and French. In each case, hreflang tells Google to show the right URL in the right market, so a searcher in Vienna doesn't land on the US price list.
Hreflang only maps pages to each other. Google's algorithms identify a page's language from its content, according to its documentation on why it doesn't use hreflang for that task. A site in one language for one market gets nothing from the tags, and adding them anyway gives you more code to maintain.
John Mueller, Search Advocate at Google, described hreflang on X as "one of the most complex aspects of SEO" because it "gets really hard quickly." Before you write a single tag, list every page that has a localized twin and the URL of each version. That list is the input for every step below.
Pick one of the three places Google reads hreflang from and use only that one. Google accepts HTML link elements in the page head or annotations in HTTP response headers. It also accepts entries in the XML sitemap. All three carry the same information. They differ in who maintains them and in which files they can cover.
| Method | Where it lives | Fits best | Main drawback |
|---|---|---|---|
| HTML `<link>` elements | The `<head>` of each HTML page | Small and mid-sized sites where the CMS templates the head | Every page carries every alternate, so the markup grows with each new language |
| HTTP headers | The server response for each URL | PDFs and other files with no HTML head | Hard to audit, because the tags don't show in the page source |
| XML sitemap | `<xhtml:link>` entries inside each `<url>` | Large sites with many languages | Changes only reach Google when it next fetches the sitemap |
HTML `<link>` elements
HTTP headers
XML sitemap
Most sites end up with the HTML head because the CMS or a plugin already writes there. Sites with dozens of locales move to the sitemap because the page code stays light. Don't use two methods at once. In its hreflang study, Ahrefs found that conflicting annotations come from a mismatch between page code and sitemaps, and Google then has to guess which set to trust.
Before you move on, check that the method you chose can reach every URL on the list you built in the previous section.
To add hreflang tags to your site, give every page in a language set a tag for itself and for each alternate version. The steps below use the HTML method. The same logic applies to headers and sitemaps.
For a three-language pricing page, every one of the three pages carries this block:
<link rel="alternate" hreflang="en" href="https://example.com/pricing/" />
<link rel="alternate" hreflang="de" href="https://example.com/de/preise/" />
<link rel="alternate" hreflang="fr" href="https://example.com/fr/tarifs/" />
<link rel="alternate" hreflang="x-default" href="https://example.com/pricing/" />The language code comes first and uses the ISO 639-1 format, such as `de` or `fr`. The optional region follows a hyphen in ISO 3166-1 Alpha 2 format, such as `de-AT`. A region on its own is invalid, so `hreflang="at"` means nothing to Google. The UK is the classic trap: its region code is `GB`, so English for Britain is `en-GB` and `en-UK` is an error. Case doesn't matter, but keep it consistent so your audits stay readable.
Every `href` needs a fully qualified URL, including the protocol and the domain. Google's syntax notes specify the fully-qualified URL of each alternate. A relative path like `/de/preise/` doesn't qualify. Each URL must also return a 200 status code and be the canonical version of itself. If a German page canonicalizes to the English one, you're telling Google two opposite things about the same URL.
The x-default tag is optional for hreflang, but add one whenever there's a sensible page for searchers outside your listed markets. Google defines `x-default` as the value that matches any language not explicitly listed in your tags. Without it, a searcher in Portugal on a site with only English, German and French versions gets whichever page Google picks.
Point x-default at the page that serves an unmatched visitor best. That's a country or language selector, or your main English version. On a site that only publishes in German, point it at a page where non-German speakers can still convert. One page can be both a listed language and the x-default, as in the pricing example above.
Teams leave this tag out more than any other. Ahrefs' 2023 study of hreflang sites found x-default missing on 56.3% of them. Check that the x-default line is identical in every page of a cluster, because it follows the same return rules as any other tag.
Every page you list in a hreflang set has to list the page that listed it. If the English page points to the German page and the German page doesn't point back, Google ignores the pair. Google requires that rule because anyone could otherwise claim another site's page as their own translation. A return link proves that both page owners agree.
Ahrefs' study found that missing return links affected 15.3% of domains; 18% lacked the self-referencing tag. When a page leaves itself out, its cluster is incomplete. Mueller has said the self-reference is optional, but the major audit tools flag it, and including it costs one line.
To fix hreflang return tag errors, start from the audit report. It names the page that points out and the page that fails to point back. Open the second page and add the missing line. Then check why it was missing. The usual causes are:
The lasting fix is to generate every block from one list of URL clusters, so adding a locale updates all pages at once. Hand-edited tags will drift again within a few releases.
European sites need region codes more than most, because the same language covers several countries with different prices and laws. Spelling also differs between these countries. German is spoken in Germany and Austria. It is also spoken in Switzerland. A site with separate pages for those three markets carries this block on each of them:
<link rel="alternate" hreflang="de-DE" href="https://example.com/de-de/" />
<link rel="alternate" hreflang="de-AT" href="https://example.com/de-at/" />
<link rel="alternate" hreflang="de-CH" href="https://example.com/de-ch/" />
<link rel="alternate" hreflang="de" href="https://example.com/de-de/" />
<link rel="alternate" hreflang="x-default" href="https://example.com/" />The plain `de` line catches German speakers in Luxembourg or Belgium, who match no regional code. Belgium needs extra care because its pages target two languages. Use `nl-BE` and `fr-BE` for the Belgian versions, and keep them separate from `nl-NL` and `fr-FR` if prices or delivery terms differ.
<link rel="alternate" hreflang="nl-BE" href="https://example.com/be-nl/" />
<link rel="alternate" hreflang="fr-BE" href="https://example.com/be-fr/" />
<link rel="alternate" hreflang="nl-NL" href="https://example.com/nl/" />
<link rel="alternate" hreflang="fr-FR" href="https://example.com/fr/" />Only create a regional split when the pages actually differ. Two identical German pages for Germany and Austria, with the same euro prices, add maintenance without helping anyone. One `de` page would serve both.
In a sitemap, each `<url>` entry carries one `<xhtml:link>` line for every version of that page, itself included. You also declare the XHTML namespace in the opening `<urlset>` tag. Here's the English pricing page from earlier:
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:xhtml="http://www.w3.org/1999/xhtml">
<url>
<loc>https://example.com/pricing/</loc>
<xhtml:link rel="alternate" hreflang="en" href="https://example.com/pricing/" />
<xhtml:link rel="alternate" hreflang="de" href="https://example.com/de/preise/" />
<xhtml:link rel="alternate" hreflang="x-default" href="https://example.com/pricing/" />
</url>
</urlset>The German and French URLs each need their own `<url>` entry with the same set of links. That repetition is how the sitemap expresses return links. Leave one entry out and the cluster breaks, just as it would in HTML.
Once the sitemap holds your hreflang, remove the tags from the page head so the two sources can't drift apart. Submit the sitemap in Google Search Console. Then confirm Google has fetched it recently, because your changes don't count until it does.
Most hreflang errors trace back to a handful of causes, and each one has a fix you can make at the website template level. Ahrefs' study of 374,756 domains found 67% had at least one hreflang issue. The table lists errors audit tools report, with the share of domains Ahrefs measured where it reported one.
| Error | What it looks like | Fix | Share of domains (Ahrefs) |
|---|---|---|---|
| Missing self-reference | Page lists only its alternates | Add a line pointing to the page's own URL | 18% |
| Missing return link | Page A lists page B, page B doesn't list page A | Add the line on page B, then generate all blocks from one list | 15.3% |
| Same page for two languages | One URL appears under `en` and `de` | Give each language its own URL | 2.5% of domains |
| Invalid code | `en-UK`, `eng`, or a region alone such as `at` | Use ISO 639-1 language plus ISO 3166-1 region, as in `en-GB` | Not reported |
| Non-canonical target | Tag points to a URL whose canonical is a different page | Point the tag at the canonical URL, or fix the canonical | Not reported |
| Broken or redirected target | Tag points to a 404 or a 301 | Replace with the live final URL | Not reported |
Missing self-reference
Missing return link
Same page for two languages
Invalid code
Non-canonical target
Broken or redirected target
Fix the errors in order of reach. A template bug, such as a wrong code in the site-wide header, breaks every page at once, so it comes first. A single missing return link on a low-traffic page can wait for the next pass. After each fix, recrawl the affected cluster rather than the whole site so you can see the change take effect.
Your hreflang setup works when a crawler finds no errors and Google shows the right version in each market. Run both checks, because the first can pass while the second fails.
Start with a site crawler that reads hreflang. Screaming Frog and Sitebulb report missing return links and invalid codes. Ahrefs Site Audit reports these errors too. Ahrefs' audit also checks the head and HTTP headers against sitemap annotations to catch conflicts between methods. Set the crawl to recur weekly or monthly, since new pages are where errors creep back in.
Next, open Google Search Console and use URL Inspection on one page per locale. Check that the Google-selected canonical matches the URL you listed in your tags. If Google picked a different canonical, it's treating your translation as a duplicate, and the hreflang for that page won't count.
Last, search for a branded query as a user in each target market would. You can change the country and language settings in Google's search preferences. Check that a searcher in Austria sees the `de-AT` URL. If they don't after Google has recrawled the cluster, go back to the error table.
Build your URL cluster list first and make it the single source every hreflang block is generated from. Every fix on this page rests on it. Return links and x-default go wrong when someone edits one page by hand and forgets the others. The same mistake affects sitemap entries. With the list in place, adding a new locale becomes one entry instead of an edit on every page in the set.
Snoika audits websites for technical SEO errors like these and tracks how each language version appears in Google and in AI assistants, and its team reviews the results. To check your hreflang setup with a person who works on this every day, talk to an AI search expert.
Hreflang identifies alternate language or regional versions of a page so the appropriate URL can appear in search results. It connects localized pages rather than determining their language, which is identified from the content.
An x-default tag is optional, but it's useful when you have a suitable fallback page for visitors outside your listed languages or regions. Point it to a language selector or your main language version, and keep it consistent across alternate pages.
Add the missing reciprocal annotation to the page that doesn't point back to its alternate. Use the exact live, canonical URL, then recrawl the affected pages. Generating annotations from one shared URL list helps prevent the error from recurring.
Sitemap changes can only be processed after the search engine fetches the updated file. There's no fixed turnaround given in this guide. Check when the sitemap was last fetched, then verify the displayed regional versions after the affected pages have been recrawled.
Yes, one language-specific page can serve several countries when its content and commercial terms are the same. Use a language-only code such as de. Create separate regional versions when differences such as prices or delivery terms justify them.


