Skip to content
Surfilby Adam Hafez
Free tool

Hreflang XML sitemap generator

Hreflang sitemap generator: turn language codes and URLs into sitemap XML with xhtml:link alternates, and check codes and URLs. Free, runs in your browser.

Runs entirely in your browser. Nothing you enter is uploaded, logged or stored.

Nothing you enter here is sent anywhere; the XML is built in your browser only.

    sitemap.xml

    Key takeaways

    • Google treats HTML tags, HTTP headers and a sitemap as equivalent ways to give hreflang, so one method is enough.
    • Each url element must list every alternate version of the page as an xhtml:link, including the page itself.
    • The sitemap must declare the xhtml namespace on its urlset element for the xhtml:link elements to be valid.
    • Google says child xhtml:link elements do not count towards the sitemap URL limit, which sitemaps.org sets at 50,000 URLs per file.
    • Language codes use ISO 639-1 with an optional ISO 3166-1 Alpha 2 region, so en and en-GB are valid but es-419 is not supported.

    What it takes

    • A language code and full URL for each localized version
    • A blank line between each group of alternate pages
    • An optional x-default row for each group

    More tools

    All of them free, all of them browser-only.

    Browse the tools

    How to use it

    1. 1List one version per lineWrite the code, a space, then the full https URL, for example en followed by the English page. Codes like en-gb are normalized to en-GB.
    2. 2Separate pages with a blank lineEvery page that has translations is its own group. The tool builds one set of annotations per group, so groups never cross-reference each other.
    3. 3Add x-default where you have a fallbackUse it for a language selector or a catch-all page. It is optional, and the tool notes when a group has none.
    4. 4Resolve the errorsThe tool reports a code pointing at two URLs, a code that is not language or language-region, and any URL that is not fully qualified https.
    5. 5Copy the XML into your sitemapSave it as a sitemap file, or merge the url blocks into an existing sitemap that already declares the xhtml namespace, then submit it in Search Console.

    What the generator checks

    Google offers three equivalent ways to declare localized versions: HTML link tags, HTTP headers and a sitemap. The sitemap keeps every annotation in one file instead of every template. The tool writes that file from a plain list and checks each line against Google’s rules:

    • Line format. Each line must be a code, a space, then a URL. Anything else is an error.
    • Code format. A two-letter language, optionally a hyphen or underscore and a two-letter region, or x-default. Codes are normalized, so fr_ca and fr-ca both become fr-CA. Google accepts either case, so this is tidying, not a correction.
    • Fully qualified https URLs. Google says alternate URLs “must be fully-qualified, including the transport method”. The tool goes one step further and requires https.
    • One URL per code in a group. A code pointing at two different URLs is an error.
    • At least two versions. A group with a single language version is a warning.
    • x-default. Optional, so a group without one is only noted.

    How to read the results

    Errors are lines the tool dropped from the XML, so fix them first. A warning means a group will build but says nothing useful to Google. Info notes, such as a missing x-default, need no action unless you have a language selector or fallback page. “No problems found” means every line parsed.

    The output follows Google’s sitemap rules: the xhtml namespace declared on urlset, one url element per page, a loc child, and an xhtml:link for every version, itself included. URLs are entity escaped, as sitemaps.org requires for characters such as &.

    Worked example

    The tool loads with two groups. The first has en, de, fr-ca and x-default rows for a pricing page, with x-default pointing at the English URL. The second has en and de rows for an about page.

    It returns one note, “Set 2: no x-default”, and builds five url blocks. The pricing group gives three, one each for the English, German and Canadian French URLs, and each carries four xhtml:link lines: en, de, fr-CA and x-default. The English URL gets only one block even though it appears twice. The about group gives two blocks of two links each.

    The x-default URL only gets a url block of its own if it is also listed under a language code, as it is here.

    Common mistakes it catches

    • Relative or http URLs, such as /de/preise.
    • Three-letter or numeric codes, such as eng or es-419. Google says es-419 is not supported.
    • One code, two URLs within the same group.
    • A group with one language, where there is nothing to point at.

    It does not catch a region code that is well formed but wrong. Google says reserved codes such as UK or EU have no effect, and the right code for the United Kingdom is GB. It also rejects script subtags such as zh-Hant, which Google does support, so add those by hand.

    Sources

    1. 1.Tell Google about localized versions of your page - Google Search CentralPrimary
    2. 2.Sitemaps XML format - sitemaps.org

    Common questions

    Should I use hreflang in the sitemap or in the page head?

    Either. Google says HTML tags, HTTP headers and sitemaps are equivalent, and that using more than one brings no benefit in Search while making the setup harder to manage.

    Why does every url entry repeat the same links?

    Google's sitemap rules say each url element must list every alternate version of the page, including itself. Three versions give three url entries with three identical xhtml:link children each.

    Do the xhtml:link lines count towards the 50,000 URL limit?

    No. Google's localized versions page says child elements do not count towards the URL limit for sitemaps. The limit itself comes from sitemaps.org, which also caps a file at 50MB uncompressed.

    Are lowercase region codes wrong?

    No. Google says the hreflang value is case-insensitive. The generator still writes the region in uppercase, such as fr-CA, which follows the ISO 3166-1 Alpha 2 convention.

    Does the generator check that my URLs work?

    No. It never fetches anything. It checks code format, that each URL is fully qualified https, and that no code points at two URLs within a group.