Bridge SEO

Hreflang: what it declares and what it does not do

6 min readUpdated Aug 2026
Hreflang tells a search engine that several pages are versions of the same thing intended for different audiences, and which audience each version is for. It is a declaration about relationships, not an instruction to send anybody anywhere, and most of the trouble people have with it comes from expecting the second.

What it actually declares

A set of alternates. Each page in the set names every page in the set, including itself, and states which language and optionally which region each one is meant for.

That is the whole model. It does not redirect anybody, does not detect where a visitor is, and does not choose a version on their behalf. What it does is remove a search engine's ambiguity: without it, several pages with similar content look like duplication, and one of them tends to be shown everywhere. With it, they are understood as a set, and the engine has a basis for showing the appropriate one to each searcher.

The consequence worth internalising early is that hreflang affects what appears in results, and nothing about what happens after somebody clicks.

The three places it can live

The same declaration can be expressed in three ways, and they are equivalent in meaning.

  • In the page itself

    As elements in the document head. The most common choice, and the most expensive at scale, because every page must list every alternate, and the total number of declarations across the site grows with the square of the set.

  • In an XML sitemap

    As annotations on each entry. This keeps the declarations out of the pages entirely, which suits large sets and sites where templates are awkward to change.

  • In an HTTP header

    The only option for files that are not documents, such as those distributed as downloads.

Choosing between them is an engineering decision rather than an SEO one. What matters is that exactly one method is used consistently, because maintaining two is how they come to disagree.

Reciprocity: the rule that makes it work

en de fr each version names the other two — and itself

Every page in the set must name every other page, and each must name itself. This is the single rule that most implementations break.

The reason it exists is that a declaration nobody can verify is worthless. If a page claims another is its alternate but that page makes no such claim, the relationship is asserted by one party alone, and an engine has no reason to believe it: anybody could point at anybody.

The practical consequence is that the set is only as good as its least maintained member. Adding a new language means editing every existing page in the set, not only the new one, and forgetting one of them breaks the relationship for the whole group rather than for that page alone.

Language and region codes

The codes lean on two standards, used together and often confused.

The language is expressed with a code from ISO 639-1. The region, optionally, with one from ISO 3166-1, and it qualifies the language rather than replacing it. A region on its own is not a valid declaration, because a region does not tell an engine what language the page is in.

The commonest error here is inventing a region where a language would do. A page in a language spoken across many countries usually wants the language alone; adding a region narrows the declaration to that country and leaves every other speaker outside the set, which is rarely what anybody intended.

The second commonest is treating the region as a marketing decision. It describes who the page is for in a way an engine can act on, and inventing combinations that do not correspond to real usage produces a set that matches nobody.

The default entry

One entry in the set can be marked as the fallback for anybody the other entries do not describe.

This exists because no set covers the world. A site with versions for three languages has nothing to offer a searcher in a fourth, and without a fallback the engine chooses for itself. Marking one version as the default makes that choice yours.

It is optional, and it is worth having whenever the set does not aim to be exhaustive, which is nearly always. The default entry has a page of its own: what it declares, and when it earns its place.

Where hreflang stops

Hreflang is regularly expected to do things it does not do.

  • It does not redirect

    Sending visitors to a regional version is a separate decision, made by your application, and combining automatic redirection with hreflang is a common way to make both worse. Redirects have their own failure modes, and a locale redirect layered on a declaration set hides both.

  • It does not fix thin or duplicated content

    Pages that differ only in a currency symbol are still nearly identical, and declaring them as alternates does not change what they are.

  • It does not apply across unrelated pages

    The set is versions of one page. A category listing in one language and an article in another are not alternates, however related they feel editorially.

Its relationship with canonical declarations has a page of its own, written from the hreflang side. The depth of canonical itself belongs to another site in the network.

What this section covers

The pages below take the parts most often broken separately: the errors that appear most often and how to find them, the default entry and whom it catches, and the one rule that keeps hreflang compatible with canonical declarations.

FAQ

What does hreflang do?

It declares that several pages are versions of the same thing for different audiences, so a search engine can show the appropriate one rather than treating them as duplicates. It affects what appears in results and does nothing at all after somebody clicks.

Does hreflang redirect visitors?

No. It is a declaration about relationships between pages, not an instruction to send anybody anywhere. Redirecting visitors to a regional version is a separate decision made by your application, and combining the two carelessly tends to make both harder to reason about.

Why does my hreflang not work?

Most often because the declaration is not reciprocal. Every page in the set must name every other page and also itself, and a set where one member has been forgotten breaks for the whole group rather than for that page alone.

Do I need a region code?

Only when the page is genuinely intended for one country. A language code alone covers everybody speaking that language, while adding a region narrows the declaration and leaves speakers elsewhere outside the set entirely, which is rarely what anybody intended when they added it.

Hreflang, claim by claim

A language set is a set of claims, and this section reads each one, faults included. The platform these pages describe is Bridge CDN, where an account is created.