FIRST CHApps

First CH Apps / Sitemap XML Validator & Tester

Sitemap XML Validator & Tester

Enter a sitemap URL and we fetch it, check that it parses as XML, and show how many URLs it holds, how their lastmod dates are spread, and what a sitemap index points at (one level deep). Give us just a site URL and we find the sitemap from the Sitemap line in robots.txt.

Point straight at https://example.com/sitemap.xml, or give just https://example.com and we look at robots.txt first, then fall back to /sitemap.xml. Gzipped sitemaps (.xml.gz) work too.

Testing and verifying a sitemap

How to test a sitemap.xml

Paste the sitemap URL (or just the site URL) above and press Check. We fetch the file the way a crawler would and test it in order: the HTTP status and Content-Type, whether the XML is well-formed (errors come with line numbers), whether the root is <urlset> or <sitemapindex> with the sitemaps.org namespace, and then every entry — <loc> must be an absolute http/https URL on the same host and under 2,048 characters, lastmod must be valid W3C Datetime and not in the future, and one file may hold at most 50,000 URLs. For a sitemap index we also open the child sitemaps one level down.

Common reasons a sitemap fails validation

The most frequent is a raw & inside a URL with a query string — in XML it has to be written &amp;. Next come an HTML page served in place of the sitemap (a login, 404 or maintenance page), stray output such as a PHP warning printed before the XML declaration, a byte-order mark at the very start, a missing or wrong xmlns, and two sitemaps concatenated into one file so it has more than one root element. Each of these shows up as a warning with its line number.

What this test cannot verify

A clean result means the file itself is valid; it does not tell you whether Google has read it. To verify that, submit the sitemap in the Sitemaps report in Google Search Console, which shows whether Google could fetch the file and how many URLs it discovered. Valid XML also says nothing about the pages it lists — check that they return 200 with the bulk HTTP status checker below. And because we fetch from our own server, a firewall or bot protection that treats us differently from Googlebot can make our result differ from what Google sees.

Are the listed URLs actually alive?

Valid XML does not help if the URLs inside return 404. Paste them into the bulk HTTP status checker to see which ones still resolve.

Go to the Bulk HTTP Status Check →

Writing the robots.txt?

A `Sitemap:` line in robots.txt tells every crawler where your sitemap lives. The robots.txt generator on tools.first-ch.com builds the file from a form — entirely in your browser, nothing uploaded.

Go to the robots.txt Generator (tools.first-ch.com) →

SERVER PROCESSING — what we send and what we keep

Sent: only the URL you type. Our server (Cloudflare Workers) fetches that sitemap as a public page — plus /robots.txt when discovery is needed, and the child sitemaps of an index. A single check makes at most 40 outbound requests.

Stored: nothing. The check lives entirely inside one request and writes neither the URL nor the result to any database (no KV, no D1). It leaves memory when the request ends.

Returned: analysis only — counts, the lastmod spread, warnings with line numbers, and the first 200 extracted <loc> values. We never re-serve the fetched XML. We read at most 1MB per file and parse at most 600,000 characters per check, to stay inside the free-tier CPU limit.

Note: public GET only. URLs pointing at internal networks, localhost or private IPs are rejected, and sitemaps behind a login cannot be checked.

Use it as an API

POST /sitemap-check/api/check with JSON ({"url": "https://example.com/sitemap.xml"}) or a form body and you get the same result back as JSON.

sitemaps.org caps one file at 50,000 URLs and 50MB uncompressed. Beyond that, split the file behind a sitemap index — indexes may not be nested.

Google uses neither changefreq nor priority. It uses lastmod as a crawl-priority signal only when the value is maintained accurately, so stamping every URL with the generation time is counter-productive.

Being in a sitemap does not guarantee indexing, and being absent does not keep a URL out of the results. A sitemap helps discovery; it does not decide inclusion.