In short
hreflang tells Google that several URLs are language or regional versions of the same page, so it can show each searcher the right one. Every version must list itself and all the others with full URLs, and every pair must link both ways, or Google ignores the unpaired links. You can declare the set in HTML, in an HTTP header or in your XML sitemap; pick one method, use valid codes and keep each version as its own canonical.
What hreflang does and when to use it
hreflang is an annotation that connects alternate versions of a page. It says: “this URL is the German version, that one is for English speakers in the UK, and this one is the fallback for everyone else”. Google can then show the British page to a searcher in the UK and the German page to a German speaker, instead of whichever version happens to be strongest.
Google lists three situations where you should mark up alternate versions:
- “If you keep the main content in a single language and translate only the template, such as the navigation and footer.” Forums and other user-generated content often work this way.
- “If your content has small regional variations with similar content, in a single language.” For example, English pages for the US, the UK and Ireland that differ in prices, spelling and delivery details.
- “If your site content is fully translated into multiple languages.” For example, German and English versions of every page.
Google separates two kinds of international site. A multilingual site offers content in more than one language, such as a Canadian business with English and French pages. A multi-regional site explicitly targets users in different countries, such as a manufacturer that ships to Canada and the United States. Many sites are both. hreflang handles both cases, because each value can name a language, or a language plus a region.
What hreflang does not do
- It does not set the page language. Google detects language from the visible content, not from hreflang or the
langattribute. - It is not a ranking boost. It helps Google swap in the right version for a searcher; it does not make the cluster rank higher.
- It does not replace canonicals. When two URLs show the same content in the same language, you still choose a preferred version with
rel="canonical". - It is not a directive. Google uses it to pick a version for the searcher, along with other signals.
What Google officially says
“If you have multiple versions of a page for different languages or regions, tell Google about these different variations. Doing so will help Google Search point users to the most appropriate version of your page by language or region.”
Google Search Central — Tell Google about localized versions of your page“If two pages don't both point to each other, the tags will be ignored.”
Google Search Central — Tell Google about localized versions of your page. The reason: “someone on another site can't arbitrarily create a tag naming itself as an alternative version of one of your pages.”More direct quotes from the same documentation:
- “Note that even without taking action, Google might still find alternate language versions of your page, but it is usually best for you to explicitly indicate your language- or region-specific pages.”
- “Localized versions of a page are only considered duplicates if the main content of the page remains untranslated.”
- “The three methods are equivalent from Google's perspective and you can choose the method that's the most convenient for your site.”
- “Google doesn't use hreflang or the HTML lang attribute to detect the language of a page; instead, we use algorithms to determine the language.”
- “Google recommends using different URLs for each language version of a page rather than using cookies or browser settings to adjust the content language on the page.”
Language and region codes
An hreflang value has one part, or two parts separated by a hyphen. The first part is always the language, in ISO 639-1 format. The optional second part is the region, in ISO 3166-1 Alpha 2 format. Google is strict about the standards: “Only language codes listed in ISO 639-1 and region codes listed in ISO 3166-1 Alpha 2 are supported; other codes that aren't listed in those standards, such as es-419, aren't supported.”
“The hreflang value is case-insensitive”, so en-gb and en-GB mean the same. Writing the region in capitals follows the ISO convention and is easier to read. Use a hyphen, not the underscore that many CMS locale settings use (en_GB).
The most important rule: “You can't specify the country code by itself.” Google “doesn't automatically derive the language from a country code.” Google's own example is Belgium. To reach Dutch, French and German speakers there, you use nl-BE, fr-BE and de-BE. A plain be is wrong, because be is the language code for Belarusian.
Reserved or invented region codes do nothing. Google says “using EU, UN, or UK in hreflang annotations doesn't have an effect on Google Search”. The United Kingdom is GB, so the correct value is en-GB, never en-UK.
For languages written in more than one script, the script is normally derived from the region: zh-TW implies Traditional Chinese. You can also name the script with an ISO 15924 code: zh-Hant (Traditional), zh-Hans (Simplified), or with a region, zh-Hans-US.
| Value | Verdict | Why |
|---|---|---|
de | ✓ Valid | German, any region |
en-GB | ✓ Valid | English for users in the United Kingdom |
de-ES | ✓ Valid | German for users in Spain; any valid language-region pair works |
zh-Hant | ✓ Valid | Chinese, Traditional script |
en-UK | ✕ Region ignored | UK is not the ISO code; use en-GB |
en-EU | ✕ Region ignored | EU is reserved, not a country |
es-419 | ✕ Not supported | Not an ISO 3166-1 Alpha 2 region |
be for Belgium | ✕ Wrong | Means Belarusian; use nl-BE, fr-BE, de-BE |
jp, dk, se | ✕ Wrong | Country codes used as languages; Japanese is ja, Danish da, Swedish sv |
ua, gr | ✕ Wrong | Ukrainian is uk, Greek is el |
en_GB | ✕ Wrong format | Use a hyphen: en-GB |
The rules every hreflang set must follow
The three methods differ in where the annotations live, but the rules are the same for all of them.
- Self-reference. “Each language version must list itself as well as all other language versions.”
- An identical set everywhere. “The set of links is identical for every version of the page.” If you have five versions, each of the five carries the same five annotations.
- Return links. If page X names page Y, page Y must name page X. Annotations without a return link are ignored. Google adds that if a complete set is hard to maintain, “you can omit some languages on some pages; Google will still process the ones that point to each other.” Its advice is to link new language versions to your original, strongest language first.
- Fully-qualified URLs. “Alternate URLs must be fully-qualified, including the transport method (http/https)”:
https://example.com/de/, not//example.com/de/or/de/. - Any domain. “Alternate URLs do not need to be in the same domain.”
example.deandexample.com/en/can be in one set. - HTTPS. Google's canonical documentation says: “Don't include the HTTP version of your pages in your sitemap or hreflang annotations rather than the HTTPS version.”
- A catch-all for each language. If you have English pages for Ireland (
en-IE), Canada (en-CA) and Australia (en-AU), Google suggests you “provide a generic English (en) page for searchers in the US, UK, and all other English-speaking locations.” It can be one of the regional pages. - Healthy targets. In practice, every URL in the set should return 200, be indexable, not be blocked in robots.txt, not redirect, and be the canonical URL of that version. A target that fails any of these cannot send a valid return link.
✕ Broken set
<head>
<link rel="canonical"
href="https://example.com/en/">
<link rel="alternate" hreflang="en-UK"
href="https://example.com/en-gb/">
<link rel="alternate" hreflang="en"
href="/en/">
<!-- no line for the de page itself -->
</head>
- Canonical to another language
UKis not a region code- Relative URL
- No self-reference, no x-default
✓ Correct
<head>
<link rel="canonical"
href="https://example.com/de/">
<link rel="alternate" hreflang="de"
href="https://example.com/de/">
<link rel="alternate" hreflang="en-GB"
href="https://example.com/en-gb/">
<link rel="alternate" hreflang="en"
href="https://example.com/en/">
<link rel="alternate" hreflang="x-default"
href="https://example.com/">
</head>
- Self-referencing canonical
- Valid ISO codes
- Absolute HTTPS URLs
- Lists itself, all versions and x-default
Method 1: HTML link elements
Add one <link rel="alternate" hreflang="…" href="…"> element per version to the <head> of every version, including the page's own line. This is the usual choice when you do not have a sitemap or cannot set HTTP headers.
Two technical rules matter. “The <link> tags must be inside a well-formed <head> section of the HTML.” A stray element in the head, such as an <img> or a <div> injected by a script, can make the browser close the head early, and every hreflang link after it then lands in the body. And “don't combine hreflang annotations with other attributes such as media in a single <link> tag.”
A site with a generic English page, a UK page, a US page, a German page and a selector page would put this block in the head of all five:
<link rel="alternate" hreflang="en-GB" href="https://example.com/en-gb/page/" />
<link rel="alternate" hreflang="en-US" href="https://example.com/en-us/page/" />
<link rel="alternate" hreflang="en" href="https://example.com/en/page/" />
<link rel="alternate" hreflang="de" href="https://example.com/de/page/" />
<link rel="alternate" hreflang="x-default" href="https://example.com/" />
Keep the block in the HTML your server sends. Tags added or changed by JavaScript only exist after rendering, and when the raw and rendered HTML disagree you are sending two different sets.
Method 2: HTTP Link header
The same set can travel in the HTTP response. Google notes: “This is useful for non-HTML files (like PDFs).” A PDF has no <head>, so the server sends a Link header with all versions, separated by commas:
Link: <https://example.com/en/guide.pdf>; rel="alternate"; hreflang="en",
<https://example.com/de-ch/guide.pdf>; rel="alternate"; hreflang="de-CH",
<https://example.com/de/guide.pdf>; rel="alternate"; hreflang="de"
Each URL sits inside angle brackets. “The Link: header returned for every version of a page is identical”, so all three PDFs return exactly this header. You set it in the web server or CDN configuration, which also makes it the easiest method to forget about when files move.
Method 3: XML sitemap
In a sitemap, each version gets its own <url> entry with a <loc>, and each entry carries one <xhtml:link> child per version, itself included. Three versions mean three entries, each with the same three children. Declare the xhtml namespace on the <urlset>:
<?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://example.com/en/page/</loc>
<xhtml:link rel="alternate" hreflang="en" href="https://example.com/en/page/"/>
<xhtml:link rel="alternate" hreflang="de" href="https://example.de/page/"/>
<xhtml:link rel="alternate" hreflang="de-CH" href="https://example.de/ch/page/"/>
</url>
<url>
<loc>https://example.de/page/</loc>
<!-- the same three xhtml:link lines -->
</url>
<url>
<loc>https://example.de/ch/page/</loc>
<!-- the same three xhtml:link lines -->
</url>
</urlset>
Useful details from Google: the order of the children does not matter, and “Child elements don't count towards the URL limit for sitemaps.” The normal sitemap rules still apply, including that a sitemap can only contain URLs below the directory it is hosted in. In practice, a sitemap that lists URLs on other domains, as above, works when you have verified all of those domains in Search Console.
Which method to choose
For Google the methods are equivalent. You can use all three at once, but Google says “there's no benefit in Search”, and three implementations are much harder to keep in sync than one. The practical choice depends on your site:
HTML <link> | HTTP Link header | XML sitemap | |
|---|---|---|---|
| Where it lives | In the <head> of each page | In the server response of each URL | In <xhtml:link> children of each <url> |
| Best for | Small and medium sites, CMS plugins | PDFs and other non-HTML files | Large sites, many languages, separate systems per country |
| Visible on the page | Yes, in the source | Only in response headers | No, only in the sitemap file |
| Page weight | Grows with every language added | None in the HTML | None in the HTML |
| Main risk | Tags pushed into <body>, JavaScript changes, template drift | Forgotten in server config after changes | Sitemap goes stale when URLs change |
| How to check | View source and the rendered HTML | curl -I or the browser's network panel | Parse the file, compare entries pair by pair |
What causes trouble is mixing methods by accident. A typical audit finding: a plugin prints HTML tags, someone later adds hreflang to the sitemap, and the two sets disagree on a URL or a code. If you switch methods, remove the old annotations, or make sure both produce exactly the same set.
x-default: the fallback page
“The reserved x-default value is used when no other language/region matches the user's browser setting.” It tells Google where to send searchers you have no version for, for example a Portuguese speaker on a site with only English and German pages.
Google adds: “While you can use the x-default value for any page, it was designed for language selector pages and so it will work best with those.” The value has no language code, because the page is meant for everyone not matched elsewhere. Google's example:
<link rel="alternate" href="https://example.com/en-gb" hreflang="en-GB" />
<link rel="alternate" href="https://example.com/en-us" hreflang="en-US" />
<link rel="alternate" href="https://example.com/en-au" hreflang="en-AU" />
<link rel="alternate" href="https://example.com/country-selector" hreflang="x-default" />
x-default is recommended, not required. If you have no selector page, it is common practice to use your main or international version, often the English one. The same URL can carry both a language code and x-default, for example hreflang="en" and hreflang="x-default" both pointing to https://example.com/en/. Like every other line, the x-default line belongs in the set on every version.
hreflang and canonical together
The two annotations answer different questions. The canonical says which URL represents a group of duplicates. hreflang says which URLs are alternates of each other. They work together only when each version is its own canonical.
- Self-canonical per version.
https://example.com/de/has a canonical to itself,https://example.com/en/to itself, and so on. - Never canonicalise across languages. Google's rule: “If you're using hreflang elements, make sure to specify a canonical page in the same language, or the best possible substitute language if a canonical page doesn't exist for the same language.” A canonical from
/de/to/en/tells Google the German page is a duplicate, and it can drop the German page out of the cluster. - Point hreflang only at canonical URLs. If an hreflang target canonicalises somewhere else, the annotation and the canonical contradict each other.
- Keep the two tags separate. “rel="canonical" annotations with hreflang, lang, media, and type attributes are not used for canonicalization.” A single
<link rel="canonical" hreflang="de">does neither job.
Same-language regional versions
Pages for the US, UK and Australia in English are usually very similar. They are still valid alternates, and hreflang is exactly what lets Google show the right one. Give each version a self-referencing canonical, and make the differences real: currency, prices, spelling, delivery and contact details.
When you have true duplicates in the same language, Google's advice is different. If “both example.de/ and example.com/de/ show similar German language content”, you should “pick 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.” The non-preferred URL canonicalises to the preferred one, and only the preferred one appears in the hreflang set.
hreflang also feeds canonical selection: “for canonicalization purposes Google prefers URLs that are part of hreflang clusters.” In Google's example, /de-de/cats and /de-ch/cats point to each other, /de-at/cats is left out, and the two linked pages are preferred as canonicals over the /de-at/ page.
URL structures for international sites
Each language or regional version needs its own URL. Google describes four ways to build them:
| Structure | Example | Pros | Cons |
|---|---|---|---|
| Country-specific domain (ccTLD) | example.de | Clear geotargeting; server location irrelevant; easy separation of sites | Expensive, limited availability; more infrastructure; strict ccTLD requirements in some countries; targets a single country |
| Subdomain with gTLD | de.example.com | Easy to set up; allows different server locations; easy separation of sites | Users might not recognise the targeting from the URL (is “de” the language or the country?) |
| Subdirectory with gTLD | example.com/de/ | Easy to set up; low maintenance on one host | Users might not recognise the targeting from the URL; single server location; separation harder |
| URL parameter | example.com/?loc=de | Not recommended by Google | URL-based segmentation is difficult; users might not recognise the targeting |
Words in the URL do not set the target. Google says the subdomains en, en-gb, en-us and de in its example “are not used by Google to determine the target audience for the page; you must explicitly map the target audience.” Localised words and internationalised domain names are fine; use UTF-8 and escape the URLs properly in links.
To decide a page's target locale, Google uses ccTLDs, hreflang “whether in tags, headers, or sitemaps”, server location (not a definitive signal, because of CDNs) and other signals such as local addresses and phone numbers, local language and currency, links from local sites and a Business Profile. It ignores locational meta tags such as geo.position.
Not every two-letter domain counts as a country. Google treats .eu and .asia as generic, and also a list of ccTLDs that people use generically, including .ai, .co, .io, .me and .tv. A site on example.io is not targeted at the British Indian Ocean Territory; it needs hreflang to show which version is for whom.
Automatic redirects, IP detection and language switchers
Redirecting visitors by IP address or browser language looks helpful, but Google advises against it for two reasons.
Googlebot may never see your other versions. If you reroute users based on language settings, “Google might not find and crawl all your variations. This is because the Googlebot crawler usually originates from the USA. In addition, the crawler sends HTTP requests without setting Accept-Language in the request header.” A site that redirects every US visitor to /en-us/ may redirect Googlebot there too, every time.
Users get trapped. Google's guidance: “Avoid automatically redirecting users from one language version of a site to a different language version of a site.” “These redirections could prevent users (and search engines) from viewing all the versions of your site.” On IP detection specifically: “Don't use IP analysis to adapt your content. IP location analysis is difficult and generally not reliable.” Think of a German speaker in Spain, or a traveller on a hotel network.
What to do instead:
- A switcher with normal links. “Consider adding hyperlinks to other language versions of a page.” Use crawlable
<a href>links to the equivalent page, not just to the home page of each version. - A suggestion, not a redirect. If you detect a likely mismatch, show a dismissible banner such as “View this page in German?” and remember the choice.
- A redirect only on a selector URL. If the root URL is a pure selector, redirecting from it is a design choice; mark it as x-default and make sure every localised URL stays reachable directly, with no redirect.
- Separate URLs, not cookies. Content that changes language by cookie on the same URL cannot be indexed per language.
Check the URLs in your hreflang sets
OurSEO Tools crawls up to 1,000 pages and records the status code, canonical and indexability of every URL, so you can confirm that each language version returns 200, is indexable and is its own canonical.
Common mistakes
- ✕Missing return linksPage X names page Y, but Y does not name X. It is first on Google's list of common mistakes; such annotations are ignored.
- ✕No self-referenceEach version must list itself, not only the others.
- ✕Wrong codes
en-UK,en-EU,es-419, a country code on its own,jpfor Japanese, underscores instead of hyphens. - ✕Targets that redirect, 404 or are noindexTypical after a migration: hreflang still points to old URLs. The target must be the final, indexable URL.
- ✕Targets that are not canonicalhreflang points to a parameter URL or another duplicate that canonicalises elsewhere.
- ✕Canonical across languagesAll language versions canonicalised to the English page.
- ✕Relative or HTTP URLs
/de/orhttp://instead of the fullhttps://address. - ✕Methods mixed inconsistentlyHTML tags and the sitemap list different sets, or an old plugin still prints tags after a switch to sitemaps.
- ✕One code, two URLsThe same
hreflangvalue points to two different URLs in one set. - ✕Tags outside the headAnnotations in
<body>, or a head closed early by an invalid element. - ✕Linking to the home page onlyThe German product page names the English home page instead of the English product page.
- ✕Forced redirects by IP or browser languageGooglebot and users cannot reach every version.
How to audit hreflang step by step
- Crawl every version, all domains and folders, and export the hreflang set of each URL from HTML, headers and the sitemap.
- Check self-reference and completeness: each URL lists itself and the same set as its alternates.
- Check return links pair by pair: if A names B with a code, B names A.
- Validate every code against ISO 639-1 and ISO 3166-1 Alpha 2, and check for duplicate codes in one set.
- Check every target: absolute HTTPS URL, status 200, no redirect, no
noindex, not blocked in robots.txt. - Check canonical alignment: each target's canonical is itself and in the same language.
- Compare sources: if more than one method is in use, the sets must be identical; compare raw and rendered HTML on key templates too.
- Check the language of each page: one language for content and navigation, translated titles and descriptions, no side-by-side translations.
- Check redirects: request the localised URLs without cookies and without an
Accept-Languageheader, as Googlebot does, and confirm none redirect. - Check Search Console: use URL Inspection on samples to see that each version is indexed as its own canonical, and the Performance report filtered by country to see which version gets impressions where.
Google points to third-party hreflang generators and testing tools, with a caveat: they “are not maintained or checked by Google.” Search Console's old International Targeting report has been retired, so a crawl is now the main way to check a whole site.
FAQ
Does hreflang improve rankings?
No. It helps Google show the most suitable version of a page to each searcher. It does not make the pages rank higher, and it cannot make a version rank in a country where it would not rank on its own merits.
Is x-default required?
No, it is recommended. Use it for a language or country selector, or point it at your main international version. Without it, Google chooses the version itself for users you have no match for.
Do I need hreflang if my pages are in different languages anyway?
Google may find alternate language versions without it, but its advice is that “it is usually best for you to explicitly indicate your language- or region-specific pages.” For same-language regional versions, hreflang is the main way to tell Google which one is for whom.
Does Google use the lang attribute or the URL to detect language?
No. Google determines language from the visible content. Keep the lang attribute correct for browsers and accessibility, but it is not what Google uses.
Can I use HTML tags and a sitemap at the same time?
Yes, but there is no benefit in Search, and two sources are harder to keep identical. If they disagree, you are sending contradictory signals. Pick one.
Should the canonical of every language point to the main language?
No. Pages in different languages are not duplicates. Each version gets a self-referencing canonical, and hreflang connects them.
Sources
- Google Search Central — Tell Google about localized versions of your page
- Google Search Central — Managing multi-regional and multilingual sites
- Google Search Central — How to specify a canonical URL
Quotes checked against the official pages on 30 October 2026.