First CHAppsWeb apps

First CH Apps / Sitemap XML Validator & Tester

Sitemap XML Validator & Tester

Test and verify a sitemap.xml online: we fetch it, validate the XML syntax and the sitemaps.org rules, and show the URL count, the lastmod spread and what a sitemap index contains.

A bare site URL works too (we try the Sitemap line in robots.txt, then /sitemap.xml). Gzip supported. Sitemap indexes are expanded one level deep, up to 10 children; the URL list shows the first 200 (counts cover everything we read, not just what is listed).

How it works and details

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.

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.

Real examples: common breakages and what this page shows

A raw & in a URL with a query string

<url><loc>https://example.com/search?q=shoes&page=2</loc></url>

The verdict is XML ERROR, with “line 3 — a raw &” and the fragment “&page=2”. Writing “&amp;page=2” fixes it. An XML parser stops at this point, so URLs after it never reach a search engine.

Two sitemaps concatenated into one file

</urlset>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">

“More than one root element” appears on the line of the second <urlset> (line 5 in our sample). It tends to happen when plugin outputs are merged; split them into two files behind a sitemap index instead.

The namespace written with https

<urlset xmlns="https://www.sitemaps.org/schemas/sitemap/0.9">

It still parses, so the verdict stays XML OK, but you get “The namespace is not the sitemaps.org 0.9 one”. A namespace is an identifier: the correct value is literally the http:// string.

A future lastmod and a time without a timezone

<lastmod>2027-01-01</lastmod>
<lastmod>2026-10-01T10:00:00</lastmod>

The first is flagged “lastmod is in the future” (warning), the second “When a time is present, a timezone (Z or +09:00) is required” (info). Future dates are the classic way to make a whole sitemap's lastmod untrusted.

Each outcome above is what this page's parser actually returned for that fragment (checked 2026-10-27).

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.

Kept on this device: to compare with your previous check, only the summary numbers (sitemap URL, URL total, share of URLs without lastmod, child sitemap count, syntax error count and the time) are saved in your browser's localStorage. They are never sent to our server. Up to 30 entries; clear them any time with “Clear this device's history” in the result.

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.