Web and domain tooling

Sitemap URLs: every URL of a website from its XML sitemaps

Sitemap URL extractor: every URL a website lists in its XML sitemaps, up to 100 sites per run: sitemaps are found through robots.txt and the usual paths, sitemap indexes and gzip are followed, and each URL comes with its sitemap, last modification date, change frequency and priority. Pay per URL.

$0.50per 1,000 · URL listed

One sitemap URL delivered. Sites without a sitemap are never charged.

Call it from your code

curl
ACTOR=steadydata~sitemap-urls
URL="https://api.apify.com/v2/acts/$ACTOR/run-sync-get-dataset-items"

curl -X POST "$URL?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"sites": ["apify.com"], "maxUrlsPerSite": 5000}'
python
import os, requests

ACTOR = "steadydata~sitemap-urls"
URL = f"https://api.apify.com/v2/acts/{ACTOR}/run-sync-get-dataset-items"

rows = requests.post(
    URL,
    params={"token": os.environ["APIFY_TOKEN"]},
    json={'sites': ['apify.com'], 'maxUrlsPerSite': 5000},
    timeout=900,
).json()

# every row carries a status; failures are records, not exceptions
ok = [r for r in rows if r.get("status") == "ok"]
print(len(ok), "rows delivered")
javascript
const ACTOR = "steadydata~sitemap-urls";
const url =
  `https://api.apify.com/v2/acts/${ACTOR}/run-sync-get-dataset-items` +
  `?token=${process.env.APIFY_TOKEN}`;

const rows = await fetch(url, {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({"sites": ["apify.com"], "maxUrlsPerSite": 5000}),
}).then((r) => r.json());

// one object per delivered row, same shape every time
console.log(rows.filter((r) => r.status === "ok").length, "rows");

Use it in an agent

Point an MCP client at Apify's hosted server with this dataset in the tools list, or run our own server locally.

mcp url
https://mcp.apify.com?tools=steadydata/sitemap-urls

# the tool arrives in your agent as steadydata--sitemap-urls

Input

FieldTypeNameWhat it does
sites
required
array of stringSites or sitemap URLsOne per row, up to 100: a domain (example.com), a site URL, or a sitemap URL (https://example.com/sitemap.xml).
maxUrlsPerSiteintegerMax URLs per siteCost ceiling per site, in sitemap order.

What you get back

output schema, one object per delivered row
{
  "site": string | null,
  "sitemapUrl": string | null,
  "url": string | null,
  "lastmod": string | null,
  "changefreq": string | null,
  "priority": number | null,
  "imageCount": integer | null,
  "status": string | null,
  "input": string | null,
  "errorCode": string | null,
  "error": string | null
}
FieldTypeWhen it is filled
sitestring, null
sitemapUrlstring, null
urlstring, null
lastmodstring, nullFilled when the sitemap publishes a last-modified date for the URL.
changefreqstring, null
prioritynumber, null
imageCountinteger, null
statusstring, nullEither 'ok' or 'error'. An error row carries errorCode and error, and leaves the data fields empty; it is never charged.
inputstring, nullThe input this row was built from, so a row can always be traced back.
errorCodestring, nullFilled on an error row only; a delivered row leaves it empty.
errorstring, nullFilled on an error row only; a delivered row leaves it empty.

Related datasets

Already using this one? Ratings are the first thing other buyers look at, and this dataset has none yet. If it does a job for you, a rating on its Apify page is the one thing that helps. It takes a minute and it is the only thing we ask for.

Open the Apify page