Skip to the tool
OnPageKit

Hreflang Tag Generator

Build a reciprocal hreflang set for every language version.

one code and URL per line

Language, then region: en-GB, not en-UK. A line starting with # is ignored.

x-default

Where a visitor lands when no version matches their language. Usually a language selector, or your main market.

0 versions in the set

Everything runs in your browser. Nothing you type is sent to a server.

Found a bug in this tool? Report it.

Share this tool

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

  1. Paste one line per version, code first: en-GB, https://example.com/uk/.
  2. Put the fallback URL in the second field. It becomes the x-default entry.
  3. Copy the block and paste it into the <head> of each page listed — the same block, unchanged.
  4. 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 meantWriteWhy
English, United Kingdomen-GBen-UK is not an ISO region
English, everywhereenRegion is optional, and often better
Latin American Spanishes-419UN M49 region code, valid and widely used
Portuguese, Brazilpt-BRHyphen, never pt_BR
Simplified Chinesezh-HansScript 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.

Frequently asked questions

Does hreflang tell Google which page to rank?

No. It tells Google which page to show once it has already decided your site is the answer. Ranking is worked out for the group as a whole, then hreflang swaps in the version that matches the searcher's language and country. That is why an hreflang set never lifts a page that was not going to rank anyway.

What happens if one page in the set is missing the tags?

Google drops the pair. Annotations must confirm each other: if the UK page names the French page but the French page does not name the UK page back, the link is treated as unverified and ignored. In a set of six, one page that forgot the block quietly costs you five relationships.

Do I need hreflang for the same language in two countries?

That is the case it was built for. An en-GB page and an en-US page are near-identical text on two URLs, which is exactly the duplicate-looking pair a search engine has to pick between. Annotating them tells it to show each one in its own market instead of choosing one and burying the other.

Can I use hreflang and canonical on the same page?

Yes, and you must — they answer different questions. Every page in the set carries a self-referencing canonical pointing at itself. A canonical that points at another language version cancels the whole set, because you have just said that page should not be indexed separately.

Where should hreflang go, in the head or the sitemap?

Either, never both. The head is easier to inspect and to debug, and it is what most CMS templates can produce. The sitemap keeps the markup out of pages you do not control and costs nothing in page weight, which matters on a large catalogue where the block would repeat on every URL.

Related tools

Updated