Hreflang is an annotation that tells Google which language and regional versions of a page exist, so it can show each searcher the version meant for them. It does not raise rankings and it does not translate anything. It swaps URLs: if your English page ranks for a query in Germany and you have declared a German equivalent, Google can show the German URL instead. It only works when every version references every other version, itself included, with valid codes.
Do you need it?
You need hreflang if either of these is true:
- The same content exists in several languages (
/en/pricing,/de/preise). - The same language is served to several regions with differences such as currency, shipping, spelling or legal text (
en-us,en-gb,en-au).
You can skip it if you have one language for one market, or if your translated sections are completely different pages with no one-to-one equivalents.
The anatomy of an annotation
<link rel="alternate" hreflang="en-gb" href="https://www.example.com/uk/pricing">
hreflangholds a language code, optionally followed by a region code.hrefis the fully qualified URL of that version, includinghttps://.
Valid codes
| Part | Standard | Examples | Notes |
|---|---|---|---|
| Language | ISO 639-1 | en, de, fr, pt, zh |
Required |
| Region | ISO 3166-1 alpha-2 | gb, us, at, br |
Optional, never alone |
| Script | ISO 15924 | zh-Hant, zh-Hans |
Optional, for languages with several scripts |
Rules that catch people:
- The language always comes first.
de-atis German for Austria.atalone is invalid, because you cannot target a country without a language. - The United Kingdom is
gb, notuk.en-ukis invalid. - There is no code for regions such as the EU, Latin America or "international".
en-euis invalid. List the countries, or use a plain language code. - Codes are not case sensitive, and the separator is a hyphen.
en_GBwith an underscore is invalid. - A plain language code (
es) acts as a catch-all for all speakers of that language not covered by a more specific entry (es-mx).
The three rules
1. Every version lists all versions, itself included. A page with three language versions carries three annotations (four with x-default), and the block is the same on all three pages.
2. Links must be reciprocal. If the English page points to the German page, the German page must point back. Google's documentation is explicit that annotations without a return link may be ignored. This protects you: nobody else can declare their page an alternate of yours.
3. URLs must be absolute and should be the canonical, indexable version. An hreflang target that redirects, returns 404, is blocked by robots.txt or carries noindex cannot be used.
Method 1: HTML link elements
Put the full set in the <head> of every version:
<head>
<link rel="canonical" href="https://www.example.com/de/preise">
<link rel="alternate" hreflang="en" href="https://www.example.com/en/pricing">
<link rel="alternate" hreflang="en-gb" href="https://www.example.com/uk/pricing">
<link rel="alternate" hreflang="de" href="https://www.example.com/de/preise">
<link rel="alternate" hreflang="x-default" href="https://www.example.com/">
</head>
Good for small to medium sites. The cost is page weight: 30 languages means 30 lines on every page. As with canonical tags, the elements must really be inside the head. A script or an unknown tag placed above them can cause the HTML parser to end the head early, and everything after that is ignored.
You can build the block with the Hreflang Tag Generator.
Method 2: HTTP headers
For PDFs and other non-HTML files:
Link: <https://www.example.com/en/guide.pdf>; rel="alternate"; hreflang="en",
<https://www.example.com/de/guide.pdf>; rel="alternate"; hreflang="de",
<https://www.example.com/guide.pdf>; rel="alternate"; hreflang="x-default"
Method 3: XML sitemap
Each <url> entry lists all alternates, itself included, using the xhtml:link element:
<?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/en/pricing</loc>
<xhtml:link rel="alternate" hreflang="en" href="https://www.example.com/en/pricing"/>
<xhtml:link rel="alternate" hreflang="de" href="https://www.example.com/de/preise"/>
<xhtml:link rel="alternate" hreflang="x-default" href="https://www.example.com/"/>
</url>
<url>
<loc>https://www.example.com/de/preise</loc>
<xhtml:link rel="alternate" hreflang="en" href="https://www.example.com/en/pricing"/>
<xhtml:link rel="alternate" hreflang="de" href="https://www.example.com/de/preise"/>
<xhtml:link rel="alternate" hreflang="x-default" href="https://www.example.com/"/>
</url>
</urlset>
This is the best option for large sites. It keeps the HTML light, the whole mapping lives in one generated file, and you can change it without touching templates. The alternates do not count towards the 50,000 URL limit, only <loc> entries do, but they do increase file size, so watch the 50 MB limit. See sitemap index files for large sites.
Google treats the three methods as equivalent. Pick one. Using two in parallel gives you two sources that can disagree.
x-default
hreflang="x-default" marks the URL to show when none of your listed languages or regions matches the user. Typical choices:
- A language or country selector page.
- The homepage that redirects or adapts by user preference.
- Your main English version, if that is your de facto international version. The same URL may carry both
enandx-default.
Hreflang and canonical tags
This pairing causes the most silent failures.
- Each language version should have a self-referencing canonical.
- Hreflang URLs should be those canonical URLs.
The broken pattern looks like this: all language versions declare the English page as canonical, often because a template hard-codes it. You are telling Google that the German page is a duplicate of the English one and should be dropped, while also saying it is an alternate that should be shown to German users. The canonical usually wins, and the German page disappears.
For same language regional versions (en-us and en-gb with nearly identical text), Google may still fold them together as duplicates and select one canonical. Correct hreflang often still lets the right URL be displayed for each country, but Search Console reports will show one of them as a duplicate. Meaningful localisation (currency, addresses, delivery information, spelling) reduces this. There is more about how Google picks canonicals in the canonical tags guide.
Common errors
Missing return links. The most frequent error. It happens when one language is added later and the older templates are not updated, or when some pages have no translation. Only annotate pages that have a real equivalent, and generate the set from one shared data source.
Invalid codes. en-uk, sp for Spanish (it is es), jp for Japanese (it is ja), cn for Chinese (it is zh), en_US.
Pointing at non-canonical URLs. Trailing slash mismatches, http://, URLs with parameters, or URLs that redirect.
Relative URLs. href="/de/preise" is not valid for hreflang.
Pointing every language at the homepage. The German product page should reference the English product page, not the English homepage. Hreflang is page to page.
Blocking or noindexing some versions. A version Google cannot crawl or index cannot take part in the cluster.
Automatic redirects by IP or browser language. Googlebot crawls mostly from the United States and does not send an Accept-Language header. If you redirect US visitors from /de/ to /en/, Googlebot may never see /de/. Google recommends against automatic redirection. Show a banner that suggests the other version and let the user choose.
Expecting hreflang to fix untranslated content. If /fr/ contains English text with a French navigation, hreflang will not make it rank in France. Google determines the language from the visible content of the page. It does not use the lang attribute or the URL for that.
Testing and monitoring
Google removed the International Targeting report from Search Console in 2022, so there is no built-in hreflang error report any more. You need to check it yourself:
- Run key templates through the Hreflang Checker, which reads the annotations on a page, validates the codes and checks the return links.
- Crawl the site with a crawler that supports hreflang validation and look for missing reciprocals, non-200 targets and conflicts with canonical tags.
- In Search Console, filter the Performance report by country and check which URLs receive impressions. If
/en/pages receive most of the impressions from Germany while/de/equivalents exist, something is off. - After deploying, inspect one URL per language with URL Inspection and confirm that each is indexed under its own canonical.
Changes take time to show. Google has to recrawl every page in a cluster before the set is consistent, so expect weeks on larger sites.
Choosing a URL structure
Hreflang works with any of these, as long as each version has its own URL:
| Structure | Example | Notes |
|---|---|---|
| Country code domains | example.de |
Strongest geographic signal. Most expensive to run. |
| Subdomains | de.example.com |
Easy to host separately. Each host needs its own robots.txt and its own Search Console property unless you use a Domain property. |
| Subdirectories | example.com/de/ |
Simplest to maintain. One host, one sitemap setup. |
| Parameters | example.com/?lang=de |
Not recommended by Google. Hard to segment and easy to break. |
What does not work is serving different languages at the same URL based on cookies or headers. Googlebot sees one version only, and there is nothing for hreflang to point at.
Get three things right (one URL per version, self-canonical pages, a complete reciprocal set of annotations) and hreflang is a setup you rarely have to revisit.
Frequently asked questions
- Does hreflang improve rankings?
- No. Hreflang does not make any page rank higher. It helps Google swap in the most suitable language or regional version of a page that already ranks, so users land on the right one.
- Do I need hreflang if my site is only in one language?
- No. Hreflang only matters when you have more than one version of the same page for different languages or regions. A single language site targeting one market gains nothing from it.
- Can I use hreflang for the same language in different countries?
- Yes, and it is one of the most useful cases. English pages for the US, UK and Australia with different prices or spelling can be annotated as en-us, en-gb and en-au, which helps Google show the right one and understand that they are intentional variants.
- Does Bing use hreflang?
- Bing has said hreflang is a far weaker signal for it than for Google. It relies more on the content-language meta tag or HTTP header, the html lang attribute, and other location signals. Setting the lang attribute correctly is worthwhile for both.
- What is hreflang x-default for?
- It names the fallback URL for users whose language or region does not match any of your listed versions. It is usually a language selector page or your main international version. It is optional but recommended.