Free tool Hreflang generator and code checker
hreflang tells Google which language or regional version of a page to show to whom. The syntax is simple and easy to get subtly wrong: en-UK instead of en-GB, an underscore, a relative URL, or a page that forgets to list itself. Write one line per version and get all three formats, with each mistake explained.
- ISO 639-1 and 3166-1 checked
- Tags, sitemap and header
- Runs locally
List your language versions
One version per line: a language code, optionally with script or region, then the full URL. Try the button to see how common mistakes are reported.
Format: code URL, e.g. en-GB https://example.com/uk/. Spaces, tabs or commas between them all work, so you can paste two spreadsheet columns.
Optional. The page for everyone whose language matches none of the above, often a language selector or your main version.
Versions
| Code | Meaning | URL | Status |
|---|---|---|---|
en | English | https://www.example.com/ | Valid |
en-GB | British English | https://www.example.com/uk/ | Valid |
en-US | American English | https://www.example.com/us/ | Valid |
de-DE | German (Germany) | https://www.example.com/de/ | Valid |
zh-Hans | Simplified Chinese | https://www.example.com/zh-hans/ | Valid |
x-default | Everyone else | https://www.example.com/ | Valid |
Checklist
- OK5 language versions, all codes and URLs valid.
- NotePut this same set of 6 lines on every URL listed. Each page must list itself and all the others; if page A lists B but B does not list A, Google ignores the pair.
<link rel="alternate" hreflang="en" href="https://www.example.com/" />
<link rel="alternate" hreflang="en-GB" href="https://www.example.com/uk/" />
<link rel="alternate" hreflang="en-US" href="https://www.example.com/us/" />
<link rel="alternate" hreflang="de-DE" href="https://www.example.com/de/" />
<link rel="alternate" hreflang="zh-Hans" href="https://www.example.com/zh-hans/" />
<link rel="alternate" hreflang="x-default" href="https://www.example.com/" />Inside <head> of every page listed, identical on each.
Link: <https://www.example.com/>; rel="alternate"; hreflang="en", <https://www.example.com/uk/>; rel="alternate"; hreflang="en-GB", <https://www.example.com/us/>; rel="alternate"; hreflang="en-US", <https://www.example.com/de/>; rel="alternate"; hreflang="de-DE", <https://www.example.com/zh-hans/>; rel="alternate"; hreflang="zh-Hans", <https://www.example.com/>; rel="alternate"; hreflang="x-default"
# Nginx (server / location)
add_header Link '<https://www.example.com/>; rel="alternate"; hreflang="en", <https://www.example.com/uk/>; rel="alternate"; hreflang="en-GB", <https://www.example.com/us/>; rel="alternate"; hreflang="en-US", <https://www.example.com/de/>; rel="alternate"; hreflang="de-DE", <https://www.example.com/zh-hans/>; rel="alternate"; hreflang="zh-Hans", <https://www.example.com/>; rel="alternate"; hreflang="x-default"';
# Apache (.htaccess, mod_headers)
Header set Link "<https://www.example.com/>; rel=\"alternate\"; hreflang=\"en\", <https://www.example.com/uk/>; rel=\"alternate\"; hreflang=\"en-GB\", <https://www.example.com/us/>; rel=\"alternate\"; hreflang=\"en-US\", <https://www.example.com/de/>; rel=\"alternate\"; hreflang=\"de-DE\", <https://www.example.com/zh-hans/>; rel=\"alternate\"; hreflang=\"zh-Hans\", <https://www.example.com/>; rel=\"alternate\"; hreflang=\"x-default\""For PDFs and other non-HTML files. Nginx and Apache versions included.
<?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/</loc>
<xhtml:link rel="alternate" hreflang="en" href="https://www.example.com/"/>
<xhtml:link rel="alternate" hreflang="en-GB" href="https://www.example.com/uk/"/>
<xhtml:link rel="alternate" hreflang="en-US" href="https://www.example.com/us/"/>
<xhtml:link rel="alternate" hreflang="de-DE" href="https://www.example.com/de/"/>
<xhtml:link rel="alternate" hreflang="zh-Hans" href="https://www.example.com/zh-hans/"/>
<xhtml:link rel="alternate" hreflang="x-default" href="https://www.example.com/"/>
</url>
<url>
<loc>https://www.example.com/uk/</loc>
<xhtml:link rel="alternate" hreflang="en" href="https://www.example.com/"/>
<xhtml:link rel="alternate" hreflang="en-GB" href="https://www.example.com/uk/"/>
<xhtml:link rel="alternate" hreflang="en-US" href="https://www.example.com/us/"/>
<xhtml:link rel="alternate" hreflang="de-DE" href="https://www.example.com/de/"/>
<xhtml:link rel="alternate" hreflang="zh-Hans" href="https://www.example.com/zh-hans/"/>
<xhtml:link rel="alternate" hreflang="x-default" href="https://www.example.com/"/>
</url>
<url>
<loc>https://www.example.com/us/</loc>
<xhtml:link rel="alternate" hreflang="en" href="https://www.example.com/"/>
<xhtml:link rel="alternate" hreflang="en-GB" href="https://www.example.com/uk/"/>
<xhtml:link rel="alternate" hreflang="en-US" href="https://www.example.com/us/"/>
<xhtml:link rel="alternate" hreflang="de-DE" href="https://www.example.com/de/"/>
<xhtml:link rel="alternate" hreflang="zh-Hans" href="https://www.example.com/zh-hans/"/>
<xhtml:link rel="alternate" hreflang="x-default" href="https://www.example.com/"/>
</url>
<url>
<loc>https://www.example.com/de/</loc>
<xhtml:link rel="alternate" hreflang="en" href="https://www.example.com/"/>
<xhtml:link rel="alternate" hreflang="en-GB" href="https://www.example.com/uk/"/>
<xhtml:link rel="alternate" hreflang="en-US" href="https://www.example.com/us/"/>
<xhtml:link rel="alternate" hreflang="de-DE" href="https://www.example.com/de/"/>
<xhtml:link rel="alternate" hreflang="zh-Hans" href="https://www.example.com/zh-hans/"/>
<xhtml:link rel="alternate" hreflang="x-default" href="https://www.example.com/"/>
</url>
<url>
<loc>https://www.example.com/zh-hans/</loc>
<xhtml:link rel="alternate" hreflang="en" href="https://www.example.com/"/>
<xhtml:link rel="alternate" hreflang="en-GB" href="https://www.example.com/uk/"/>
<xhtml:link rel="alternate" hreflang="en-US" href="https://www.example.com/us/"/>
<xhtml:link rel="alternate" hreflang="de-DE" href="https://www.example.com/de/"/>
<xhtml:link rel="alternate" hreflang="zh-Hans" href="https://www.example.com/zh-hans/"/>
<xhtml:link rel="alternate" hreflang="x-default" href="https://www.example.com/"/>
</url>
</urlset>One <url> per version, each listing all versions.
Share these inputs: the values go after the # in the link, so they never reach a server.
https://tapcub.com/tools/hreflang-generator
Version v1.0Updated Update history
What the generator tells you
The table shows how each code is read; the checklist explains anything that is wrong or worth a second look; the three code blocks are the same set in three formats.
Code and meaning
Each valid code is shown in its conventional form with its meaning, so you can spot a code that is valid but not what you meant: uk is Ukrainian, se is Northern Sami, DE alone means German, not Germany.
Errors and left-out lines
Codes Google would ignore (en-UK, jp, zh_CN, es-419) and relative URLs are errors. Those lines are left out of the output so you never copy a broken tag; the message suggests the correct form.
Fallbacks
If you have en-GB and en-US but no plain en, English speakers elsewhere match nothing. Google suggests a language-only catch-all; x-default covers everyone whose language you do not serve at all.
Three formats
Link tags, sitemap entries and the HTTP header are equivalent; pick one per page. The sitemap is easiest for large sites, the header for PDFs, the tags for everything else.
The generator checks the codes and URLs you give it. It cannot see whether each listed page actually carries the same set; that return-link check needs a crawl of the live pages.
Three steps
Works the same for two versions or two hundred.
-
1
List every version
One line per language or region version of the page, including the one you are editing. Paste two columns from a spreadsheet if you keep a URL map.
-
2
Fix what is flagged
Read the checklist from the top. Errors mean a line is left out; notes are suggestions, such as adding a language-only fallback or an x-default.
-
3
Copy one format
Put the link tags in the head of every listed page, or add the sitemap block, or send the header. The same set goes on every version.
What a valid hreflang value looks like
From Google’s documentation on localized versions. Values are case-insensitive; the conventional form is lowercase language, title-case script and uppercase region.
- Language: ISO 639-1, two letters. Region: ISO 3166-1 alpha-2. Script: ISO 15924, four letters
- A region alone is invalid; a language alone is fine
- Every URL must be absolute, and every version must list itself and all the others
| Value | Valid? | Why |
|---|---|---|
de | Yes | German, any region |
en-GB | Yes | English for the United Kingdom |
zh-Hant, zh-Hans-US | Yes | Traditional Chinese; Simplified Chinese for the US |
x-default | Yes | Fallback for unmatched languages |
en-UK | No | UK is reserved; the code is GB |
jp, cn | No | Country codes; Japanese is ja, Chinese is zh |
zh_CN | No | Underscore; use zh-CN |
es-419 | No | Numeric regions are not supported |
GB | No | Region without a language |
The “common mistakes” list, fixed
What the checker reports for the list behind the “Show common mistakes” button, line by line.
| Line | Wrote | Problem | Fix |
|---|---|---|---|
| 1 | en-UK | Reserved region code | en-GB |
| 2 | jp | Country code instead of language | ja |
| 3 | zh_CN | Underscore | zh-CN |
| 4 | es-419 | Numeric region (Latin America) | es, or es-MX, es-AR… per country |
| 5 | de /de/ | Relative URL | https://www.example.com/de/ |
| 6–7 | en-us twice | Same code, two URLs | Keep one URL for en-US |
Of seven lines, only one would survive as written, and a set with one version does nothing. After the fixes there are six versions; add an x-default and put the identical set on all six pages.
Why Google ignores hreflang
Invalid codes are easy to catch. These problems pass a syntax check and still break the setup.
No return links
The English page lists the German one, but the German page lists nothing back. Google needs both directions, or it ignores the pair.
Forgetting the page itself
Each version must include its own URL in the set. Templates that list only “the other languages” break this on every page.
Pointing to redirected or noindex URLs
hreflang URLs should be the final, canonical, indexable pages. A URL that redirects or carries noindex weakens the whole cluster.
Treating it as a redirect
hreflang only changes which URL appears in results. It does not move visitors, and automatic language redirects can stop Google crawling other versions.
Check each version gets the right audience
After hreflang goes live, the question is whether each version gets search traffic from the countries it was built for.
Search data by country
Google Search Console and Bing Webmaster in one view, broken down by query, page, country and device.
Learn moreLanding pages per version
Entry pages and exit rates for /uk/, /de/ or /zh/ side by side, so a version that never receives visitors stands out.
Learn moreAudience by country
Visitors by country, device and browser, counted without cookies and without bots.
Learn moreHreflang questions
Still have a question?
Chat with the team behind TapCub — we usually reply within a few hours on business days.
What is hreflang?
An annotation that tells search engines a page has versions for other languages or regions, and which is which. Google uses it to show the matching version in results, for example the UK page to searchers in Britain. It is a hint, not a redirect.
Should I use HTML tags, the sitemap or HTTP headers?
Any one of them; Google treats them as equivalent and using more than one adds nothing. Tags are simplest for small sites, the sitemap for large ones because templates stay untouched, and the header for PDFs and other non-HTML files.
What is x-default?
The URL for users whose language or region matches none of your versions. It is often a language selector or your main international version. It is optional, but without it those users get whatever Google picks.
Is it en-UK or en-GB?
en-GB. The ISO 3166-1 code for the United Kingdom is GB; UK is a reserved code, and Google’s documentation says hreflang values with UK, EU or UN have no effect.
Should I use zh-CN or zh-Hans?
Both are valid. zh-Hans and zh-Hant describe the script (Simplified or Traditional) for any region; zh-CN, zh-TW and zh-HK describe the region. If you have one Simplified version for everyone, zh-Hans or plain zh is the more accurate choice.
Does every page need to list itself?
Yes. Google’s documentation says each language version must list itself as well as all other versions. The identical set goes on every page.
Can hreflang point to another domain?
Yes. Versions can live on different domains, such as example.de and example.co.uk, as long as every page links back. Make sure each domain is verified if you use Search Console to monitor it.
Is my list sent anywhere?
No. Codes are checked and the output is built in your browser. If you copy the share link, the list is stored after the # in the URL, which browsers do not send to servers.
Update history
New features, fixes and data refreshes for this tool, newest first.
-
· v1.0
LaunchedFirst release.
Missing something or found an error? Tell us — requests that come up often go into the next update. All tool updates
Watch traffic arrive on each language version
Connect your site and Search Console and see clicks and visits per country next to each version’s pages.