What this tool does
This hreflang generator takes your list of language versions and writes the complete annotation
block for every page in the set — not one tag, but the whole reciprocal group, in the two
formats Google reads: <link> tags for the <head> and <xhtml:link> elements for a sitemap.
It runs in your browser and never fetches your pages, so it cannot tell you whether the URLs you
typed exist. What it can do is refuse the mistakes that make an otherwise correct set worthless:
a code that is not a language code, a relative href, the same code declared twice, and the
missing x-default.
How to use it
- Paste one line per version, code first:
en-GB, https://example.com/uk/. - Put the fallback URL in the second field. It becomes the
x-defaultentry. - Copy the block and paste it into the
<head>of each page listed — the same block, unchanged. - Or switch the output to sitemap markup and publish it as a separate file.
The reciprocity rule, which is where sets die
Every page in the group must list every other page and itself. Google treats hreflang as a two-way confirmation: page A claims page B is its French version, and the claim is only believed if page B claims A back. A one-way annotation is discarded without a word.
This is why the output above repeats the identical block once per URL. It looks redundant on screen, and that redundancy is the whole point: the block is the same everywhere, including the self-referencing line. A set of four pages where one template forgot the tags is not a set of three that works — it is four pages of relationships Google could not verify.
The self-reference catches people out most often. https://example.com/uk/ must carry
hreflang="en-GB" pointing at itself. Without it the page is not a member of its own group.
en-GB is real, en-UK is not
The language part is ISO 639-1, the region is ISO 3166-1 Alpha 2, and in that standard the
United Kingdom is GB. UK is not a code at all; the tag is silently invalid and the whole
annotation for that URL is thrown away.
| You probably meant | Write | Why |
|---|---|---|
| English, United Kingdom | en-GB | en-UK is not an ISO region |
| English, everywhere | en | Region is optional, and often better |
| Latin American Spanish | es-419 | UN M49 region code, valid and widely used |
| Portuguese, Brazil | pt-BR | Hyphen, never pt_BR |
| Simplified Chinese | zh-Hans | Script beats country for Chinese |
Region without language is not allowed either: hreflang="gb" means Gaelic-something, not Britain.
If you serve one market per country, the language always comes first.
When x-default earns its place
x-default names the page for a visitor whose language and country match none of your versions.
Use it when you have a genuine fallback — a language selector, a global home page, or the market
that will do least badly for a stranger. Skip it when every visitor you care about already has a
version; an x-default pointing at a random language is worse than none.
It is a member of the set like any other, so it appears in every block, and it may reuse a URL that already has a language code. That duplication is expected.
hreflang does not replace canonical
They solve different problems and both are required. Canonical says this URL is the one to index. hreflang says this URL has equivalents elsewhere. Each page canonicalises to itself and annotates the others. Pointing the canonical of the French page at the English one deletes the French page from the index, and the annotations go with it.
The same discipline applies to redirects. If you are moving a market onto a new path, keep the hreflang set pointing at the final URLs and let the htaccess redirect generator handle the hop. An annotation aimed at a URL that 301s is a wasted relationship, and a chain of them is how a migration loses its international rankings for a quarter.
If you publish the sitemap version, remember it is still a sitemap: the same sitemap generator rules about absolute URLs and the 50,000 ceiling apply to the file you paste it into.