Paste the URLs you want indexed and get a valid sitemap.xml back, with ampersands escaped, duplicates dropped, relative paths rejected, and a sitemap index when the list goes past 50,000. The tool does not crawl your site, because a web page cannot fetch another origin. Export the URL list from your CMS, a database query or a crawler you run locally.
A date after a URL, separated by a space, becomes that URL's lastmod. The second /pricing is a duplicate, so the tool drops it. It also escapes the & in the query string, because one raw ampersand makes the whole file invalid XML.
https://example.com/
https://example.com/pricing
https://example.com/blog/tags?name=css&page=2
https://example.com/blog/hello-world 2026-08-14
https://example.com/pricing <?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/pricing</loc>
</url>
<url>
<loc>https://example.com/blog/tags?name=css&page=2</loc>
</url>
<url>
<loc>https://example.com/blog/hello-world</loc>
<lastmod>2026-08-14</lastmod>
</url>
</urlset> Required. It must be an absolute URL on the same host as the sitemap, unless you have verified both properties in Search Console. List the canonical version of each URL, not one that redirects.
Leave lastmod out unless the dates are real. Google uses it only on sites where it has proven accurate. Stamping every URL with today's date on every build teaches Google to ignore the field for your site.
Google ignores it and says so in its documentation. Bing treats it as a weak hint at most. The option is here because the sitemap protocol defines it, and it defaults to Omit.
Google ignores this too. Priority only ever ranked your pages against each other, so setting every URL to 1.0 changes nothing.
One sitemap file may hold at most 50,000 URLs and 50 MB uncompressed. Over either limit, this tool writes sitemap-1.xml, sitemap-2.xml and so on, plus a sitemap-index.xml that lists them, and Download gives you a zip of the set. The index builds each file's address from the origin of your URLs, so upload the files to the site root, or edit the loc lines if they live elsewhere.
<?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>
<lastmod>2026-09-30</lastmod>
</sitemap>
<sitemap>
<loc>https://example.com/sitemap-2.xml</loc>
<lastmod>2026-09-30</lastmod>
</sitemap>
</sitemapindex> Submit only the index. In Search Console, submit sitemap-index.xml instead of the individual files, and add one Sitemap: line for it to robots.txt.
import { writeFileSync } from "node:fs";
const xmlEscape = (s) => s
.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">")
.replace(/"/g, """).replace(/'/g, "'");
const pages = [
{ loc: "https://example.com/", lastmod: "2026-09-01" },
{ loc: "https://example.com/blog?tag=css&page=2" },
];
const body = pages.map((p) =>
" <url>\n <loc>" + xmlEscape(new URL(p.loc).href) + "</loc>\n" +
(p.lastmod ? " <lastmod>" + p.lastmod + "</lastmod>\n" : "") +
" </url>\n").join("");
writeFileSync("sitemap.xml",
'<?xml version="1.0" encoding="UTF-8"?>\n' +
'<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n' +
body + "</urlset>\n"); new URL(...).href percent-encodes spaces and non-ASCII characters, which the protocol requires, before the XML escaping step.
<?php
$pages = [
['loc' => 'https://example.com/', 'lastmod' => '2026-09-01'],
['loc' => 'https://example.com/blog?tag=css&page=2'],
];
$xml = new XMLWriter();
$xml->openURI('sitemap.xml');
$xml->startDocument('1.0', 'UTF-8');
$xml->setIndent(true);
$xml->startElement('urlset');
$xml->writeAttribute('xmlns', 'http://www.sitemaps.org/schemas/sitemap/0.9');
foreach ($pages as $p) {
$xml->startElement('url');
$xml->writeElement('loc', $p['loc']); // XMLWriter escapes & for you
if (!empty($p['lastmod'])) {
$xml->writeElement('lastmod', $p['lastmod']);
}
$xml->endElement();
}
$xml->endElement();
$xml->endDocument();
$xml->flush(); from xml.sax.saxutils import escape
pages = [
{"loc": "https://example.com/", "lastmod": "2026-09-01"},
{"loc": "https://example.com/blog?tag=css&page=2"},
]
def chunks(items, size=50_000):
for i in range(0, len(items), size):
yield items[i:i + size]
for n, part in enumerate(chunks(pages), start=1):
with open(f"sitemap-{n}.xml", "w", encoding="utf-8") as f:
f.write('<?xml version="1.0" encoding="UTF-8"?>\n')
f.write('<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n')
for p in part:
f.write(f" <url>\n <loc>{escape(p['loc'])}</loc>\n")
if p.get("lastmod"):
f.write(f" <lastmod>{p['lastmod']}</lastmod>\n")
f.write(" </url>\n")
f.write("</urlset>\n") saxutils.escape handles &, < and >, which is all that element text needs. Pass a dict as the second argument if you also want quotes escaped.
Google treats a sitemap as a hint. It uses the file to discover URLs and decide how often to recheck them. However, listing a URL does not guarantee it gets crawled or indexed, and leaving one out does not stop Google finding it through links. A sitemap helps most on large sites, new sites with few inbound links, and pages deep in the navigation.
The protocol also allows image, video and news extensions in their own namespaces. This tool does not generate them, so add them by hand only if you publish that kind of content. For ordinary pages, loc and an accurate lastmod are all the file needs.
This tool follows the specifications below. Read them when you need the exact normative wording, for example to settle an edge case between two implementations.
No. CORS stops a web page from reading pages on another origin, so no browser-only tool can crawl your site. Export the URL list from your CMS, a database query or a desktop crawler, and paste it in or use Upload.
50,000 URLs or 50 MB uncompressed, whichever comes first. Above that, split the list into several files and list them in a sitemap index. This tool does the split automatically and downloads the set as a zip.
No. Google's documentation says it ignores both. It does use lastmod, but only on sites where the dates have proven accurate, so leave lastmod out instead of setting every URL to today.
A sitemap is XML, and a bare & starts an entity reference. URLs with query strings must write it as & inside <loc>. The generator escapes &, <, >, quotes and apostrophes for you.
Upload it to the site root, add a Sitemap: line with its absolute URL to robots.txt, and submit it under Sitemaps in Google Search Console and Bing Webmaster Tools. A sitemap only covers URLs on its own host and below its own directory.
The protocol allows always, hourly, daily, weekly, monthly, yearly and never. always is for pages that change on every request, such as a live feed, and never for archived pages. Google ignores the field, and Bing treats it as a weak hint, so leave it on Omit unless a tool you use requires it. If you set it, be honest: a daily value on pages that never change teaches crawlers to ignore it.
Not here. The changefreq and priority selects apply one value to every URL in the list, which is why they default to Omit. priority only ever ranked your pages against each other, so a single value for all of them says nothing. Only lastmod can vary per URL, by writing the date after it on the same line. Edit the XML by hand if you need different values.
Point crawlers at the finished file with a Sitemap:
line from the robots.txt
generator. If some of the URLs moved, write the rules with the
redirect generator and list only
the new addresses. To pull a URL apart and check its query string,
use the URL parser.