---
title: "Fix Invalid hreflang Tags for Better International SEO"
description: "Learn how to fix hreflang validation errors including unexpected language codes and relative URLs in your multi-language site."
canonical_url: "https://unlighthouse.dev/learn-lighthouse/seo/hreflang"
last_updated: "2025-01-18"
---

The `hreflang` attribute tells search engines which version of a page to show users based on their language or region. When it's misconfigured, Google might show French users your English page - or ignore your translations entirely.

**The scale of the problem:** Implementation errors are widespread, and [common hreflang errors and how to fix them](https://developers.google.com/search/docs/specialty/international/localized-versions) are a major focus for international SEO. This is one of the most error-prone SEO implementations.

## What's the Problem?

Lighthouse flags two specific issues with hreflang:

**1. Unexpected Language Code**

Invalid or misspelled language codes mean Google can't identify the language.

```html
<!-- Wrong: "uk" is the country code for Ukraine, not United Kingdom -->
<link rel="alternate" hreflang="uk" href="https://example.com/en-gb/" />

<!-- Wrong: invented language code -->
<link rel="alternate" hreflang="esp" href="https://example.com/es/" />
```

**2. Relative href Value**

The href must be an absolute URL. Relative URLs are rejected.

```html
<!-- Wrong: relative URL -->
<link rel="alternate" hreflang="es" href="/es/" />

<!-- Right: absolute URL -->
<link rel="alternate" hreflang="es" href="https://example.com/es/" />
```

These mistakes are common because hreflang has strict syntax requirements that aren't obvious.

## How to Identify This Issue

### Chrome DevTools

1. Open DevTools (F12) → Elements tab
2. Search for `hreflang` in the HTML
3. Verify each link element has:

  - A valid language code (ISO 639-1) or language-region code
  - An absolute URL starting with `https://` or `http://`

You can also check the response headers for HTTP header-based hreflang:

- Network tab → select the document → Headers → Look for `Link:` headers

### Lighthouse

Run a Lighthouse SEO audit. Look for "Document doesn't have a valid hreflang" which shows each failing element with the specific error (unexpected language or relative URL).

## The Fix

### 1. Use Valid Language Codes

Language codes must follow ISO 639-1 (two-letter codes) or BCP 47 format.

```html
<!-- Valid language codes -->
<link rel="alternate" hreflang="en" href="https://example.com/" />
<link rel="alternate" hreflang="es" href="https://example.com/es/" />
<link rel="alternate" hreflang="fr" href="https://example.com/fr/" />
<link rel="alternate" hreflang="zh" href="https://example.com/zh/" />

<!-- Valid language-region codes -->
<link rel="alternate" hreflang="en-US" href="https://example.com/en-us/" />
<link rel="alternate" hreflang="en-GB" href="https://example.com/en-gb/" />
<link rel="alternate" hreflang="pt-BR" href="https://example.com/pt-br/" />
<link rel="alternate" hreflang="zh-TW" href="https://example.com/zh-tw/" />
```

Common mistakes to avoid:

- Use `en-GB` not `uk` for UK English
- Use `zh-TW` not `tw` for Traditional Chinese
- Use `es` not `esp` for Spanish
- Use `pt` not `por` for Portuguese

### 2. Always Use Absolute URLs

Every href must include the full URL with protocol and domain.

```html
<!-- Before: relative URLs -->
<link rel="alternate" hreflang="en" href="/" />
<link rel="alternate" hreflang="es" href="/es/" />

<!-- After: absolute URLs -->
<link rel="alternate" hreflang="en" href="https://example.com/" />
<link rel="alternate" hreflang="es" href="https://example.com/es/" />
```

If you're generating hreflang tags dynamically, construct the full URL:

```javascript
const baseUrl = 'https://example.com'
const hreflangs = [
  { lang: 'en', path: '/' },
  { lang: 'es', path: '/es/' },
  { lang: 'fr', path: '/fr/' },
]

hreflangs.map(h => ({
  rel: 'alternate',
  hreflang: h.lang,
  href: `${baseUrl}${h.path}`,
}))
```

### 3. Include x-default for Fallback

Add `x-default` to specify which page to show when no language matches.

```html
<link rel="alternate" hreflang="x-default" href="https://example.com/" />
<link rel="alternate" hreflang="en" href="https://example.com/" />
<link rel="alternate" hreflang="es" href="https://example.com/es/" />
<link rel="alternate" hreflang="fr" href="https://example.com/fr/" />
```

Typically, `x-default` points to your primary language version or a language selector page.

### 4. Add hreflang to All Alternate Pages

Every page in your hreflang set must include links to all other versions, including itself.

```html
<!-- On https://example.com/ (English) -->
<link rel="alternate" hreflang="en" href="https://example.com/" />
<link rel="alternate" hreflang="es" href="https://example.com/es/" />

<!-- On https://example.com/es/ (Spanish) - must have the same links -->
<link rel="alternate" hreflang="en" href="https://example.com/" />
<link rel="alternate" hreflang="es" href="https://example.com/es/" />
```

If the Spanish page doesn't link back to the English page, Google may ignore the hreflang entirely.

### 5. Choose the Right Implementation

You can implement hreflang in three places:

**HTML head (most common):**

```html
<head>
  <link rel="alternate" hreflang="en" href="https://example.com/" />
  <link rel="alternate" hreflang="es" href="https://example.com/es/" />
</head>
```

**HTTP headers (for non-HTML files like PDFs):**

```http
Link: <https://example.com/file.pdf>; rel="alternate"; hreflang="en",
      <https://example.com/es/file.pdf>; rel="alternate"; hreflang="es"
```

**XML sitemap (for large sites):**

```xml
<url>
  <loc>https://example.com/</loc>
  <xhtml:link rel="alternate" hreflang="en" href="https://example.com/" />
  <xhtml:link rel="alternate" hreflang="es" href="https://example.com/es/" />
</url>
```

Pick one method and stick with it. Lighthouse only checks HTML head and HTTP headers - not sitemaps.

## Framework-Specific Solutions

<callout icon="i-logos-nextjs-icon">

**Next.js**: Use `next-intl` or similar i18n library that handles hreflang automatically. Or add links in your `_document.js` or via the `Head` component with computed absolute URLs from your domain config.

</callout>

<callout icon="i-logos-nuxt-icon">

**Nuxt**: Use `@nuxtjs/i18n` module which generates correct hreflang tags automatically. Set `baseUrl` in your i18n config so the module generates absolute URLs.

</callout>

## Verify the Fix

1. Run Lighthouse SEO audit again
2. Confirm "Document has a valid hreflang" shows as passing
3. Use Google Search Console → URL Inspection to verify Google sees your hreflang
4. Check the International Targeting report in Search Console for hreflang errors

## Common Mistakes

- **Forgetting the self-referencing link**: Each page must include an hreflang link to itself. The English page needs `hreflang="en"` pointing to itself, not just to other languages.
- **Mixing implementation methods**: Don't use HTML head on some pages and HTTP headers on others. Pick one method for consistency.
- **Not updating hreflang when URLs change**: When you change a URL structure, update all hreflang links across all language versions. Broken links break the entire hreflang cluster.
- **Using hreflang in body**: Hreflang links must be in `<head>` or HTTP headers. Links in `<body>` are ignored by Lighthouse and may be ignored by search engines.
- **X-default on a page that redirects**: If your x-default URL redirects, it can't link back to the hreflang cluster, creating validation errors.
- **Missing self-referencing tags**: Each page must include an hreflang pointing to itself. This is one of the most [common errors in international SEO implementations](https://developers.google.com/search/docs/specialty/international/localized-versions).

## Related Issues

Hreflang issues often appear alongside:

- [Canonical](/learn-lighthouse/seo/canonical) - Canonical URLs must match hreflang URLs
- [HTML Lang](/learn-lighthouse/accessibility/html-has-lang) - The HTML lang attribute must match hreflang language
- [Meta Description](/learn-lighthouse/seo/meta-description) - Each language version needs unique descriptions

## Test Your Entire Site

Hreflang issues compound across a multilingual site. If your English-to-Spanish links are broken, every page in both languages is affected. Unlighthouse scans your entire site and identifies every page with hreflang errors, so you can fix the pattern once rather than hunting page by page.
e by page.
