FreeToGenerate.com

Paste the alternates you have, or type them in, and see what each code actually says before a search engine reads it. Nothing is uploaded.

Paste the link tags you already have, or type one line per version as a code and a URL. Both directions work.

Give a URL and the checker confirms the set includes the page itself, which Google requires.

Try one

What these codes actually say

1 errors · 0 warnings · 0 notes

CodeReads asURL
enEnglishhttps://example.com/
brBretonalso the country code for Brazilhttps://example.com/br/
seNorthern Samialso the country code for Swedenhttps://example.com/se/
jpnot a language codeError jp is the country code for Japan, and it is not a language code, so this will be thrown away. If you meant the country, it belongs after a language: en-JP or fr-JP.https://example.com/jp/

Put this on every page in the set

The same block goes on all of them, unchanged. Because it lists every URL including its own, each page ends up referring to itself and to all the others, which is exactly what the return-link rule asks for.

<link rel="alternate" hreflang="en" href="https://example.com/" />
<link rel="alternate" hreflang="br" href="https://example.com/br/" />
<link rel="alternate" hreflang="se" href="https://example.com/se/" />
<link rel="alternate" hreflang="jp" href="https://example.com/jp/" />

Also available in: Español · Português · Français · العربية

hreflang generator and checker

Generate the link tags for a set of translated pages, and check the set you already have against the rules search engines actually apply.

What an hreflang tag is

When one page exists in several languages, each version needs a way to say so. An hreflang tag is that statement: a link element naming a language and the URL of the version written in it. Put the full set on every version and a search engine can show a Spanish reader the Spanish page instead of guessing from the text.

The value is a language code, optionally followed by a region. Google states the format plainly: the first code is the language in ISO 639-1 form, followed by an optional second code for the region in ISO 3166-1 Alpha 2 form. So en is English everywhere, en-GB is English for readers in the United Kingdom, and pt-BR is Portuguese for readers in Brazil. There is also one reserved value, x-default, for the version to show when nothing else matches.

The rule people miss is the next sentence in the same documentation: you cannot specify the country code by itself. The first position is a language, always. That reads like a formality, and it is the most expensive mistake in international SEO, for a reason worth measuring.

How to use it

  1. Paste what you have, or type it in. Existing link tags work as they are, in any attribute order. So does a plain list of one line per version, a code and a URL, in either order.
  2. Read the middle column. It says what each code means rather than whether it parsed. That is where a code meant as a country shows up as somebody else's language.
  3. Copy the generated block onto every page in the set. The same block, unchanged, on all of them. It lists every URL including its own, which is what the self-reference and return-link rules ask for.

The mistake that never reaches your reports

Writing a country code where a language belongs is the classic hreflang error, and most write-ups treat it as one mistake. It is two, and only one of them is ever reported to you.

Take the 249 country codes in ISO 3166-1 and ask which are also valid ISO 639-1 language codes. For 140 of them the answer is no: hreflang set to jp or cn or us is not a language, so it is thrown away and a search console will tell you the tag is invalid. That is the loud half, and it gets fixed.

The other 109 are also language codes. They parse. Nothing rejects them, nothing reports them, and for 75 of those the language named has nothing to do with the country the author had in mind. A page marked br is not Brazilian, it is Breton, a language of western France. A page marked ca is not Canadian, it is Catalan. Marked se it is not Swedish but Northern Sami; marked sv it really is Swedish, which is unfortunate if you meant El Salvador. Taiwan gets tw, which is Twi, spoken in Ghana. Cyprus gets cy, which is Welsh.

Every one of those is a valid annotation for a real audience, so the tags work perfectly. They simply describe a set of pages nobody was trying to reach, and there is no error state to notice. The half of this mistake you can find is the harmless half.

That is what the middle column of the table above is for. This tool does not accuse you of anything when it sees a bare code, because it cannot know what you meant: ar really is Arabic, and this site publishes in it. It just tells you which language you have written, next to the URL you have written it on, and leaves the noticing to the only party who knows the answer.

Honest limits, and how this was checked

This runs in your browser, so it cannot fetch the other pages in your set to confirm they carry matching tags. That is a cross-origin read and no client-side tool can honestly claim it. What it can do is remove the need: because the generated block lists every URL including the page's own, pasting it unchanged onto all of them satisfies both of the rules that trip people up. Google is unambiguous about the consequence of getting them wrong. Each language version must list itself as well as all other language versions, and if two pages do not both point to each other the tags will be ignored.

Two things are deliberately not treated as errors. Capitalisation is one: BCP 47 makes subtag case insignificant, so en-us works exactly as en-US does, and tools that flag it are inventing a rule. It is shown as a note about the usual spelling, nothing more. The other is a four-letter script subtag such as Hant, which is accepted by shape and not checked against a register, because Google's documented format is a language and an optional region.

The language and country tables are not typed in here. They are generated from the same two datasets behind this site's ISO 639 and ISO 3166 list pages, so what this validator accepts and what those pages print cannot drift apart. The 75 figure is a measurement over them: for each collision, CLDR is asked both whether the country speaks that language and whether that language belongs to that country, and a code is only counted when both say no. A single test overcounts by three, since Fijian really is spoken in Fiji, Marshallese in the Marshall Islands and Norwegian in Norway. The engine carries 761 assertions, including a sweep confirming that every one of the 109 collisions raises neither an error nor a warning.

Why is it free?

Nothing here needs a server. It is a lookup against two tables and a handful of rules, all of it running in the tab you already have open, so there is no cost to pass on and no account to create.

What you paste is not uploaded, stored or logged. Unreleased URLs go into a tool like this all the time, and that is worth stating rather than assuming.