Google accepts hreflang annotations in three different places: an HTML <link> tag in every page's <head>, an HTTP header, or an entry in your XML sitemap. Most guides only show you the HTML version, which is fine until you have a hundred URLs times a dozen languages and your <head> section turns into a wall of link tags nobody wants to maintain by hand. The sitemap method solves that — but it has its own syntax to get right, and the same failure mode that breaks HTML hreflang breaks it too.
One signal, three delivery methods
Google's own documentation on localized versions lists the HTML tag, the HTTP header, and the sitemap entry as interchangeable — pick one method per site and stick to it, because mixing all three on the same set of pages adds maintenance risk without adding any signal strength. The header option is mostly useful for non-HTML files like PDFs, where there's no <head> to put a tag in.
For ordinary HTML pages, the real choice is between tags in the page itself and entries in the sitemap. Here's the practical difference. HTML tags live with the page: open the file, see every language alternate right there. Sitemap entries live in one central file: open the sitemap, see every language alternate for every URL, without touching a single page template.
For two languages and a few dozen URLs, that centralization barely matters. Past a few hundred URLs across many locales, editing hreflang in-page means shipping a template change every time you add a language; editing it in the sitemap means regenerating one XML file.
The XML sitemap syntax
Sitemap-based hreflang uses the XHTML namespace, which most sitemap generators don't add unless you specifically ask for hreflang support. Per Google's sitemap extension guide, the urlset root element needs the namespace declared, and then each url block gets one xhtml:link entry per language version — including one pointing at itself:
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:xhtml="http://www.w3.org/1999/xhtml">
<url>
<loc>https://example.com/en/pricing/</loc>
<xhtml:link rel="alternate" hreflang="en" href="https://example.com/en/pricing/" />
<xhtml:link rel="alternate" hreflang="de" href="https://example.com/de/preise/" />
</url>
<url>
<loc>https://example.com/de/preise/</loc>
<xhtml:link rel="alternate" hreflang="en" href="https://example.com/en/pricing/" />
<xhtml:link rel="alternate" hreflang="de" href="https://example.com/de/preise/" />
</url>
</urlset>
Miss the xmlns:xhtml declaration and the whole block fails as XML before Google ever gets to the hreflang logic — most validators will catch that first.
Not a ranking factor
Hreflang doesn't move your position in search results. Per Google's own documentation, it only tells Google which URL to serve a visitor based on their language and region — get it wrong and the wrong page shows up in the wrong market, but your rankings for the correct market stay exactly where your content earned them.
The reciprocal-tag rule
Both HTML and sitemap hreflang share one requirement that trips up almost every multi-language site at some point: annotations have to point both ways. If your English pricing page lists the German page as its de alternate, the German page has to list the English page back as its en alternate — and each page additionally lists itself. Google's guidance on localized versions is explicit that annotations without a matching return link may be ignored rather than corrected or guessed at.
This is the failure mode that shows up after a redirect, a URL rename, or a page that got deleted on one side but not the other. Ahrefs' Site Audit tool has a dedicated check for exactly this, filed under the label "missing reciprocal hreflang (no return tag)."
Google used to surface hreflang problems through the International Targeting report in Search Console. That report is retired now, and there's no direct replacement inside Search Console itself. Catching a broken return tag today usually means running a crawler — Screaming Frog and Ahrefs both check reciprocity — or spot-checking a sample of URLs with the URL Inspection tool, rather than getting a dashboard warning.
HTML tags vs. sitemap entries: when each wins
HTML <link> tags | XML sitemap entries | |
|---|---|---|
| Best fit | A handful of locales, template-driven sites | Dozens of locales, or URLs generated outside your page templates |
| Where you edit | Every page template | One central sitemap file |
| Visibility while debugging | View source on the actual page | Open the sitemap and search |
| Non-HTML files (PDFs, etc.) | Not applicable — no <head> | Works, alongside the HTTP header option |
| Setup effort for 2 languages | Low | Unnecessary overhead |
Here's the opinion part: if you're running two languages and a normal template, sitemap-based hreflang is solving a problem you don't have. It earns its complexity on sites with real locale sprawl — a travel site with 15 country versions of every listing page is a legitimate sitemap-hreflang candidate. A blog with an English and a German version of each post isn't, and forcing it there just adds a second place for the reciprocal-tag rule to quietly break.
Sitemap limits and the x-default fallback
Whichever method you choose, the sitemap protocol itself still applies. As of July 2026, a single sitemap file is capped at 50,000 URLs and 50MB uncompressed per the sitemaps.org protocol — a site with more URLs than that needs a sitemap index pointing at multiple sitemap files, hreflang or not. Protocols do get revised, so treat that number as current rather than permanent and check the source directly before you build automation around it. Our XML Sitemap Generator flags it the moment a crawl passes that count, so you know to split the URLs across several sitemap files and list them in a sitemap_index.xml rather than shipping one oversized file.
x-default
hreflang="x-default" marks a fallback URL for visitors whose language or region doesn't match any of your listed alternates — typically your homepage or a language-selector page. Per Google's own guidance on x-default, it's optional, not required: skip it and unmatched visitors just get Google's normal best guess instead of your explicit fallback.
Build it without hand-coding the XML
Hand-writing xhtml:link blocks for a few dozen URLs is tedious and exactly the kind of task where a stray missing quote or unclosed tag breaks the whole file. Our free Hreflang Generator takes your language versions and outputs valid, reciprocal tags in whichever format matches your setup:
| Your setup | Output format to generate |
|---|---|
| Editing page templates directly | HTML link tags |
| An existing XML sitemap you control | XML sitemap entries |
| Non-HTML files (PDFs, images) | HTTP header |
Everything runs in your browser; nothing you enter is sent anywhere. Once you've got sitemap entries, run the result through our Sitemap Validator to confirm the XML itself is well-formed before you push it live.
Hreflang GeneratorBuild valid, reciprocal hreflang tags in HTML, XML sitemap or HTTP header format — free, no account.Open the tool