hreflang and language checker

Check whether your page declares its language at all, and how many hreflang alternates it offers. The first thing to get right before any international rollout.

Measuring rankings in

Runs the full audit on your live site. Your report opens in your dashboard.

What this checks

This reads the lang attribute on the html element and counts the hreflang alternates the page declares. Those are two different jobs. lang states what language this page is written in, which is the baseline every page needs. hreflang declares that other language or country versions of the same page exist and where they are, which only applies once you actually have them.

Why it matters

A missing lang attribute is a small tag with a wide blast radius: screen readers use it to choose a voice, browsers use it to offer translation, and search engines use it as one input when deciding which audience a page suits. hreflang is what stops your German page competing against your English one for the same customer, and what stops a search engine serving the wrong currency and the wrong shipping promise to someone ready to buy.

How to read a bad result

No lang attribute is a warning and worth fixing in the template today, because it is one attribute and it applies to every page. No hreflang is reported as information, not a fault, because a single language site should not have any. If you do run multiple versions, the rule that breaks most implementations is reciprocity: every version must list every other version including itself, and one page that does not point back invalidates the set.

Reciprocity is the rule that breaks most hreflang implementations and it cannot be checked from a single URL. The audit reads the alternates, follows them, and reports whether the set agrees with itself, which is the difference between an implementation that works and one that is being discarded whole.

A failing result, and what it costs

A two-language set where one side was added later, by a different template. This is the failure that silently disables an entire implementation.

The English page names both versions. The German page names only itself. That breaks reciprocity, and a set whose members do not agree with each other is discarded rather than partially honoured — so the correct half is thrown away with the incorrect half and the site behaves as though hreflang was never added. The usual cause is exactly this: one language rendered by a template that was updated and one by a template that was not.

<!-- on /en/ -->
<link rel="alternate" hreflang="en" href="https://example.com/en/">
<link rel="alternate" hreflang="de" href="https://example.com/de/">

<!-- on /de/ -->
<link rel="alternate" hreflang="de" href="https://example.com/de/">

How to fix it

  1. Make every version list every version, including itself.An n-language set means n links on each of n pages. Anything less is not a partial implementation, it is an ignored one.
  2. Generate the set from one list.Hand-maintained alternates drift the first time somebody adds a locale. One source of truth, rendered by every template.
  3. Use codes that exist.Language in ISO 639-1, region in ISO 3166-1 alpha-2, and region alone is never valid: en-GB, not gb.
  4. Add an x-default.The version to serve when nothing matches, usually the selector or international English. Optional, and it is the difference between a sensible fallback and an arbitrary one.
  5. Point alternates at canonical URLs.An alternate pointing at a URL that canonicalises elsewhere gives a search engine two contradictory instructions about the same page.

Questions people ask

Do I need hreflang for a single language site?

No. Declaring lang on the html element is enough. Adding hreflang to a site with nothing to alternate between creates work and a source of errors with no upside.

What is x-default for?

The version to serve when no declared language or region matches the visitor. Usually a language selector or the international English page. It is optional but it is the difference between a sensible fallback and an arbitrary one.

Why is my hreflang being ignored?

Almost always because the return links are missing. Every alternate must point back to every other alternate. Search engines discard sets that do not agree, which means one broken template can silently disable the whole implementation.

Check another dimension

More free tools in crawling and indexing, and the rest of the set at all free tools.

Run the hreflang checker
on your own URL

Free account, no card. Paste your URL and get a real, scored report of your AI and search visibility.

Measuring rankings in