---
title: Hreflang Validator
description: Checks return linksValidates language codesNo signupNothing stored   Free tool Find out why your hreflang cluster is being ignored Google discards an entire hre
url: https://moxseo.com/tools/hreflang-validator
date_modified: 2026-08-14
author: Admin
language: en_US
---

.mox-hf{
  --mox-bg:#fff;
  --mox-panel:#fff;
  --mox-ink:#0e0f12;
  --mox-ink-soft:#525866;
  --mox-line:#e8e8ea;
  --mox-primary:#ff5a1f;
  --mox-primary-d:#e8470a;
  --mox-accent:#ff5a1f;
  --mox-dark:#0b0d12;
  --mox-dark-2:#16181f;
  --mox-good:#16a077;
  --mox-warn:#e8a20c;
  --mox-risk:#e34d5b;
  --mox-r:18px;
  --mox-r-sm:12px;
  --mox-font-d:'Sora',sans-serif;
  --mox-font-b:'Inter',sans-serif;
  --mox-font-m:'IBM Plex Mono',monospace;
  font-family:var(--mox-font-b);
  background:var(--mox-bg);
  color:var(--mox-ink);
  line-height: 1.6;
}
.mox-hf *,.mox-hf *::before,.mox-hf *::after{box-sizing:border-box;margin:0;padding:0}
.mox-hf a{text-decoration:none}
.mox-hf button{font-family:inherit}
.mox-hf .w{max-width:1180px;margin:0 auto;padding:0 22px}
.mox-hf .sec{padding:88px 0;transition: background 0.3s ease;}

/* 1. WHITE SECTIONS */
.mox-hf .sec--white {
  background: #ffffff !important;
  color: #0e0f12 !important;
  border-top: 1px solid #eef0f3;
  border-bottom: 1px solid #eef0f3;
}
.mox-hf .sec--white h1,
.mox-hf .sec--white h2,
.mox-hf .sec--white h3 {
  color: #0e0f12 !important;
}
.mox-hf .sec--white p,
.mox-hf .sec--white li,
.mox-hf .sec--white .sub,
.mox-hf .sec--white .lead {
  color: #525866 !important;
}
.mox-hf .sec--white .card {
  background: #ffffff !important;
  border: 1px solid #e2e8f0 !important;
  box-shadow: 0 4px 20px rgba(0,0,0,0.03) !important;
}
.mox-hf .sec--white .card:hover {
  transform: translateY(-4px);
  border-color: rgba(245, 131, 39, 0.4) !important;
  box-shadow: 0 18px 40px rgba(14,15,18,0.08) !important;
}

/* 2. GREY SECTIONS (Cool Neutral Tech Grey) */
.mox-hf .sec--grey {
  background: #f1f3f7 !important;
  color: #0e0f12 !important;
  border-top: 1px solid #e2e8f0;
  border-bottom: 1px solid #e2e8f0;
}
.mox-hf .sec--grey h1,
.mox-hf .sec--grey h2,
.mox-hf .sec--grey h3 {
  color: #0e0f12 !important;
}
.mox-hf .sec--grey p,
.mox-hf .sec--grey li,
.mox-hf .sec--grey .sub,
.mox-hf .sec--grey .lead {
  color: #4b5563 !important;
}
.mox-hf .sec--grey .card,
.mox-hf .sec--grey .band,
.mox-hf .sec--grey .tool {
  background: #ffffff !important;
  border: 1px solid #e2e8f0 !important;
  box-shadow: 0 10px 30px rgba(15,23,42,0.05) !important;
}
.mox-hf .sec--grey .card:hover {
  transform: translateY(-4px);
  border-color: rgba(245, 131, 39, 0.4) !important;
  box-shadow: 0 18px 40px rgba(15,23,42,0.09) !important;
}

/* 3. BLACK SECTIONS (Obsidian High-Tech Dark) */
.mox-hf .sec--dark {
  background: #0b0d12 !important;
  color: #f4f4f6 !important;
  border-top: 1px solid rgba(255,255,255,0.06);
  border-bottom: 1px solid rgba(255,255,255,0.06);
}
.mox-hf .sec--dark h1,
.mox-hf .sec--dark h2,
.mox-hf .sec--dark h3 {
  color: #ffffff !important;
}
.mox-hf .sec--dark p,
.mox-hf .sec--dark li,
.mox-hf .sec--dark .sub,
.mox-hf .sec--dark .lead {
  color: #94a3b8 !important;
}
.mox-hf .sec--dark .card {
  background: #16181f !important;
  border: 1px solid rgba(255, 255, 255, 0.08) !important;
  box-shadow: 0 16px 36px rgba(0, 0, 0, 0.5) !important;
}
.mox-hf .sec--dark .card h3 {
  color: #ffffff !important;
}
.mox-hf .sec--dark .card p {
  color: #94a3b8 !important;
}
.mox-hf .sec--dark .card:hover {
  transform: translateY(-4px);
  border-color: rgba(245, 131, 39, 0.5) !important;
  box-shadow: 0 20px 48px rgba(0,0,0,0.8), 0 0 20px rgba(245, 131, 39, 0.15) !important;
}
.mox-hf .sec--dark .chip {
  background: rgba(245, 131, 39, 0.15) !important;
  color: #ff5a1f !important;
  border: 1px solid rgba(245, 131, 39, 0.3) !important;
}

/* TYPOGRAPHY & ELEMENTS */
.mox-hf .eyebrow{display:inline-flex;align-items:center;gap:8px;font-family:var(--mox-font-m);font-size:12px;font-weight:600;letter-spacing:.14em;text-transform:uppercase;color:var(--mox-primary);margin-bottom:16px}
.mox-hf .eyebrow::before{content:"";width:22px;height:2px;background:var(--mox-accent)}
.mox-hf h1{font-family:var(--mox-font-d);font-size:clamp(32px,4.6vw,54px);font-weight:800;line-height:1.12;letter-spacing:-.02em}
.mox-hf h2{font-family:var(--mox-font-d);font-size:clamp(26px,3.4vw,38px);font-weight:700;line-height:1.18;letter-spacing:-.015em;max-width:780px}
.mox-hf h3{font-family:var(--mox-font-d);font-weight:700}
.mox-hf .sub{font-size:17px;color:var(--mox-ink-soft);max-width:700px;margin-top:14px;line-height:1.7}
.mox-hf .btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;font-family:var(--mox-font-d);font-weight:700;font-size:15px;padding:15px 28px;border-radius:999px;border:2px solid transparent;cursor:pointer;transition:transform .25s,background .2s,box-shadow .25s}
.mox-hf .btn:hover{transform:translateY(-2px)}
.mox-hf .btn--p{background:var(--mox-primary);color:#fff !important;box-shadow:0 10px 26px rgba(255,90,31,.32)}
.mox-hf .btn--p:hover{background:var(--mox-primary-d)}
.mox-hf .btn--ghost{background:transparent;border-color:var(--mox-line);color:var(--mox-ink)}
.mox-hf .btn--dg{background:transparent;border-color:rgba(255,255,255,.25);color:#fff !important}

/* TRUST BAR */
.mox-hf .trust{background:#0b0d12;padding:14px 0;border-bottom:1px solid rgba(255,255,255,0.06)}
.mox-hf .trust__row{display:flex;flex-wrap:wrap;justify-content:center;gap:10px 28px;font-family:var(--mox-font-m);font-size:11.5px;letter-spacing:.06em;text-transform:uppercase;color:#a7acb5}
.mox-hf .trust__row span{display:inline-flex;align-items:center;gap:8px}
.mox-hf .trust__row span::before{content:"";width:6px;height:6px;border-radius:50%;background:var(--mox-accent)}

/* HERO */
.mox-hf .hero{padding:88px 0 76px;background:radial-gradient(900px 500px at 85% -10%,rgba(255,90,31,.12),transparent 60%),radial-gradient(700px 420px at -10% 30%,rgba(255,90,31,.08),transparent 55%),#ffffff}
.mox-hf .hero__grid{display:grid;grid-template-columns:1.05fr .95fr;gap:56px;align-items:center}
.mox-hf .lead{font-size:18px;color:var(--mox-ink-soft);margin:20px 0 28px;max-width:560px;line-height:1.7}
.mox-hf .cta-row{display:flex;gap:14px;flex-wrap:wrap;margin-bottom:26px}
.mox-hf .ticks{display:flex;flex-wrap:wrap;gap:10px 22px;font-size:14px;color:var(--mox-ink-soft)}
.mox-hf .ticks span{display:inline-flex;align-items:center;gap:7px}
.mox-hf .ticks span::before{content:"13";color:var(--mox-good);font-weight:700}

/* SAMPLE CARD */
.mox-hf .sample{background:#0b0d12;border:1px solid rgba(255,255,255,0.08);border-radius:24px;padding:30px;box-shadow:0 30px 70px rgba(14,15,18,.35);transform:rotate(1.2deg)}
.mox-hf .sample__tag{font-family:var(--mox-font-m);font-size:11px;letter-spacing:.12em;text-transform:uppercase;color:var(--mox-accent);margin-bottom:18px}
.mox-hf .sample__score{display:flex;align-items:baseline;gap:14px;border-bottom:1px solid rgba(255,255,255,.12);padding-bottom:18px;margin-bottom:18px}
.mox-hf .sample__num{font-family:var(--mox-font-m);font-size:56px;font-weight:600;color:var(--mox-accent);line-height:1}
.mox-hf .sample__lbl{font-size:14px;color:#a7acb5;max-width:160px}
.mox-hf .sample__row{display:flex;justify-content:space-between;gap:16px;padding:9px 0;font-size:14px}
.mox-hf .sample__row b{color:#fff;font-weight:600}
.mox-hf .sample__row span{color:#85898f}
.mox-hf .sample__note{margin-top:16px;font-size:12.5px;color:#85898f;border-left:3px solid var(--mox-accent);padding-left:12px;line-height:1.6}

/* GRIDS & CARDS */
.mox-hf .g3{display:grid;grid-template-columns:repeat(3,1fr);gap:22px;margin-top:44px}
.mox-hf .g2{display:grid;grid-template-columns:repeat(2,1fr);gap:22px;margin-top:44px}
.mox-hf .card{border-radius:var(--mox-r);padding:28px;transition:transform .3s,box-shadow .3s,border-color .3s}
.mox-hf .card h3{font-size:17.5px;margin:14px 0 8px}
.mox-hf .card p{font-size:14.5px;line-height:1.65}
.mox-hf .chip{display:inline-flex;font-family:var(--mox-font-m);font-size:11px;font-weight:600;letter-spacing:.08em;padding:5px 10px;border-radius:6px;background:rgba(255,90,31,.1);color:var(--mox-primary)}

/* SCORE BANDS */
.mox-hf .bands{display:grid;grid-template-columns:repeat(3,1fr);gap:20px;margin-top:44px}
.mox-hf .band{border-radius:var(--mox-r);padding:26px;border-top:5px solid var(--mox-line);transition:transform .3s,box-shadow .3s}
.mox-hf .band:hover{transform:translateY(-3px);box-shadow:0 18px 40px rgba(15,23,42,0.08) !important}
.mox-hf .band h3{font-size:16px;margin:8px 0}
.mox-hf .band p{font-size:14px;color:var(--mox-ink-soft);line-height:1.65}
.mox-hf .band__t{font-family:var(--mox-font-m);font-weight:600;font-size:20px}
.mox-hf .band--a{border-top-color:var(--mox-good) !important}.mox-hf .band--a .band__t{color:var(--mox-good)}
.mox-hf .band--b{border-top-color:var(--mox-warn) !important}.mox-hf .band--b .band__t{color:var(--mox-warn)}
.mox-hf .band--c{border-top-color:var(--mox-risk) !important}.mox-hf .band--c .band__t{color:var(--mox-risk)}

/* TOOL FORM */
.mox-hf .tool{border-radius:24px;padding:36px;margin-top:38px}
.mox-hf .form{display:flex;flex-wrap:wrap;gap:14px}
.mox-hf .form input, .mox-hf .form textarea, .mox-hf .form select{flex:1 1 320px;min-width:250px;font-family:var(--mox-font-b);font-size:16px;color:var(--mox-ink);background:#ffffff;border:1.5px solid #cbd5e1;border-radius:999px;padding:16px 24px;outline:none;transition:border .2s,box-shadow .2s}
.mox-hf .form textarea{border-radius:18px !important;}
.mox-hf .form input:focus, .mox-hf .form textarea:focus, .mox-hf .form select:focus{border-color:var(--mox-primary);box-shadow:0 0 0 4px rgba(255,90,31,.14)}
.mox-hf .hint{font-size:13.5px;color:var(--mox-ink-soft);margin-top:14px}

/* FAQ */
.mox-hf .faq{max-width:860px;margin:44px auto 0}
.mox-hf .faq details{border-bottom:1px solid #e2e8f0;padding:20px 0}
.mox-hf .faq summary{font-family:var(--mox-font-d);font-weight:700;font-size:17px;cursor:pointer;list-style:none;display:flex;justify-content:space-between;gap:16px;color:#0e0f12}
.mox-hf .faq summary::after{content:"+";color:var(--mox-primary);font-size:22px;line-height:1}
.mox-hf .faq details[open] summary::after{content:"12"}
.mox-hf .faq p{font-size:15px;color:var(--mox-ink-soft);line-height:1.7;margin-top:14px}

/* FINAL CTA */
.mox-hf .final{text-align:center;background:radial-gradient(700px 380px at 50% -20%,rgba(255,90,31,.18),transparent 60%),#0b0d12 !important;border-top:1px solid rgba(255,255,255,0.08)}
.mox-hf .final h2{margin:0 auto;color:#ffffff !important}.mox-hf .final .cta-row{justify-content:center;margin-top:32px}

@media(max-width:900px){
  .mox-hf .hero__grid{grid-template-columns:1fr;gap:40px}
  .mox-hf .g3,.mox-hf .bands{grid-template-columns:1fr}
  .mox-hf .g2{grid-template-columns:1fr}
  .mox-hf .sec{padding:60px 0}
  .mox-hf .sample{transform:none}
}

/* .mox-hf base: light surface */
.mox-hf h1,.mox-hf h2,.mox-hf h3,.mox-hf h4{color:var(--mox-ink)!important}
.mox-hf p,.mox-hf li,.mox-hf td{color:var(--mox-ink-soft)!important}
.mox-hf .sub,.mox-hf .lead,.mox-hf .hint{color:var(--mox-ink-soft)!important}
.mox-hf .card h3{color:var(--mox-ink)!important}
.mox-hf .card p{color:var(--mox-ink-soft)!important}
.mox-hf .band h3{color:var(--mox-ink)!important}
.mox-hf .band p{color:var(--mox-ink-soft)!important}
.mox-hf .faq summary{color:var(--mox-ink)!important}
.mox-hf .faq p{color:var(--mox-ink-soft)!important}
.mox-hf .eyebrow,.mox-hf .chip{color:var(--mox-primary)!important}
.mox-hf a{color:var(--mox-primary)!important}
.mox-hf .btn--p{color:#fff!important}
.mox-hf .btn--ghost{color:var(--mox-ink)!important}
.mox-hf .band--a .band__t{color:var(--mox-good)!important}
.mox-hf .band--b .band__t{color:var(--mox-warn)!important}
.mox-hf .band--c .band__t{color:var(--mox-risk)!important}
/* .mox-hf dark surfaces */
.mox-hf .trust__row,.mox-hf .trust__row span{color:#a7acb5!important}
.mox-hf .sec--dark h1,.mox-hf .sec--dark h2,.mox-hf .sec--dark h3,.mox-hf .sec--dark p,.mox-hf .sec--dark li{color:#f4f4f6!important}
.mox-hf .sec--dark .sub,.mox-hf .sec--dark .eyebrow{color:#a7acb5!important}
.mox-hf .final h1,.mox-hf .final h2,.mox-hf .final h3{color:#fff!important}
.mox-hf .final p,.mox-hf .final .sub{color:#a7acb5!important}
.mox-hf .final .eyebrow{color:var(--mox-accent)!important}
.mox-hf .final .btn--dg{color:#fff!important}
.mox-hf .sample__tag{color:var(--mox-accent)!important}
.mox-hf .sample__num{color:var(--mox-accent)!important}
.mox-hf .sample__lbl,.mox-hf .sample__note{color:#85898f!important}
.mox-hf .sample__row span{color:#85898f!important}
.mox-hf .sample__row b{color:#fff!important}
.mox-hf .ticks span{color:var(--mox-ink-soft)!important}

Checks return linksValidates language codesNo signupNothing stored

Free tool

# Find out why your hreflang cluster is being ignored

Google discards an entire hreflang cluster if the return links are missing. This checks your annotations, validates the language codes, and actually fetches your alternates to confirm they link back.

[Check a URL](#mox-run)[International SEO](https://moxseo.com/services/seo/international/)
Verifies reciprocity liveChecks x-defaultFlags invalid codes

Sample result
60hreflang health score for this URL
Annotations found**6**
Self-reference**Present**
x-default**Missing**
de-de return link**Missing**
One broken return link is enough. Google treats reciprocity as a requirement, and a cluster that fails it is dropped in full — not partially.

The problem

## hreflang fails silently, and it fails as a whole cluster

There is no error report for broken hreflang. Search Console’s international targeting report was retired years ago. Meanwhile the rules are unforgiving: every page must reference itself, every alternate must link back, and one missing return link invalidates the entire set rather than the single broken pair.

RECIPROCITY
### Return links are mandatory

If your English page points to the German page, the German page must point back. Without it Google ignores the annotation entirely — and this is where most implementations break, usually because one locale was migrated separately.

SELF-REFERENCE
### Every page must list itself

A page must include an hreflang tag pointing at its own URL. It looks redundant and it is routinely omitted, which is enough on its own to invalidate the cluster.

CODES
### Region codes are not language codes

*en-uk* is invalid; the correct code is *en-gb*. Language uses ISO 639-1, region uses ISO 3166-1 Alpha 2, and mixing them up is one of the most common errors in international SEO.

What gets checked

## Six validations, including the one most tools skip

### Live reciprocity verification

We fetch up to five of your alternate URLs and confirm each one links back to the page you entered. This is the check that actually predicts whether Google will honour your cluster, and most validators never make the request.

### Language and region code validity

Every code is tested against the expected ISO format. Invalid values are reported individually rather than as a generic warning.

### Self-reference and x-default

We confirm the page references itself, and flag a missing x-default — the fallback that decides what unmatched visitors are served.

### Duplicates and relative URLs

Two tags declaring the same locale creates ambiguity. Relative hrefs are invalid outright; hreflang requires absolute URLs including protocol.

The tool

## Check hreflang on any URL

Enter a page from your international cluster. We read its annotations, validate them, then fetch the alternates to confirm the return links exist.

Check hreflang

Fetches up to five alternates to verify reciprocity, so this one takes a few seconds longer.

Reading your results

## What the severity levels mean

Error
### The cluster is broken

Missing self-reference, a missing return link, an invalid code or a relative URL. Any of these means Google is likely disregarding your annotations completely.

Warning
### Working, but incomplete

Usually a missing x-default. Your cluster still functions for matched locales, but unmatched visitors get whichever version Google picks.

Clean
### Reciprocal and valid

Self-referencing, reciprocal, correctly coded. Your locale signals are being read as intended.

The honest version

## hreflang solves the wrong-version problem. It does not solve the ranking problem.

### What it will not do

hreflang does not make a page rank in a new market. It tells Google which existing version to serve to which audience. If your German page has no authority in Germany, correct annotations will not create demand for it.

### When it genuinely matters

When you have real equivalents across locales and the wrong one is surfacing — a UK visitor landing on the US page with the wrong currency, or your Spanish content cannibalising your Mexican content. That is a serving problem, and this is the fix for it.

Common questions

## hreflang, answered plainly

Does one broken return link really invalidate everything?
Google treats hreflang as a bidirectional agreement. If page A claims page B is its German alternate but B does not confirm it, the claim is untrusted. In practice a broken pair frequently causes the wider cluster to be disregarded, which is why we verify reciprocity live rather than assuming it.

Do I need x-default?
Not strictly, but it is strongly recommended. It defines what a visitor sees when no locale matches. Without it Google chooses for you, which is usually your highest-authority version regardless of whether that suits the visitor.

HTML tags, HTTP headers, or sitemap?
All three are valid and Google treats them equally. HTML link tags are easiest to audit, which is what this tool reads. If you implement via sitemap or headers, this tool will report no annotations even though your setup may be correct.

Should hreflang and canonical point to the same URL?
Each page should canonicalise to itself and reference itself in hreflang. Canonicalising a locale variant to a different locale tells Google to drop it, which defeats the purpose of having the cluster.

Is en-uk valid?
No. The United Kingdom’s ISO 3166-1 code is GB, so the correct value is en-gb. This is probably the single most frequent hreflang error we encounter.

Next step

## Correct annotations get the right page served. Authority gets it found.

International SEO usually fails on market-level authority long before it fails on tags — but broken tags waste whatever authority you have.

[International SEO services](https://moxseo.com/services/seo/international/)[See all free tools](https://moxseo.com/tools/)

(function(){
  var inp=document.getElementById('hf-in'),btn=document.getElementById('hf-go'),out=document.getElementById('hf-out');
  if(!inp||!btn||!out)return;
  var SEV={error:'#e34d5b',warn:'#e8a20c',info:'#16a077'};
  var SL={error:'ERROR',warn:'WARNING',info:'INFO'};
  var RS={ok:'#16a077',missing:'#e34d5b',unreachable:'#e8a20c'};
  var RL={ok:'LINKS BACK',missing:'NO RETURN',unreachable:'UNREACHABLE'};
  function esc(s){var d=document.createElement('div');d.textContent=s==null?'':s;return d.innerHTML;}
  function note(m,c){return ''+m+'';}
  function run(){
    var u=(inp.value||'').trim();
    if(!u){out.innerHTML=note('Enter a URL to check.');return;}
    btn.disabled=true;btn.textContent='Checking...';
    out.innerHTML=note('Reading annotations and fetching alternates for '+esc(u)+'. This can take a few seconds.');
    fetch('/wp-json/moxtools/v1/hreflang?url='+encodeURIComponent(u))
      .then(function(r){return r.json().then(function(j){return {s:r.status,j:j};});})
      .then(function(res){
        btn.disabled=false;btn.textContent='Check hreflang';
        var j=res.j;
        if(res.s!==200||j.error){out.innerHTML=note(esc(j.error||'Something went wrong.'),'#e34d5b');return;}
        var sc=j.score||0,col=sc>=80?'#16a077':(sc>=50?'#e8a20c':'#e34d5b');
        var h='';
        h+='hreflang report';
        h+=''+sc+''+j.count+' annotation(s) · self-reference '+(j.self_ref?'present':'missing')+' · x-default '+(j.x_default?'present':'missing')+'';
        if((j.tags||[]).length){
          h+='';
          j.tags.forEach(function(t){h+=''+esc(t.lang)+'';});
          h+='';
        }
        h+='';
        var body='';
        if((j.reciprocity||[]).length){
          body+='';
          body+='Return link verification';
          j.reciprocity.forEach(function(r){
            body+='';
            body+=''+RL[r.status]+'';
            body+=''+esc(r.lang)+'';
            body+=''+esc(r.href)+'';
          });
          body+='';
        }
        if((j.issues||[]).length){
          body+='';
          j.issues.forEach(function(x,i){
            body+='';
            body+=''+SL[x.sev]+'';
            body+=''+esc(x.msg)+'';
          });
          body+='';
        } else if(j.count){ body+='**No issues detected.** Annotations are reciprocal, self-referencing and correctly coded.'; }
        out.innerHTML=h+body;
      })
      .catch(function(){btn.disabled=false;btn.textContent='Check hreflang';out.innerHTML=note('Request failed. Please try again.','#e34d5b');});
  }
  btn.addEventListener('click',run);
  inp.addEventListener('keydown',function(e){if(e.key==='Enter'){e.preventDefault();run();}});
})();
