If your website exists in more than one language, or has different pages for different countries, search engines need a way to know which page belongs to which audience. Hreflang is that signal. It is a set of annotations that says "this page has an alternate version for this language or region, and here is its address."
Hreflang is easy to describe and easy to get wrong. The most common failures are missing return links, invented language codes and annotations that disagree with canonical tags. This guide is for site owners, developers and marketers who run a multilingual or multi-regional site. By the end you will have chosen one of the three supported methods, written a correct set of annotations, added an x-default fallback and checked the result.
This guide follows Google's documentation. Other search engines may handle language and region targeting differently, so check their own guidance if they matter to your audience.
Before you begin
You need a list of every page that has an equivalent in another language or region, and the final, live URL of each equivalent. Hreflang only works between pages that really are versions of each other, so a content map comes first.
- Access: edit rights to your page templates, your server's response headers, or your sitemap generator, depending on the method you choose.
- Time: an hour to plan, and then however long your templates or sitemap generator need. Large sites should generate the annotations from data rather than by hand.
- Risk: low for most sites, since annotations without return links are simply ignored. Even so, test on a copy of the site first if you can, because a template bug can put wrong annotations on thousands of pages at once.
- Backup: save the current templates, header configuration or sitemap files before editing.
Decide first whether each version is a different language (for example English and German), a different region (for example English for the United States and English for the United Kingdom), or both. That decision drives the codes you use.
What hreflang does and does not do
Google says hreflang annotations help it point users to the most appropriate version of a page by language or region. They are a hint for choosing between your own pages, not a way to make a page rank higher. Per the same documentation, Google does not use the HTML lang attribute or the hreflang annotations to detect what language a page is written in. It works that out from the visible content.
Hreflang also does not replace translation. Google notes that localized versions only count as duplicates when the main content stays untranslated. A page that is truly translated is a different page. For a comparison of URL layouts such as subdirectories and subdomains, see subdomain vs subdirectory for international SEO.
Step-by-step instructions
Step 1: Map every alternate version
Build a table with one row per page and one column per language or region. Each cell holds the full URL of that version, or stays empty if no version exists. Use the HTTPS, canonical form of each URL.
This matters because every annotation must point to a URL that exists, answers with a normal 200 status and is the version you want shown. Google also advises against listing HTTP versions of pages in hreflang. If a URL redirects or returns an error, remove it from the map until it is fixed. The canonical URL guide explains how to settle which form of a URL is the real one.
You have succeeded when every cell in your table is either empty or a working, final URL.
Step 2: Choose valid language and region codes
Hreflang values use a language code, optionally followed by a region code.
- The language is an ISO 639-1 code:
en,de,es,fr. - The region is an ISO 3166-1 Alpha 2 code, added after a hyphen:
en-GB,de-CH,es-MX. - A region on its own is not valid. Google says a bare country code such as
beis read as a language code, which is not what you meant. - Some codes that look sensible have no effect. Google lists
EU,UNandUKas having no effect; the code for the United Kingdom isGB. - Google says codes such as
es-419(Latin American Spanish) are not supported. - Script variants such as
zh-Hansandzh-Hantare supported, and a region can be added, as inzh-Hans-US. - Values are case-insensitive. Uppercase region codes are the convention, so use
en-GB.
If you have several regional versions of one language, Google suggests considering a generic version of that language (for example en) for visitors in places you have not specified.
You have succeeded when every language code in your table passes a check against the ISO lists and none is a country code on its own.
Step 3: Pick one implementation method
Google supports three equivalent methods. Pick one and use only that one. Google states that using all three together gives no benefit in Search and makes the setup harder to maintain.
| Method | Best when |
|---|---|
HTML <link> elements in the <head> |
You control page templates and have few versions per page |
HTTP Link response headers |
The files are not HTML, such as PDFs |
XML sitemap with xhtml:link entries |
You have many versions per page, or editing templates is hard |
Method 1, in the <head> of every version:
<link rel="alternate" hreflang="en-GB" href="https://example.com/en-gb/pricing/" />
<link rel="alternate" hreflang="en-US" href="https://example.com/en-us/pricing/" />
<link rel="alternate" hreflang="de" href="https://example.com/de/preise/" />
<link rel="alternate" hreflang="x-default" href="https://example.com/pricing/" />
Method 2, an HTTP header for a PDF that exists in two languages:
Link: <https://example.com/files/guide-en.pdf>; rel="alternate"; hreflang="en",
<https://example.com/files/guide-de.pdf>; rel="alternate"; hreflang="de"
Method 3, in the sitemap. Each version gets its own <url> entry, and every entry lists the same full set:
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:xhtml="http://www.w3.org/1999/xhtml">
<url>
<loc>https://example.com/en-gb/pricing/</loc>
<xhtml:link rel="alternate" hreflang="en-GB" href="https://example.com/en-gb/pricing/"/>
<xhtml:link rel="alternate" hreflang="de" href="https://example.com/de/preise/"/>
</url>
<url>
<loc>https://example.com/de/preise/</loc>
<xhtml:link rel="alternate" hreflang="en-GB" href="https://example.com/en-gb/pricing/"/>
<xhtml:link rel="alternate" hreflang="de" href="https://example.com/de/preise/"/>
</url>
</urlset>
A sitemap can only contain URLs under the directory where it is hosted, and the normal sitemap size limits still apply. If you are new to sitemaps, read how to create a valid XML sitemap first.
You have succeeded when only one method is live on the site and its output matches your table.
Step 4: Make every set reciprocal and self-referencing
Each version must list itself and every other version, and the list must be the same on every page. Google says that if page A names page B as an alternate but B does not name A, the annotations are ignored. This rule is what stops other sites from claiming to be an alternate of your pages.
All URLs must be fully qualified, which means they include the protocol: https://example.com/de/, not /de/ and not //example.com/de/. Alternate versions do not have to be on the same domain, so a country-code domain can sit in the same set as your main site.
If keeping complete sets is too hard, Google allows partial linking. It advises that you link new variants in both directions to the dominant or original language version at least.
You have succeeded when, for any two pages in a set, each one's annotations contain the other's URL.
Step 5: Add an x-default fallback
The x-default value marks the page to show when a visitor's language settings match none of your versions. It needs no language code. Google says it works best on a language selector page, and it typically points to a country picker or a generic home page.
<link rel="alternate" hreflang="x-default" href="https://example.com/choose-your-country/" />
It is optional, but a well-chosen fallback saves visitors from landing on a version they cannot read. Add the same x-default line to every page in the set.
You have succeeded when every set contains exactly one x-default entry.
Step 6: Keep canonical tags in agreement
Each language version should be its own canonical. Google advises specifying a canonical page in the same language when you use hreflang. Do not point the canonical of the German page at the English page; that tells Google the German page is a duplicate, and the hreflang set then contradicts it. Google also says rel="canonical" annotations that carry an hreflang attribute are not used for canonicalization, so keep the two signals in separate tags.
Google adds that when it chooses a canonical it prefers URLs that belong to a reciprocal hreflang cluster, so a clean set helps your intended pages win.
You have succeeded when each page's canonical points to itself and its hreflang set lists that same URL.
Step 7: Validate and monitor
Fetch each template type with a command-line tool and read the raw output, not just the browser's view:
curl -s https://example.com/de/preise/ | grep -i hreflang
curl -sI https://example.com/files/guide-en.pdf | grep -i '^link'
Then open the URL Inspection tool in Google Search Console for a few pages, and check that the rendered HTML contains the annotations if you inject them with JavaScript. Google mentions that third-party hreflang debugging tools exist but are not maintained or checked by Google, so treat them as a convenience only.
You have succeeded when the raw responses match the annotations you planned and a spot-check of ten pages finds no missing return links.
Final verification checklist
- Every alternate URL is HTTPS, fully qualified and returns a 200 status.
- Each page lists itself and all of its alternates, and the set is identical on every page.
- Every pair of pages in a set links to each other.
- Language codes are valid ISO 639-1 values, and region codes are valid ISO 3166-1 Alpha 2 values (
GB, notUK). - Only one method (HTML, header or sitemap) is in use.
- One
x-defaultentry exists per set. - Each page's canonical URL is its own URL, not another language's page.
- No alternate URL is blocked by robots.txt or carries a noindex directive.
- Language is not guessed from IP address or browser settings; each version has its own URL.
Common mistakes to avoid
- Missing return links. Page A points to B but B does not point back, so Google ignores the pair. Generate sets from one source of data so they stay symmetric.
- Country codes used as language codes.
beis read as a language, andUKhas no effect. Use the language first andGBfor the United Kingdom. - Relative URLs.
/de/is not accepted. Write the fullhttps://address. - Pointing canonicals at another language. This contradicts the hreflang set. Give each language its own self-referencing canonical.
- Listing redirecting or broken URLs. Annotate only final, working URLs.
- Using all three methods at once. It adds maintenance with no benefit in Search, and the copies drift apart.
- Relying on the
langattribute or meta tags. Google says it does not use them to detect language or location. They are fine for accessibility but are not a replacement for hreflang. - Redirecting visitors by guessed language. Google advises against automatic redirects based on a guess about the user's language, because they can stop users and crawlers from reaching all versions. Offer visible links to other versions instead.
Frequently asked questions
Does hreflang improve rankings?
No. Google describes it as a way to help point users to the most appropriate version. It does not add ranking strength. A correct set helps the right page show for the right audience; it does not make a weak page stronger.
Do I need hreflang if my pages are in different languages already?
Not strictly. Google may find alternate-language pages without annotations, but it says explicit annotations are usually best. If the versions are clearly distinct and well linked, hreflang is a useful extra rather than a requirement.
Can I use a language-only code and a language-and-region code together?
Yes. You can list en as a general English page and en-GB or en-US for specific regions in the same set. Google suggests a generic version for visitors in regions you have not named.
What if I have no good fallback page?
Then skip x-default. It is optional. If you do add one, a country or language selector is the usual choice, and Google says it works best there.
Where should I put hreflang for PDFs?
In an HTTP Link header, because a PDF has no <head>. Google lists the header method for non-HTML files. A sitemap entry also works for any URL.
How long does it take to work?
Google must recrawl the pages to see the annotations, and there is no fixed schedule. Check the pages again after a few weeks rather than expecting an instant change.
Related guides
- Subdomain vs Subdirectory for International SEO: Pick a Structure
- Fix Duplicate URLs and Incorrect Canonical Tags
- How to Create a Valid XML Sitemap for Your Website
- X-Robots-Tag Header: Noindex PDFs, Images and Other Files
Official references
- https://developers.google.com/search/docs/specialty/international/localized-versions
- https://developers.google.com/search/docs/specialty/international/managing-multi-regional-sites
- https://developers.google.com/search/docs/crawling-indexing/consolidate-duplicate-urls
Next step: See how Crawvix checks a website and capture a baseline once scanning opens. This guide provides technical information, not a guarantee of rankings, traffic or index inclusion.