---
title: "Hreflang in XML sitemaps: syntax, limits and common errors"
description: "When to put hreflang in a sitemap instead of the page head, one valid multilingual sitemap to copy, Google's size limits and the errors that break the file."
url: "https://www.langrelay.com/blog/hreflang-xml-sitemap"
---

1. [Home](https://www.langrelay.com/)
2. [Blog](https://www.langrelay.com/blog)
3. Hreflang in XML sitemaps: syntax, limits and common errors

ArticleMultilingual SEO

# Hreflang in XML sitemaps: syntax, limits and common errors

When to put hreflang in a sitemap instead of the page head, one valid multilingual sitemap to copy, Google's size limits and the errors that break the file.

[Chris Jayden](https://www.langrelay.com/about)

Founder

Published

6 October 2026

Reading time

7 min read

![Two skaters glide toward each other across a frozen lake at dusk, past a sauna cabin whose door carries leaf tiles.](https://www.langrelay.com/_emdash/api/media/file/01M4ET5D5B4ER233AEN4NJNV5G.webp)

On this page

1. Head, sitemap or HTTP header: which one fits?
2. A valid multilingual sitemap
3. The rules, from Google's documentation
4. How big can a multilingual sitemap get?
5. Should lastmod change when a translation is published?
6. Common errors
7. How do you check a hreflang sitemap?
8. Multilingual sitemaps on WordPress
9. Where LangRelay puts the set

An XML sitemap can carry the whole hreflang set, so the pages themselves don't have to. Declare the `xhtml` namespace on the `<urlset>` element, give every language version its own `<url>` entry, and inside each entry add one `<xhtml:link rel="alternate">` for every version, that entry's own URL included. Google calls the sitemap, head tags and HTTP headers "equivalent", so use the sitemap when it is the place your stack can keep correct, and use one method rather than two.

## Head, sitemap or HTTP header: which one fits?

Google accepts the same set in three places. Its documentation says you can use all three at once but that "there's no benefit in Search", and that three implementations are harder to manage than one. What decides it is where your site can generate the list reliably.

| Method | Where the set lives | Fits when | Watch out for |
| --- | --- | --- | --- |
| Link tags in the `<head>` | In every HTML page | Templates print the page, and each page knows its translations | The set adds a few lines to every page and has to be right on every one |
| XML sitemap | In one or more sitemap files | Templates are hard to change, the site is large, or a separate system knows the translations | Nobody sees the set by viewing a page, and the file has to change whenever a translation goes live or is withdrawn |
| HTTP `Link` header | In the response headers | Files with no `<head>`, such as PDFs | Server or CDN configuration per URL |

Yoast's hreflang guide makes the case for the sitemap from the operator's side. The markup adds no weight to pages that visitors download, and it is usually easier to change one sitemap than every page of a site, which can spare a long approval process. Its complaint is the size: the sitemap form is "very verbose". The reason is visible in the sample below: every URL repeats the full list.

If you do run two methods, for example during a migration from head tags to a sitemap, make sure they say the same thing. Two sources that disagree about which URL is the Portuguese version leave you guessing which one Google used.

## A valid multilingual sitemap

An outdoor shop publishes its tents page in English, with Spanish and Portuguese translations under `/es/` and `/pt/`. English is also the fallback for everyone else. This sitemap describes that one page in all three languages:

```
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
        xmlns:xhtml="http://www.w3.org/1999/xhtml">
  <url>
    <loc>https://www.alderbrook.example/tents/</loc>
    <lastmod>2026-09-30</lastmod>
    <xhtml:link rel="alternate" hreflang="en" href="https://www.alderbrook.example/tents/"/>
    <xhtml:link rel="alternate" hreflang="es" href="https://www.alderbrook.example/es/tents/"/>
    <xhtml:link rel="alternate" hreflang="pt" href="https://www.alderbrook.example/pt/tents/"/>
    <xhtml:link rel="alternate" hreflang="x-default" href="https://www.alderbrook.example/tents/"/>
  </url>
  <url>
    <loc>https://www.alderbrook.example/es/tents/</loc>
    <lastmod>2026-10-02</lastmod>
    <xhtml:link rel="alternate" hreflang="en" href="https://www.alderbrook.example/tents/"/>
    <xhtml:link rel="alternate" hreflang="es" href="https://www.alderbrook.example/es/tents/"/>
    <xhtml:link rel="alternate" hreflang="pt" href="https://www.alderbrook.example/pt/tents/"/>
    <xhtml:link rel="alternate" hreflang="x-default" href="https://www.alderbrook.example/tents/"/>
  </url>
  <url>
    <loc>https://www.alderbrook.example/pt/tents/</loc>
    <lastmod>2026-10-04</lastmod>
    <xhtml:link rel="alternate" hreflang="en" href="https://www.alderbrook.example/tents/"/>
    <xhtml:link rel="alternate" hreflang="es" href="https://www.alderbrook.example/es/tents/"/>
    <xhtml:link rel="alternate" hreflang="pt" href="https://www.alderbrook.example/pt/tents/"/>
    <xhtml:link rel="alternate" hreflang="x-default" href="https://www.alderbrook.example/tents/"/>
  </url>
</urlset>
```

The second namespace declaration, `xmlns:xhtml`, is what makes the `xhtml:` prefix legal. Without it the file is not well-formed XML once namespaces are taken into account, and a strict parser stops at the first `<xhtml:link>`.

Each translation has an entry of its own. A sitemap that lists only the English URL in `<loc>` and tucks the Spanish and Portuguese URLs inside it as alternates is missing two thirds of the set. Google's rules ask for a separate `<url>` element for each URL, and its return-link rule needs the Spanish entry to point back at the English one.

The `<lastmod>` dates differ. The Portuguese page went live on 4 October, two days after the Spanish one, so its date is its own.

## The rules, from Google's documentation

Google's page on localized versions, last updated on 2026-09-21, lists the sitemap rules, and its general hreflang guidelines apply on top:

1. Declare `xmlns:xhtml="http://www.w3.org/1999/xhtml"`.
2. Create a separate `<url>` element for each URL, with a `<loc>` child naming that page.
3. Give each `<url>` an `<xhtml:link rel="alternate" hreflang="...">` child for every alternate version, including itself. The article on [self-referencing hreflang and x-default](https://www.langrelay.com/blog/self-referencing-hreflang-x-default) explains why the entry's own line matters.
4. Use fully qualified URLs with the scheme, so `https://example.com/foo` and never `/foo` or `//example.com/foo`. This holds for `<loc>` as well: Google's sitemap guide says it "will attempt to crawl your URLs exactly as listed".
5. Alternate URLs may sit on other domains, which matters if your languages live on subdomains or country domains (see [subdomain vs subdirectory](https://www.langrelay.com/blog/subdomain-vs-subdirectory-multilingual-seo)). If two pages don't point to each other, though, Google ignores the tags.
6. Everything else in Google's sitemap documentation applies to the extension too: UTF-8 encoding, entity-escaped values and the size limits below.

The language codes are the same as in head tags: an ISO 639-1 language, optionally followed by an ISO 3166-1 Alpha 2 region, or `x-default`.

## How big can a multilingual sitemap get?

Google limits a single sitemap to 50 MB uncompressed or 50,000 URLs. Past either limit you split the file and list the parts in a sitemap index, which can itself hold up to 50,000 sitemaps. Search Console accepts up to 500 sitemap index files per site.

Hreflang makes a sitemap grow faster than the page count suggests. Each language version is its own `<url>` entry, and each entry repeats the full list. A site with 3,000 pages in one original and four translations has 15,000 entries, each carrying six `<xhtml:link>` lines (five languages and x-default), so 90,000 link lines in total. That stays under the URL limit, but each link line in the sample above is about 100 characters, so at that length the alternates alone come to about 9 MB. Plan the split before the file reaches the limit, for example one sitemap per section, with every language of a section in the same file so each set can be read in one place.

## Should lastmod change when a translation is published?

Yes, for the translated URL. Google uses `<lastmod>` only when it is "consistently and verifiably" accurate, and it describes a significant update as a change to the main content, the structured data or the links on the page. A new or revised translation is exactly that for the translated URL. It is not a change to the original, so leave the original's date alone, even though its alternate list grew by one line.

## Common errors

| Error | What you see | Fix |
| --- | --- | --- |
| `xmlns:xhtml` missing | The file fails to parse at the first `<xhtml:link>` | Declare both namespaces on `<urlset>` |
| Wrong sitemap namespace (for example `.../sitemap/.9`) | Search Console reports an incorrect namespace or unsupported format | Use `http://www.sitemaps.org/schemas/sitemap/0.9` exactly |
| Only the original has a `<url>` entry | Return links are missing for every translation | Give every version its own entry with the full list |
| An entry lacks its own line | The set on that entry is incomplete | Generate the list once and print it in every entry |
| Relative `href` or `<loc>` values | Google cannot use them | Write full `https://` URLs |
| A raw `&` in a URL with a query string | A parsing error | Escape it as `&amp;` |
| Curly quotes around attribute values | An unsupported format error | Use straight quotes; word processors insert curly ones |
| Sitemap on `www` lists URLs without it, or the reverse | A path mismatch error | Keep the host consistent with the sitemap's location |
| Alternates that redirect, return 404 or carry `noindex` | Those versions cannot be shown | List only final, indexable URLs |

Google's sitemap guide also asks you to include the URLs you want in its results, which in practice means the canonical URL of each version. A translated page whose canonical points at the original should not be in the sitemap as a translation; the article on [hreflang and canonical tags](https://www.langrelay.com/blog/hreflang-and-canonical-tags) covers that conflict.

## How do you check a hreflang sitemap?

Start with the file itself:

```
curl -s https://www.alderbrook.example/sitemap.xml | xmllint --noout -
curl -s https://www.alderbrook.example/sitemap.xml | grep -c '<url>'
```

The first command prints nothing when the XML parses. The second counts entries, which should equal your page count times the number of languages that are live for each page.

Then submit the sitemap, or the index, in Search Console's Sitemaps report. The report shows only sitemaps submitted there or through the API, not ones Google found through `robots.txt`, so submit it even if your `robots.txt` already has a `Sitemap:` line. A status of Success means the file was read without errors. Has errors means the file was fetched but some entries failed, and only the entries that parsed cleanly are queued for crawling. Discovered pages counts the URLs it found, and Google adds that a discovered URL is no guarantee of crawling or indexing. To check a single translated URL afterwards, use URL Inspection on it.

## Multilingual sitemaps on WordPress

WordPress has generated a basic XML sitemap since version 5.5, built from providers for posts, taxonomies and users that plugins can extend or replace. Most multilingual WordPress sites use the sitemap of an SEO plugin instead, and the translation plugin adds the hreflang to it:

- WPML's documentation says it prints `<xhtml:link rel="alternate">` entries inside the XML sitemaps of Yoast SEO and Rank Math, and tells you to look for them under `/sitemap.xml` for Yoast SEO or `/sitemap_index.xml` for Rank Math.
- Rank Math's knowledge base says translated posts appear in its sitemap index automatically and that WPML adds the hreflang to the translated pages.
- TranslatePress's SEO Pack documentation says the add-on extends the sitemaps of SEO plugins and creates a multilingual sitemap automatically. The SEO Pack is available only in the premium versions (Personal, Business or Developer), so the free plugin does not do this.

In each case the translated URLs reach the SEO plugin's sitemap through the translation plugin's integration with it. [Hreflang in WordPress](https://www.langrelay.com/blog/hreflang-wordpress) covers how to see which plugin printed which tags.

## Where LangRelay puts the set

LangRelay's WordPress plugin prints the hreflang set as link tags in the `<head>` of the original page and of each translated version. It adds nothing to your sitemaps and does not generate a sitemap of its own, so your SEO plugin's sitemap keeps listing your original URLs as it does today.

The translated pages are not separate WordPress posts. The plugin serves `/es/tents/` from the original post and translates the rendered page, so a crawler reaches the Spanish URL through the set in the original's head, through the language switcher's links and through internal links, which the plugin points at the same language on a translated page. The set in the head is enough for Google to connect the versions: its documentation treats the three methods as equivalent. A language appears in it once that page's translation is live.

Our [hreflang guide](https://www.langrelay.com/guides/hreflang) has the rest of the rules for the set, and [hreflang vs the HTML lang attribute](https://www.langrelay.com/blog/hreflang-vs-html-lang) covers the attribute the head needs as well. For the feature overview see [multilingual SEO](https://www.langrelay.com/multilingual-seo), and to look at the plugin's output on your own site, [book a demo](https://www.langrelay.com/book-a-demo).

## Sources

The pages this one cites, with the day each was read.

1. 01[Localized versions of your pages (Google Search Central, last updated 2026-09-21)](https://developers.google.com/search/docs/specialty/international/localized-versions)developers.google.com, checked 6 October 2026
2. 02[Build and submit a sitemap (Google Search Central, last updated 2026-07-08)](https://developers.google.com/search/docs/crawling-indexing/sitemaps/build-sitemap)developers.google.com, checked 6 October 2026
3. 03[Manage your sitemaps with a sitemap index file (Google Search Central, last updated 2025-12-10)](https://developers.google.com/search/docs/crawling-indexing/sitemaps/large-sitemaps)developers.google.com, checked 6 October 2026
4. 04[Manage your sitemaps using the Sitemaps report (Search Console Help)](https://support.google.com/webmasters/answer/7451001)support.google.com, checked 6 October 2026
5. 05[Sitemaps XML format (sitemaps.org)](https://www.sitemaps.org/protocol.html)sitemaps.org, checked 6 October 2026
6. 06[hreflang: the ultimate guide (Yoast, published 2022-03-01, modified 2024-08-21)](https://yoast.com/hreflang-ultimate-guide/)yoast.com, checked 6 October 2026
7. 07[How to Translate Your Site for Multilingual SEO (WPML documentation, last updated 2026-07-02)](https://wpml.org/documentation/translating-your-contents/multilingual-seo/)wpml.org, checked 6 October 2026
8. 08[Multilingual SEO with Rank Math SEO and WPML (Rank Math knowledge base)](https://rankmath.com/kb/multilingual-seo-wpml/)rankmath.com, checked 6 October 2026
9. 09[Multilingual SEO (TranslatePress)](https://translatepress.com/multilingual-seo/)translatepress.com, checked 6 October 2026
10. 10[SEO Pack (TranslatePress documentation)](https://translatepress.com/docs/addons/seo-pack/)translatepress.com, checked 6 October 2026
11. 11[New XML Sitemaps Functionality in WordPress 5.5 (Make WordPress Core, 2020-07-22)](https://make.wordpress.org/core/2020/07/22/new-xml-sitemaps-functionality-in-wordpress-5-5/)make.wordpress.org, checked 6 October 2026

[Chris Jayden](https://www.langrelay.com/about)

Founder, LangRelay

Chris Jayden is the founder of LangRelay. Chris has worked on websites of every size, from large e-commerce stores to small sites with a handful of pages, and started LangRelay after years of translating them the hard way.

On this page

1. Head, sitemap or HTTP header: which one fits?
2. A valid multilingual sitemap
3. The rules, from Google's documentation
4. How big can a multilingual sitemap get?
5. Should lastmod change when a translation is published?
6. Common errors
7. How do you check a hreflang sitemap?
8. Multilingual sitemaps on WordPress
9. Where LangRelay puts the set

Share

- [Share on LinkedIn (opens in a new tab)](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fwww.langrelay.com%2Fblog%2Fhreflang-xml-sitemap)
- [Share on X (opens in a new tab)](https://x.com/intent/post?url=https%3A%2F%2Fwww.langrelay.com%2Fblog%2Fhreflang-xml-sitemap&amp;text=Hreflang%20in%20XML%20sitemaps%3A%20syntax%2C%20limits%20and%20common%20errors)

See it on your site

A 30-minute walkthrough on one of your pages.

[Book a demo](https://www.langrelay.com/book-a-demo)

- hreflang
- multilingual SEO
- XML sitemap

## Keep reading

- Article
  ### [Hreflang vs the HTML lang attribute: what each one does](https://www.langrelay.com/blog/hreflang-vs-html-lang)
  The lang attribute says what language this page is in; hreflang points to the page in other languages. Who reads each, valid values, and both in one head.
- Article
  ### [Hreflang in WordPress: how plugins print it and how to check](https://www.langrelay.com/blog/hreflang-wordpress)
  Where hreflang comes from on WordPress, what WPML, Polylang, TranslatePress and Weglot print by default, how Yoast SEO and Rank Math fit in, and how to check.

Book a demo

## See LangRelay on your own site

Book 30 minutes with the team. We translate one of your pages live and walk through review, publishing and multilingual SEO.

[Book a demo](https://www.langrelay.com/book-a-demo)[See pricing](https://www.langrelay.com/pricing)
