hreflang done right: the four errors that happen silently

hreflang: de, en, x-default
Key Takeaways:

Incorrect hreflang annotations can stop working without any visible error message. Google no longer reports such errors centrally in Search Console. Since 22 September 2022 the International Targeting report has no longer been available there.

  • The syntax is the easiest part of the whole topic. In my view almost every guide covers nothing else.
  • Common breaking points include: missing return links, a conflicting canonical, invalid language codes and placement inside the document.
  • The return link rule is worded softly. If the return link is missing, the attributes „may be ignored or not interpreted correctly”, according to the Google documentation.
  • Checking is now entirely your job. This article shows you a four step check path that you can run in about ten minutes.

Since 22 September 2022 the International Targeting report has been switched off. For a long time that was the central place for hreflang hints in Search Console. Since then that feedback no longer exists. The annotation itself keeps working, the error message about it does not.

This changes the task fundamentally. In the past you could implement and then wait for an error to show up. Today nothing shows up. Neither when it works nor when it does not.

That is exactly what makes hreflang a special kind of technical SEO. A broken canonical eventually becomes visible in your rankings and a broken robots.txt shows up sooner or later in your indexing, but a broken hreflang annotation has no warning signal of its own. The pages keep ranking, which means users may end up seeing the wrong language version.

I run seo-kreativ.de bilingually and every post exists in both German and English. For this article I checked my own annotation with curl instead of assuming it was fine. The result: three out of four check points clean and one missing completely. The commands to reproduce it are further down.

This text keeps the part short that you find in every other guide. The syntax sits in one single section and the entire rest of the article deals with a single question: does it actually do anything?

What hreflang actually controls, and what it does not

Key Takeaway: hreflang does not decide whether you rank, but which of your language versions gets served. Google’s documentation treats it consistently as a selection mechanism. It does not classify it as a ranking signal.

The misconception I keep seeing most often is expecting hreflang to win rankings. The annotation does not do that. It answers a narrower question: when several of your pages carry the same content in different languages, which one does Google show to a particular user?

Google describes the purpose in the official documentation as informing Google about content variants. Informing. Not instructing. That word choice runs through the entire specification and it has real consequences for the outcome you may expect.

John Mueller made this clear in May 2025 using a concrete case. An SEO had observed Belgian French pages appearing in French search results and the annotation intended something entirely different. Search Engine Journal documented Mueller’s answer from a Bluesky post dated 12 May 2025: „hreflang doesn’t guarantee indexing, so it can also just be that not all variations are indexed.” What is not in the index cannot be served either. I have written up separately how crawling and indexing fit together at Google.

For same language variants Mueller gets even more explicit: „if they are the same (eg fr-fr, fr-be), it’s common that one is chosen as canonical”. Two pages with identical French text are simply two copies to Google’s systems and the hreflang annotation changes nothing about that. That is not a bug. That is consolidation.

Note: If you want to know at which point in the pipeline this selection even happens, the overview of how Google works from crawling to ranking helps. hreflang comes into play late, namely when the URL to be served is chosen.

In practice this means hreflang does not repair weak content. It makes sure the existing content reaches the right audience. Anyone with a page sitting at position 30 in German will not gain a single position in the German results through an English version, no matter how clean the annotation is.

The syntax: structure, language codes and three delivery methods

Key Takeaway: Language code per ISO 639-1, optional region code per ISO 3166-1 Alpha 2. Three delivery methods are available: HTML head, HTTP header or XML sitemap. Pick one and stick with it.

The element is a link tag with rel="alternate". For a German and an English version it looks like this:

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

The code structure is defined precisely in Google’s documentation: the first code of the hreflang attribute is the language code in ISO 639-1 format, followed by an optional second code as a region code in ISO 3166-1 Alpha 2 format. The region code is optional. The language code is not.

The order gets swapped regularly. Correct is de-AT with the language first and the region second. AT-de is invalid. What happens then? The documentation is unambiguous: „If you use codes that are listed as reserved for something else, Google Search ignores that part of the annotation”. Google silently ignores the affected part of the annotation.

A second classic concerns countries that are not a language. There is no hreflang="uk" for the United Kingdom, because uk is the ISO 639-1 language code for Ukrainian. What is meant in these cases is en-GB.

For delivery Google names three options: HTML, HTTP header and sitemap. Which one fits depends less on SEO than on your stack.

MethodWhen it makes senseDownside
HTML head
<link rel="alternate">
Standard case for CMS driven sites. Readable by every tool, visible in the source immediately. Bloats the head with many languages. With 20 versions you get 20 lines on every page.
HTTP header
Link:
The only option for non HTML files such as PDFs. Invisible in the source. Only checkable through the response headers.
XML sitemap
xhtml:link
Large sites with many languages. Changes happen centrally without touching templates. Needs an xmlns:xhtml namespace. Many standard sitemaps do not ship it.
Warning: Do not mix the three methods. If the HTML head and the sitemap make different statements, you have two contradicting claims about the same URLs in circulation. That is considerably harder to debug than a missing annotation, because both sides look correct on their own.

Four breaking points where hreflang fails silently

Key Takeaway: Missing return links, a contradicting canonical, invalid codes and placement outside the head. These four are the ones I keep seeing most, and none of them produces a visible error message.

For its hreflang guide Ahrefs evaluated 374,756 domains and arrives at this result: „67% of the hreflang implementations had issues”. Ahrefs does not state a collection period and the figure comes from the tool vendor itself, which is why I use it here purely as an order of magnitude and not as a reliable error rate for the web. Two out of three implementations carry at least one problem.

1. The missing return link

In my view this is the rule most implementations fail at, and it is at the same time the only rule in Google’s documentation that requires reciprocity. Google words it as follows: every language version must list the version itself and all other language versions.

Two things are contained in that. First, every page must list itself and not just its siblings. Second, the connection must exist in both directions. What happens with a one sided reference is listed by Google under the common errors: if page X links to page Y, page Y must link back to page X, and if that is not the case for all pages carrying an hreflang attribute, the attributes may be ignored or not interpreted correctly.

Two qualifiers hang on that sentence and both get skipped easily. First the word „may”: Google is not promising here that one sided annotations are always ignored, only that you cannot rely on it. In practice that is the worse case. Sporadic errors are considerably harder to find than permanent ones.

Second, Google names two possible outcomes and not one. The attributes can be ignored, but they can also be „not interpreted correctly”. That is the more unpleasant result, because an ignored annotation simply does nothing while a misinterpreted one does something you did not intend.

The typical cause is mundane. A language version gets added later and the existing pages are not updated in the process, so the new page links to all the old ones and none of the old ones knows about the new one.

2. The canonical working against it

hreflang and canonical must tell the same story. Every language version needs a canonical pointing at itself. If the English page canonicalises to the German one, you are telling Google two contradicting things: „these are equivalent language variants” and „this is merely a copy of the German page”.

Google does not resolve this contradiction in your favour. As a rule the canonical wins and the English page disappears from the index. At that point the hreflang group is incomplete anyway.

One special case explains why this error often goes unnoticed: with very similar language variants Google consolidates even when your canonical is set correctly from the first to the last page. Mueller explicitly frames this as a suspicion: „I suspect this is a ‘same language’ case where our systems just try to simplify things for sites.”

3. Invalid or invented codes

Besides the already mentioned mix up of language and region code there is a second category: codes that are not available as a region code. en-EU is extremely popular in projects with a Europe wide focus and still unusable. Google names this exact case in the documentation: „for example, using EU, UN, or UK in hreflang annotations doesn’t have an effect”. The reason sits in the sentence before it: „Only language codes listed in ISO 639-1 and region codes listed in ISO 3166-1 Alpha 2 are supported; other codes aren’t supported.” EU and UK are not among the regular country codes there but are reserved for other purposes.

The effect is the same in both cases. The affected line drops out and the rest of the group remains in place, so what you end up with is a partially working annotation. From the outside that looks exactly like a fully working one.

4. The annotation does not end up where it belongs

Google’s documentation requires the HTML variant in the head section. Placement in the body is therefore not compliant with the specification, regardless of how Google handles it in any individual case.

It gets interesting because you cannot see this in the source code. I examined this for canonical and robots tags in a separate post: a single misplaced script can cause the parser to close the head earlier than you think, and everything after that slips into the body. For canonical and robots it is established that Google does not process directives in the body. For hreflang I know of no comparably hard statement and would therefore rely on nothing at all, but simply look at where the tags actually sit in the rendered DOM.

The same caution applies when the tags are loaded via JavaScript. And one trivial but real case: if the target language version is blocked through robots.txt, Google cannot see the return link. The group stays incomplete even though everything in the markup is correct.

x-default: the safety net almost everyone skips

Key Takeaway: x-default catches all users for whom none of your language versions fits. It is optional and in my view still the most frequently forgotten element. On my own domain it is missing as well, there as a decision; the reasoning is in the practice check.

Google defines the value briefly: the reserved value x-default is used when no other language or region matches the user’s browser setting.

That sounds like an edge case and is not one. Take a site with a German and an English version. What happens with a user whose browser is set to Spanish? Without x-default you leave the decision about which of the two versions gets served to Google. With x-default you make it yourself.

The value is not a replacement for a language annotation. It sits in addition and usually points to the English version or to a language selection page. An automatic redirect is explicitly not what is meant and Google advises against it, recommending that you avoid automatically redirecting users from one language version of a site to another.

My rule of thumb (my own recommendation, not a Google requirement): With two or three languages, x-default points to the version with the widest reach, usually English. From roughly five languages onwards a dedicated selection page without automation is worth it in my view. And if you are considering IP based routing: Google warns against it because IP location analysis is complex and mostly unreliable. For context, the documentation on locale-adaptive pages states two things side by side: „the default IP addresses of the Googlebot crawler appear to be based in the USA”, and at the same time „Googlebot crawls with IP addresses based outside the USA, in addition to the US-based IP addresses”.

Verifying since the International Targeting report disappeared

Key Takeaway: Google discontinued the report but continues to support hreflang. Since then verification is entirely up to you. Four steps are enough and three of them cost nothing.

Google’s help page is very short on this point: „The International Targeting report has been deprecated.” And immediately afterwards the reassurance: „Google will continue to support and use hreflang tags on your pages.” So the annotation stays relevant. Only the monitoring instance is gone.

It was announced on 24 August 2022 via the Google Search Central account, and the notification inside Search Console named 22 September 2022 as the last day. The country targeting feature sat in the same report and is no longer supported either. Google justifies this by saying it was „determined to have little value for the ecosystem, and is no longer supported”.

That leaves this check path. I run through it completely once with every relaunch.

Step 1: Look at the served head

Not in the browser, but in the raw server response. One command is enough:

curl -s https://example.com/page/ | grep -i 'rel="alternate"' | grep -i hreflang

This shows you what is actually served, without browser interpretation. The second filter is not cosmetic. A plain grep -i hreflang searches the whole document and therefore also finds the hreflang attribute on a link in the body copy. My own language switcher does exactly that: unfiltered, my two test pages return 21 and 22 matches, filtered, two remain on each, and only those two are the annotation (own measurement, 3 August 2026). An attribute on an <a> in the body belongs to none of the three methods Google’s documentation lists.

For the HTTP header method you need a variant of it:

curl -sI https://example.com/page/ | grep -i '^link:'

Step 2: Check the return direction

In my view this is the step almost everyone skips. Take the URL you just linked to and check whether it links back. With two languages that is two commands. With five languages it is five and at that point a small script starts paying off.

The criterion is simple. Every page in the group must serve the same complete list and include itself in it. If the lists differ, you have found your error.

Step 3: Verify against the rendered DOM

Open the URL Inspection tool in Search Console and display the rendered HTML. Here you see what survives processing by the renderer and whether the tags still sit where they belong afterwards. This is one of the few steps where Search Console still helps here, and it explicitly does not replace the old report. It shows you the state of your page, not Google’s assessment of it.

Step 4: Cross-read your search data

An indirect but usable signal: if the wrong language version is served for a country, you will sooner or later see it in the Search Console performance report. Filter by country there and look at which of your pages collect impressions in that market at all. If the German URL appears systematically in British search results although an English version exists, that is a hint. How to build such filters efficiently is covered in my collection of RegEx templates for Search Console.

Checklist: Head read out, return direction checked, rendered DOM verified, country filter in the performance report reviewed. Four steps, roughly ten minutes for one language pair. External validators take steps 1 and 2 off your hands, but they do not replace step 3.

Practice check: what my own setup actually serves

Key Takeaway: Three out of four check points on seo-kreativ.de are clean. x-default is missing, and that is a deliberate decision with a reason. The finding comes from my own curl check on 3 August 2026 and applies to the three URLs checked.

Instead of constructing an example I check my own site. seo-kreativ.de runs on WordPress with Polylang for language delivery and Yoast for the sitemaps. German sits under /blog/, English under /en/blog/.

I checked three URL pairs with the commands from steps 1 and 2. This is what came out:

Check pointFindingAssessment
Return links both waysDE and EN both list hreflang="de" and hreflang="en"clean
Self referenceEvery page lists itself as wellclean
CanonicalEvery page canonicalises to itself, no cross referenceclean
x-defaultno occurrence in the served HTMLmissing (deliberately, reasoning below)
Delivery methodHTML head exclusively. No Link: header, no xhtml:link entries in the Yoast sitemapconsistent

The last point interested me most. The post-sitemap.xml generated by Yoast declares a namespace for images and none for xhtml, so it cannot carry hreflang annotations at all. Anyone assuming that a sitemap ships this automatically is wrong here. A glance at the root node of the file is enough.

The missing x-default is the one point where my annotation is not complete. I am leaving it open deliberately, and the reasoning belongs here, because it shows which part the annotation handles and which part it does not.

German speaking users land on the German version. That is not Google being clever, it is hreflang="de" doing exactly its job. The matching runs on the language setting, not on the country the user sits in: „Google Search returns the appropriate result for the user, according to their browser settings.” A German speaker in Spain therefore gets the German version, an English speaker in Austria the English one. x-default would not come into play in either case, because the value „is used when no other language/region matches the user’s browser setting”.

That leaves exactly one group: users whose language setting is neither German nor English. Without x-default Google decides which of my two versions they see, and how it decides is not in the documentation. I consider that risk acceptable, because with a German-English pair English is the version I would pick for that case anyway. This is a judgement call for my site and not a recommendation: Google explicitly recommends the value, namely „for specifying the fallback page for users whose language settings don’t match any of your site’s localized versions”. Anyone who does not want to leave that decision to Google should set it.

Warning: The findings above are a snapshot of three URLs, collected via curl on 3 August 2026. They describe what my server serves. They say nothing about how Google processes or assesses this annotation. That distinction is the core of the topic: what you can verify is your own output, not Google’s handling of it.

Frequently asked questions (FAQ)

Do I need hreflang if my pages are served in the same language for different countries?

Yes, that is in fact the main use case for the region code. You distinguish an Austrian and a German version of the same language through de-AT and de-DE. Expect Google to consolidate with very similar content though. John Mueller describes it for the fr-fr and fr-be case as follows: „it’s common that one is chosen as canonical”. The more the versions differ in substance, the more likely both survive.

Is x-default mandatory?

No. Google describes x-default as a reserved value for the case where no other language matches the browser setting. The documentation derives no obligation from that. Without x-default Google decides which version users outside your annotated languages see. With x-default you decide it.

How do I check hreflang now that the International Targeting report is gone?

Through the served head instead of through Search Console. curl -s URL | grep -i hreflang shows you the actual output, and the same command on the linked counterpart exposes missing return links. In addition you check the rendered HTML in the URL Inspection tool to see whether the tags still sit in the head. A report that returns Google’s assessment of your annotation has not existed since 22 September 2022.

Does hreflang improve my rankings?

Google’s documentation treats hreflang consistently as a mechanism for selecting the matching language version and never classifies it as a ranking signal. The benefit lies in users receiving the version that suits them. That can indirectly affect metrics such as click through rate, but it is something different from a direct ranking effect.

What happens with an invalid language code?

The affected line drops out without any message appearing. Google words it like this: if you use codes that are reserved for something else, that part of the annotation is ignored by Google Search. The rest of the group remains in place. Common errors are en-UK instead of en-GB as well as en-EU. Google lists both codes in the documentation as an explicit example whose use „doesn’t have an effect”.

Should I serve hreflang in the head, the HTTP header or the sitemap?

Google names three permitted delivery methods and gives none of them preference. For classic CMS pages the HTML head is the standard, for PDFs only the HTTP header remains anyway, and with very many language versions the sitemap keeps your templates lean. What matters is that you decide on exactly one method and stick with it. Contradicting statements from two sources are considerably harder to track down than a simply missing statement, because each of the two sources looks perfectly correct on its own.

Conclusion: The syntax is the easy part

Key Takeaway: Implementing hreflang takes an hour. Checking whether it works takes ten minutes and gets skipped anyway. Since the International Targeting report disappeared the instance that used to remind you of that step is gone.

In my view the pattern is the same with almost every ineffective implementation. The syntax is right and the codes are right and still nothing at all happens, because somewhere a single page in the group does not link back or a forgotten canonical works against it. You only see either error if you go looking for it deliberately.

That is why reversing the usual order pays off. Implement the annotation and schedule the check straight away as a fixed second appointment. Not as an optional extra. In my case that exact check showed that x-default is missing. Whether it stays that way is a decision you make afterwards. Before the check it was a blind spot.

And if you take away only one single command from this article, make it the one on the return direction. In my view almost everyone checks the outbound direction. Almost nobody checks the way back.

Tip: Set yourself a recurring reminder after every larger release. Language versions rarely break during implementation, but during the next deployment, when a new page arrives and nothing updates the existing ones.

As of: August 2026. All information without guarantee, despite careful research no warranty is given as to topicality or completeness. This post is not individual legal or consulting advice. The cited evaluation results are based on the figures published by Ahrefs, for whose accuracy no warranty is assumed. The findings on seo-kreativ.de are own measurements via curl from 3 August 2026 and refer to the URLs named there. The technical statements reflect the processing path as documented at the stated date and are subject to change; recommendations given without a source are my own experience and not a Google requirement. All brands and product names mentioned are the property of their respective owners.

Sources: Google Search Central: Localized versions of your pages · Google Search Central: Managing multi-regional and multilingual sites · Google Search Central: Crawling locale-adaptive pages ·Search Console Help: The International Targeting report is deprecated · Search Engine Roundtable: Google Search Console Deprecates International Targeting Report · Search Engine Journal: Google Reminds That Hreflang Tags Are Hints, Not Directives

Christian Ott - Gründer von www.seo-kreativ.de

Christian Ott – Creative SEO Thinking & Knowledge Sharing

As the founder of SEO-Kreativ, I live out my passion for SEO, which I discovered in 2014. My journey from hobby blogger to SEO expert and product developer has shaped my approach: I share knowledge in a clear, practical way-without jargon.