Hreflang errors: what they mean and how to fix them

Most hreflang errors come down to one thing: the language versions of a page don't agree with each other, so search engines can't trust what they say. Fix those first, starting with missing return links and pages that don't list themselves. They usually come from one template or plugin setting, so you fix them once rather than page by page. Here's what each error means, in the order I'd tackle them.

Before you start: run the check on two pages

Hreflang is a set of links that tells search engines which language version of a page to show each person. Problems are often in the relationship between two pages, so check a page and one of its translations, not only your homepage.

The free hreflang checker reads a page's tags in the HTML head and the HTTP Link header, then opens up to 20 of its language versions to see whether they answer and link back. One limit to know: it doesn't read your XML sitemap. If your hreflang lives only in the sitemap, the report will say it found none. That doesn't mean your setup is wrong. Check those entries against the rules below.

The errors to fix first

These can make search engines ignore your hreflang for a page, or for a pair of pages.

A language version doesn't link back ("missing return link"). If your English page lists the German page as its German version, the German page has to list the English page too. When the link only goes one way, search engines may ignore the pair. It usually happens when one language was added later, or when only your main language has the tags. Fix: every version carries the same full list.

The page doesn't list itself. Each page lists all its versions, its own included. Fix: add the page's own URL to its list. If the report says it lists itself "only with a different trailing slash", use the exact address the page answers at. To a search engine, /de and /de/ are two URLs.

A language version doesn't answer 200. A link to a page that returns 404 or a server error is a dead end. This often happens with a page that exists in only some languages, when a template lists every language regardless. Fix: list only the languages the page really has, or publish the missing version.

The canonical URL points to another page. Search engines ignore hreflang on a page that isn't canonical. The classic case is every translation having a canonical that points at the main-language page, which tells search engines the translations aren't the real pages. Fix: each language version's canonical points to itself.

A language code is wrong. The two you'll see most:

  • en-UK isn't valid, because the country code for the United Kingdom is GB. Use en-GB.
  • en_US isn't valid, because hreflang uses a hyphen. Use en-US.

Language codes come from ISO 639-1, with an optional ISO 3166-1 country after them, like de or de-AT. A country on its own isn't a language.

A URL is relative or empty. Hreflang URLs must be absolute, with https:// and the domain. /de/pricing isn't enough.

The tags are in the body. Search engines only read hreflang links in the <head>. A common cause is a stray tag or script that closes the head early, or a theme that prints the tags too late.

One language points to two different URLs. Each language gets one address per set. Look for two systems writing tags at once, such as a theme and a plugin.

Warnings worth fixing when you get to them

These won't always cost you anything, but they're cheap to clear:

  • No x-default. It names the page for visitors whose language you don't offer, often your main language or a language chooser. It's optional and recommended.
  • <html lang> doesn't match. A page tagged as German with <html lang="en"> sends a mixed signal, and it's usually a template default nobody changed.
  • A language version redirects. Link to the final address, not one that forwards to it. http:// links and missing www are the usual reasons.
  • A language version lists a different set of languages. One page lists five languages and its translation lists four. Often a sign that a language was added to some pages and not others.
  • The same URL is listed for several languages. Several countries sharing a page is possible (de-DE, de-AT), but a list where every language points to one address usually means the translations aren't separate pages at all.
  • The HTML and the HTTP header disagree. Pick one method and use it consistently.

What a correct set looks like

For a page in English and German, both pages carry the same block in their <head>:

<link rel="alternate" hreflang="en" href="https://example.com/pricing" />
<link rel="alternate" hreflang="de" href="https://example.com/de/preise" />
<link rel="alternate" hreflang="x-default" href="https://example.com/pricing" />

The English page's canonical is https://example.com/pricing. The German page's canonical is https://example.com/de/preise. That's it: same list on both, full addresses, valid codes, and each page canonical to itself. The generator on the checker page writes this block and the matching sitemap entries from your list of languages and URLs.

Fix the source, not the page

On a site of any size, nobody should be editing hreflang by hand. When a check fails, find what writes the tags:

  1. A theme or template. One fix covers every page, which is the good news.
  2. A plugin. Look for a setting first, and check that a second plugin or your theme isn't writing tags too.
  3. A sitemap generator. Regenerate it after any change to your languages.
  4. A hand-built site. Consider generating the list from one table of pages and languages, so a new language can't reach only half the site.

Then re-run the check on the same two pages, plus one page you added recently. New pages are where this tends to break again.

Don't expect the search results to change the same day. Search engines have to recrawl the pages first, and hreflang is a signal rather than a command, so correct tags don't guarantee which version shows for every search. If the wrong language still ranks well after that, look at whether the right page has real, complete content and whether your other pages link to it. Our guide to adding a second language covers that wider setup.

If you'd rather not think about this again

I built this into FolioPress because hreflang is a lot of rules for something that should be invisible. Every page gets its tags automatically, on the page and in the sitemap, with return links, x-default, self-referencing canonicals and a translated address per language. A page lists only the languages it has a version in, so a missing translation doesn't turn into a dead link.

It only helps if you build your site in FolioPress, though. It doesn't fix hreflang on a site you run somewhere else. If your current site is otherwise fine, fixing its template is the cheaper move. If it's the second or third thing a language plugin has broken this year, plans start at €12 a month, with a 30-day free trial (pricing).