How to convert a json url list to an xml sitemap
- Step 1Shape the JSON as a urlset — Build a top-level object with a
urlarray. Each entry is an object with alockey (your absolute URL) and optionallastmod,changefreq,prioritykeys. Set the Root element option tourlset. - Step 2Add the sitemaps.org namespace — The tool won't add the namespace for you. Include it on the wrapper: make the object
{ "@xmlns": "http://www.sitemaps.org/schemas/sitemap/0.9", "url": [ ... ] }. The@xmlnskey serializes as thexmlnsattribute on<urlset>. - Step 3Make sure loc values are already absolute HTTPS — The converter does not validate URLs. Confirm every
locis a fullhttps://example.com/pathbefore converting — relative paths or bare slugs will pass straight through and Search Console will reject the sitemap. - Step 4Confirm lastmod is already in W3C date form — Dates pass through verbatim — there is no ISO→
YYYY-MM-DDnormalization. Ensurelastmodis already2026-06-01or a full W3C datetime. If yours are ISO timestamps, normalize them upstream first. - Step 5Choose indent and convert — Pick 2 spaces for a readable sitemap or Minified to reduce file size. Keep XML declaration on. Click Convert to XML, then Download — rename the file to
sitemap.xml. - Step 6Check the count, then submit — The tool does not warn at 50,000 URLs. Count your entries yourself; if you exceed 50,000 URLs or 50 MB, split into multiple sitemaps and create a sitemap index. Upload
sitemap.xmlto your site root and submit the full URL in Google Search Console.
JSON entry → sitemap XML
How each sitemap field maps. Root element option set to urlset. The converter copies values verbatim — it does not validate or reformat them.
| JSON | XML | Tool behaviour |
|---|---|---|
{ "url": [ { "loc": "https://x/a" } ] } | <urlset><url><loc>https://x/a</loc></url></urlset> | url array repeats as <url> elements |
"lastmod": "2026-06-01" | <lastmod>2026-06-01</lastmod> | Passed through verbatim — no date normalization |
"loc": "https://x/?a=1&b=2" | <loc>https://x/?a=1&b=2</loc> | & escaped to & (keeps query strings valid) |
"loc": "/about" (relative) | <loc>/about</loc> | Passed through — NOT flagged; Search Console will reject |
"priority": 0.8 | <priority>0.8</priority> | Number emitted unquoted, verbatim |
"@xmlns": "http://...0.9" | <urlset xmlns="http://...0.9"> | @-prefixed key becomes the namespace attribute |
What the converter does NOT do (do it yourself)
These are common sitemap requirements the structural converter leaves to you. Older descriptions claiming it validates or warns are inaccurate.
| Requirement | Converter? | Where to handle it |
|---|---|---|
Reject relative / non-HTTPS loc | No | Validate loc values in your data pipeline before converting |
Normalize lastmod to W3C date | No | Format dates upstream; values pass through verbatim |
| Warn at 50,000 URLs / 50 MB | No | Count entries yourself; split + build a sitemap index |
Add sitemaps.org xmlns | Only if you add @xmlns | Include @xmlns on the urlset object |
Escape & in URLs | Yes | Automatic — & → & |
Cookbook
Real JSON URL lists and the exact XML the converter produces. Set root = urlset, nest a url array, and add @xmlns for the namespace.
Minimal sitemap with namespace
ExampleAdd the sitemaps.org namespace via @xmlns on the wrapper object and nest a url array. Each entry's loc is required.
Input JSON:
{
"@xmlns": "http://www.sitemaps.org/schemas/sitemap/0.9",
"url": [
{ "loc": "https://example.com/" },
{ "loc": "https://example.com/about" }
]
}
Options: Root element = urlset, indent = 2
Output XML:
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>https://example.com/</loc>
</url>
<url>
<loc>https://example.com/about</loc>
</url>
</urlset>Full entries with lastmod, changefreq, priority
ExampleOptional fields map to their matching elements. Values are copied verbatim, so they must already be in the right format.
Input JSON:
{ "url": [
{ "loc": "https://example.com/blog",
"lastmod": "2026-06-01",
"changefreq": "daily",
"priority": 0.8 }
] }
Options: Root element = urlset
Output XML:
<?xml version="1.0" encoding="UTF-8"?>
<urlset>
<url>
<loc>https://example.com/blog</loc>
<lastmod>2026-06-01</lastmod>
<changefreq>daily</changefreq>
<priority>0.8</priority>
</url>
</urlset>Query-string URLs stay valid
ExampleAmpersands in tracking parameters are escaped automatically, which is what keeps the sitemap well-formed and parseable.
Input JSON:
{ "url": [ { "loc": "https://example.com/p?ref=a&id=2" } ] }
Options: Root element = urlset
Output XML:
<?xml version="1.0" encoding="UTF-8"?>
<urlset>
<url>
<loc>https://example.com/p?ref=a&id=2</loc>
</url>
</urlset>Building a sitemap index by hand
ExampleThere's no auto-split. For more than 50,000 URLs, split your data into chunks, convert each to a sitemap, then build the index with a different root and a sitemap array.
Input JSON (index):
{
"@xmlns": "http://www.sitemaps.org/schemas/sitemap/0.9",
"sitemap": [
{ "loc": "https://example.com/sitemap-1.xml" },
{ "loc": "https://example.com/sitemap-2.xml" }
]
}
Options: Root element = sitemapindex
Output XML:
<?xml version="1.0" encoding="UTF-8"?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<sitemap>
<loc>https://example.com/sitemap-1.xml</loc>
</sitemap>
<sitemap>
<loc>https://example.com/sitemap-2.xml</loc>
</sitemap>
</sitemapindex>Pitfall: relative loc passes through unflagged
ExampleThe converter does not validate URLs. A relative loc is copied verbatim and Search Console rejects the whole sitemap. Fix the data, not the converter.
Input JSON:
{ "url": [ { "loc": "/about" }, { "loc": "https://example.com/x" } ] }
Output XML (the /about entry is invalid for a sitemap):
<?xml version="1.0" encoding="UTF-8"?>
<urlset>
<url><loc>/about</loc></url>
<url><loc>https://example.com/x</loc></url>
</urlset>
Fix at source: make every loc an absolute https:// URL.Errors and edge cases
Real errors and silent failures sourced from each platform's own documentation. Match the wording to the row, fix what the row says to fix.
Relative or non-HTTPS loc values
Not validatedThe converter does not check that loc is an absolute HTTPS URL — older descriptions claiming it 'validates and flags relative paths' are wrong. A /about or http:// value passes through verbatim and Google Search Console rejects the sitemap. Validate loc values in your data pipeline before converting.
lastmod given as an ISO timestamp
Not normalizedDates are copied verbatim; there is no ISO-8601 → YYYY-MM-DD conversion. A value like 2026-06-01T14:30:00Z is emitted as-is. The sitemap spec accepts full W3C datetimes, so that's valid — but if you need date-only lastmod, format it upstream.
More than 50,000 URLs
No warningThe tool does not count URLs or warn at Google's 50,000-URL / 50 MB per-file limit. It will happily emit a single oversized sitemap. Count entries yourself, split into multiple files of 50,000 or fewer, convert each, and reference them from a sitemapindex document (see the cookbook).
Missing namespace declaration
Rejected by validatorsIf you don't include @xmlns, the output has a bare <urlset> with no namespace, which strict sitemap validators reject. Add "@xmlns": "http://www.sitemaps.org/schemas/sitemap/0.9" as the first key on the wrapper object so it serializes as the required xmlns attribute.
Top-level array instead of a urlset object
Wrong shapeIf you feed a bare top-level array of URL objects, the converter wraps it as <urlset><item>...</item></urlset> using the Array-item element name (default item), not <url>. Either set the Array-item element to url, or wrap your array in a { "url": [...] } object so the key drives the element name.
Ampersand in a URL
Escaped (correct)Unescaped & in a query string would make the XML malformed. The converter escapes it to & automatically, which is the correct sitemap form. Do not double-escape upstream — if your data already contains &, it will be escaped again to &amp;.
Invalid JSON pasted
Parse errorInput runs through JSON.parse; a trailing comma or unquoted key throws and nothing is generated. Repair with json-format-fixer or prettify with json-prettifier to spot the error.
Very large URL list over the free limit
Blocked (Pro)JSON to XML is Pro. The free tier caps the input file at 2 MB; Pro at 100 MB. A 50,000-URL sitemap can exceed 2 MB of JSON, so large sites need Pro. Conversion still runs locally in your browser.
Frequently asked questions
How do I get repeated <url> elements?
Nest a url array inside the wrapper object: { "url": [ {...}, {...} ] }. Because an array inside an object repeats under its own key, each element becomes a <url>. Set the Root element option to urlset so the whole thing is wrapped correctly.
Does the tool add the sitemaps.org namespace?
No — you add it. Include "@xmlns": "http://www.sitemaps.org/schemas/sitemap/0.9" as a key on the urlset object. The @ attribute prefix turns it into the xmlns attribute on <urlset>. Without it, strict validators reject the sitemap.
Will it validate that my URLs are absolute and HTTPS?
No. The converter does not validate loc values — relative paths, http://, and bare slugs all pass through verbatim. Search Console will then reject the sitemap. Validate URLs in your data before converting; this is a structural mapper, not a sitemap linter.
Are lastmod dates normalized to YYYY-MM-DD?
No. Dates are copied exactly as they appear in the JSON. The sitemap spec accepts both date-only and full W3C datetime forms, so an ISO timestamp is technically valid, but if you specifically want YYYY-MM-DD, format it upstream first.
What happens at Google's 50,000-URL limit?
Nothing automatic — there's no count or warning. Split your data into chunks of 50,000 URLs (and under 50 MB) yourself, convert each chunk to its own sitemap, then build a sitemapindex document referencing them (set the root to sitemapindex and use a sitemap array). The cookbook shows the index shape.
Are ampersands in tracking URLs handled?
Yes — a literal & in a loc is escaped to &, which keeps the XML well-formed. Don't pre-escape in your JSON, or you'll get &amp; from double-escaping. Other special characters (<, >, ", ') are escaped too.
Do changefreq and priority affect Google's crawling?
Google officially ignores both changefreq and priority and schedules crawling from its own signals. Including them is harmless and Bing still reads changefreq. That's about Google's behaviour, not the converter — it emits whatever fields you put in the JSON.
I fed a bare array and got <item> not <url>. Why?
A top-level array uses the Array item element name (default item). Either change that option to url, or wrap your array in { "url": [...] } so the JSON key drives the element name. The object form also lets you add @xmlns.
Should I minify the sitemap?
You can — pick Minified to drop indentation and shave bytes, which helps stay under the 50 MB per-file limit on large sites. Crawlers parse minified and pretty XML identically. For human review, use 2-space indent instead.
Will my staging URLs be uploaded?
No. Conversion is fully client-side. Private staging and pre-launch URLs in your JSON never leave your machine until you choose to upload the generated sitemap.xml to your server. Only an anonymous run counter (no content) is recorded when signed in.
How large a URL list can I convert?
JSON to XML is Pro. Free tier caps the input at 2 MB of JSON; Pro at 100 MB. A 50,000-URL list often exceeds 2 MB, so large sitemaps need Pro. Everything is processed in the browser, so the real ceiling on huge files is browser memory.
How do I turn an XML sitemap back into JSON?
Use xml-to-json to parse sitemap.xml into JSON, with its removeNSPrefix option to strip the sitemaps namespace prefix. To extract just the loc values from a parsed sitemap, json-path-extractor can pull $.urlset.url[*].loc.
Privacy first
Conversion runs locally in your browser. No file is uploaded — only metadata counters are saved for signed-in dashboard stats.