If you went looking for the International Targeting report in Google Search Console to read your hreflang errors and could not find it, that is the first thing to fix: Google deprecated that report on September 22, 2022 and removed it from Search Console. It no longer exists, and Search Console no longer surfaces hreflang errors anywhere in the UI (they are not in the Enhancements or Page indexing reports either). Google still reads and uses hreflang annotations — it just stopped reporting on them.
Fastest fix: crawl your site with Screaming Frog SEO Spider (free up to 500 URLs), open the Hreflang tab, and read the filters. They flag the same problems the old report did — No return tags (missing reciprocal), invalid codes, and non-200 targets — but at the exact URL, not as an aggregate count. Then fix every flagged pair and re-crawl.
For the general hreflang concept overview, see Hreflang warning — quick guide.
Where do hreflang errors live now (as of June 2026)?
| You used to do this | Do this instead |
|---|---|
| Open Search Console → Legacy tools → International Targeting | Crawl with Screaming Frog, Sitebulb, Ahrefs Site Audit, or Semrush |
| Read aggregate “No return tags” count | Read the per-URL Hreflang tab / Site Audit issue list |
| Set a country target in Search Console | Country targeting is gone; Google infers region from hreflang, ccTLD, server location, and content |
| Wait for the report to refresh | Re-crawl instantly; for Google itself, re-fetch a page in the URL Inspection tool |
The URL Inspection tool still works for spot-checking a single page: it shows the live HTML Google fetched, so you can confirm your <link rel="alternate" hreflang> tags are actually present in the served markup. It will not list reciprocity errors across pages, though — for that you need a crawler.
Common causes
Ordered by hit rate, highest first.
1. “No return tags” — page A links to B, but B doesn’t link back
Hreflang must be bi-directional. If /en/article/ declares hreflang="zh-Hans" pointing to /zh/article/, then /zh/article/ MUST declare hreflang="en" pointing back. Per Google’s own docs: “If two pages don’t both point to each other, the tags will be ignored.” Asymmetric declarations are silently dropped — not just the broken link, the whole set for that pair.
This is the single most common hreflang error. In Screaming Frog it appears under Hreflang → Missing Confirmation Links (and Inconsistent Language & Region Confirmation Links when the codes don’t match exactly).
How to spot it by hand:
# Check both sides of a pair
curl -s https://site.com/en/article/ | grep -oE 'hreflang="[^"]+" href="[^"]+"'
curl -s https://site.com/zh/article/ | grep -oE 'hreflang="[^"]+" href="[^"]+"'
If /en/ has 4 hreflang lines but /zh/ has 1, the missing 3 cause “no return tags.”
2. Missing self-referencing hreflang
A frequently missed requirement: each page must include an hreflang entry pointing to itself. Google’s docs say “Each language version must list itself as well as all other language versions.” If /en/article/ lists zh-Hans and x-default but omits its own en self-link, crawlers flag Missing Self Reference and the reciprocity math can break.
How to spot it: in the curl output above, confirm each page lists its own language code with its own URL. In Screaming Frog this is the Hreflang → Missing Self Reference filter.
3. “Invalid language code” — wrong format
Google only accepts language codes from ISO 639-1 and region codes from ISO 3166-1 Alpha-2. Anything else is rejected. Common mistakes:
hreflang="en_US"— underscore instead of hyphen; must been-UShreflang="english"— full name instead of the ISO codeenhreflang="en-UK"—UKis not an ISO 3166-1 code; the United Kingdom isGB, so useen-GBhreflang="zh-CHS"— legacy Microsoft locale code; use ISOzh-Hans
Note on Chinese: plain hreflang="zh" is valid (Google accepts it), but zh-Hans (Simplified) and zh-Hant (Traditional) are clearer when you serve both scripts, and zh-Hans is what we recommend below. The earlier advice that “Google requires zh-CN” was never quite right — region codes are optional, script subtags are the precise way to disambiguate.
How to spot it:
curl -s https://site.com/en/article/ | grep -oP 'hreflang="\K[^"]+' | sort -u
Validate each against the BCP 47 / language-tags reference (ISO 639-1 language + optional ISO 3166-1 Alpha-2 region). Screaming Frog flags these under Hreflang → Incorrect Language & Region Codes.
4. “URL not found” — hreflang target returns 404 or redirects
You added a hreflang pointing to /de/article/, but the German version does not exist yet, or its URL changed. A target that returns 404 — or 301/302 to somewhere else — invalidates that hreflang. Google wants every hreflang to land on a live, final, 200 URL.
How to spot it:
for url in $(curl -s https://site.com/en/article/ | grep -oP 'hreflang="[^"]+" href="\K[^"]+'); do
echo -n "$url: "
curl -sI "$url" | head -1
done
Any non-200 response = broken hreflang. In Screaming Frog this is the Hreflang → Non-200 Hreflang URLs filter; export the culprits via Reports → Hreflang → Non-200 Hreflang URLs.
5. Hreflang declares non-canonical URLs
You point hreflang to /zh/article?ref=newsletter, but the canonical of that page is /zh/article/. Google treats this as hreflang to a non-canonical URL and discounts it. Worse: if your <link rel="canonical"> and your hreflang self-link disagree, the page sends conflicting signals.
How to spot it: for each hreflang URL, compare it to that page’s rel="canonical". They should match exactly (same protocol, host, trailing slash, no tracking params). See Canonical mismatch bilingual for the canonical side of this.
6. Missing x-default
Not strictly an error, but warning-adjacent. Without x-default, Google has no declared fallback for users whose locale matches none of your hreflang values. And if some pages in a set carry x-default while others don’t, crawlers report a reciprocal mismatch.
How to spot it: check for <link rel="alternate" hreflang="x-default" href="..." />. If absent (or present on only some pages in the set), add it consistently, pointing to your primary language version or a language-selector page.
7. Hreflang exists in two places at once
You added hreflang in HTML <link> tags AND as HTTP Link headers (or in the sitemap). Google reads all of them, but Google’s docs explicitly warn there is “no benefit” to multiple implementations and that they are “much harder to manage” — duplicated or drifting copies become a source of inconsistency.
How to spot it:
curl -sI https://site.com/en/article/ | grep -i 'link:'
If both HTML <link rel="alternate"> and an HTTP Link header are emitting hreflang, pick one (HTML is most common for content sites) and remove the other.
Shortest path to fix
Step 1: Generate hreflang from a single source
Don’t write hreflang by hand per page — that is how asymmetry creeps in. Generate every page’s set from one translation-key map, and include the self-reference:
// site.config.mjs or similar
export const locales = {
en: { hreflang: 'en', urlPrefix: '/en/' },
zh: { hreflang: 'zh-Hans', urlPrefix: '/zh/' },
};
export function hreflangAlternates(translationKey) {
// Emits an entry for EVERY locale (including the current page's own = self-reference)
const alternates = Object.values(locales).map(({ hreflang, urlPrefix }) => ({
hreflang,
href: `https://site.com${urlPrefix}${translationKey}/`,
}));
alternates.push({ hreflang: 'x-default', href: `https://site.com/en/${translationKey}/` });
return alternates;
}
In your layout, iterate this list to emit <link rel="alternate"> tags. Because every page renders the full set from the same map, every page self-references and every pair is reciprocal by construction.
Step 2: Use valid, unambiguous locale codes
ISO 639-1 language + optional ISO 3166-1 Alpha-2 region. No spaces, no underscores, no invented region codes:
| Wrong | Right |
|---|---|
zh-CHS (legacy MS code) | zh-Hans (Simplified) or zh-Hant (Traditional) |
pt when you serve two | pt-BR or pt-PT |
en_US | en-US |
en-UK | en-GB (UK is not an ISO code) |
english | en |
Step 3: Validate all hreflang URLs return 200
# CI script — extract all hreflang URLs from sitemap and verify each
xmllint --xpath '//*[local-name()="link"]/@href' sitemap.xml | grep -oP 'href="\K[^"]+' | while read url; do
status=$(curl -s -o /dev/null -w "%{http_code}" "$url")
[ "$status" = "200" ] || echo "BAD: $status $url"
done
Step 4: Add x-default
Always include it on every page in the set:
<link rel="alternate" hreflang="x-default" href="https://site.com/en/article/" />
Point it at your primary / fallback language version (or a true language-selector page if you have one).
Step 5: Pick one delivery mechanism
Pick exactly one and remove the others:
- HTML
<link>tags in<head>— easiest for static and content sites - HTTP
Linkheader — best for non-HTML resources (PDFs, etc.) - Sitemap
<xhtml:link>— good for very large sites where editing<head>per page is impractical
Google says there is no Search benefit to running more than one, and three implementations are far harder to keep in sync. Pick one and stick with it.
Step 6: Re-crawl and confirm (don’t wait on Search Console)
Since the International Targeting report is gone, your feedback loop is now the crawler, not Google:
- Re-crawl in Screaming Frog, run Crawl Analysis (needed to populate the
Unlinked Hreflang URLsfilter), and confirm the Hreflang tab shows zero issues. - Spot-check one page in Search Console’s URL Inspection → View crawled page → HTML to confirm Google sees your hreflang tags in the live markup.
- Resubmit your sitemap under Search Console → Sitemaps so Google re-discovers the corrected pages. Re-indexing and re-evaluation of hreflang typically takes from a few days up to 2-3 weeks for larger sites.
Step 7: Validate with a dedicated tool
Run your URLs through the TechnicalSEO hreflang tester or Aleyda Solis’s hreflang generator/validator. They show exactly which page-pairs are asymmetric, which is the fastest way to close out remaining “no return tags” cases.
How to confirm it’s fixed
- Screaming Frog Hreflang tab is clean after Crawl Analysis: no
Missing Confirmation Links,Missing Self Reference,Incorrect Language & Region Codes, orNon-200 Hreflang URLs. - A manual
curlof any two paired pages shows identical, reciprocal hreflang sets (same codes both directions, each page self-referencing, plusx-default). - The TechnicalSEO or Aleyda Solis validator reports no errors for a sampled pair.
- In URL Inspection, the crawled HTML of a live page contains your hreflang
<link>tags.
FAQ
Where is the International Targeting report in Search Console now? Gone. Google deprecated it on September 22, 2022 and removed it from Search Console. Hreflang errors are no longer reported anywhere in the Search Console UI, so use a crawler (Screaming Frog, Sitebulb, Ahrefs, Semrush) to find them.
Does Google still support hreflang at all? Yes. Google explicitly said it “continues to support hreflang” and that its multilingual/multiregional recommendations still stand. Only the reporting and the separate country-targeting setting were removed — the annotations themselves still work and still influence which language version ranks for a given user.
Is hreflang="zh" an error, or do I need zh-CN?
Plain zh is valid; Google accepts ISO 639-1 codes on their own. Region codes are optional. If you serve both Simplified and Traditional, use the script subtags zh-Hans and zh-Hant to disambiguate — that is clearer than a country code like zh-CN.
Do I really need a self-referencing hreflang tag? Yes. Google’s docs state each language version must list itself as well as all other versions. Generating the full set from one map (Step 1) gives you the self-reference automatically.
My hreflang is correct but the wrong language still ranks. Why? Hreflang is a clustering and swap hint, not a ranking override. Google can still pick a different URL if the reciprocity is broken (any asymmetry voids the whole set), if your canonical contradicts the hreflang self-link, or while it re-crawls after a change. Fix reciprocity and canonicals first, then allow a couple of weeks.
How long after fixing do I see results? There is no report to watch anymore, so confirm the markup with a crawler immediately. For Google to act on the change, expect a few days to ~2-3 weeks depending on crawl frequency and site size. Resubmitting the sitemap speeds re-discovery.
Prevention
- Generate hreflang from a single
translationKeysource — never hand-write per page — and include the self-reference in the generated set. - Validate hreflang in CI: every URL returns 200, every code is valid (ISO 639-1 + ISO 3166-1 Alpha-2), every pair is symmetric,
x-defaultis present on all pages in the set. - Pick one delivery mechanism (HTML link tags is most common) and don’t mix.
- When adding a new locale, re-crawl existing pages to confirm they now emit hreflang for the new locale.
- Schedule a periodic Screaming Frog or Ahrefs Site Audit crawl, since Search Console will not warn you when hreflang drifts.
Related
- Canonical mismatch bilingual
- Hreflang warning quick guide
- Hreflang explained bilingual
- Bilingual pages drift apart
Tags: #Troubleshooting #SEO #Debug #hreflang