Package Information
Available Nodes
Documentation generatingβ¦
Documentation
πΊοΈ n8n Sitemap Validator
A custom n8n Community Node that loads your sitemap and smoke-tests every single URL inside it β before your users do.
Catch broken links, server errors, redirect loops, and timeouts in one pass, and turn the results into a ready-to-use report in your workflow.
β¨ The problem it solves
Sitemaps are your source of truth for what your site should be serving β and they rot silently. Pages get deleted, routes change, certificates expire, and a 404 hides behind a redirect. Your crawlers might even pick up URLs that should never have been published in the first place.
Most people find out from Google Search Console β weeks later. This node runs the check now, on demand, as part of your automation:
- π Schedule a weekly SEO health-check workflow.
- β οΈ Pipe the output into Slack / Email / n8n-formatted-notification the moment a broken link appears.
- π§Ή Run it before a site migration or relaunch to verify nothing breaks.
- π Store results in a database and track link-health over time.
Give it a sitemap URL, get back one item per URL with its status, redirect chain, and a rollup summary β nothing to configure, everything to filter on.
β What it catches
| Issue | How it's flagged |
|---|---|
| π΄ Broken links | Any URL returning 404 Not Found |
| π Server errors | 5xx responses (500, 502, 503, β¦) |
| π Client errors | Other 4xx responses (401, 403, 410, β¦) |
| π Redirect chains | Every hop recorded (from β to β status), so nothing is hidden |
| β Redirect loops | A chain that points back at itself β detected before it hangs |
| π Too many redirects | Chains exceeding your configured hop limit |
| β±οΈ Timeouts | URLs that don't answer within the configured window |
π
Missing lastmod |
Optional β flag URLs published without a <lastmod> element |
| π Network errors | DNS failures, TLS issues, connection refused, aborted requests |
Plus: it resolves sitemap indexes, nested sub-sitemaps, and gzip-compressed .xml.gz files automatically β no extra steps.
π¦ Installation
Prerequisites: Node.js β₯ 18.10
There are two ways to install: automatic (recommended β a few clicks) and manual (copy the package into the folder where n8n loads custom nodes). Either way, restart n8n afterwards so the node shows up in the editor.
π€ Automatic install
Method 1 β Install from inside n8n (recommended)
The easiest way; straight from the n8n UI:
- Open your n8n admin panel and go to Settings β Community Nodes.
- Click Install.
- Search for and install the package
n8n-nodes-sitemap-validator. - Restart n8n.
After the restart, the Sitemap Validator node appears in the editor under Transform.
Method 2 β Global install via npm
If you have shell access, install the package once on the system and it becomes available to every n8n instance on that machine:
npm install -g n8n-nodes-sitemap-validator
Then restart n8n. (Thanks to the n8n-community-node-package keyword in package.json, n8n picks it up automatically.)
ποΈ Manual install
If you want exact control over which version gets installed, or there's no UI option available:
Method 3 β Copy into the custom-nodes folder
Obtain the package (e.g. build it from the repo with npm pack ., or download it from npm), then place it in n8n's standard custom-nodes folder:
mkdir -p ~/.n8n/nodes
cp -R ./n8n-nodes-sitemap-validator ~/.n8n/nodes/
And restart n8n.
Method 4 β Upload the package in n8n
Package it as an archive file (npm pack . β .tgz), then:
- Go to Settings β Community Nodes.
- Click Install and choose Upload package.
- Select the archive, install it, and restart n8n.
β For the npm route, the
n8n-community-node-packagekeyword and then8nblock inpackage.jsonare already in place β just like official n8n community nodes.
π§ Usage in a workflow
Connect the node to any trigger and tell it what to check. The Input Format dropdown decides how the Sitemap URL / XML / URLs field is read β including from incoming data via an expression, e.g. ={{ $json.sitemapUrl }}:
| Input Format | What goes in the field |
|---|---|
| Sitemap URL (default) | The URL of a sitemap β index files, nested sub-sitemaps and .xml.gz are all handled |
| Raw XML | Paste a <urlset> or <sitemapindex> document directly |
| URL List | A newline- or comma-separated list of URLs to check directly |
| Option | Default | Description |
|---|---|---|
| Max URLs to Check | 0 (all) |
Check only the first N URLs β set 20 for a quick preview that returns fast |
| Concurrency | 20 |
Max URLs checked in parallel (1β100) |
| Timeout (ms) | 10000 |
Per-request timeout before a URL is flagged |
| Max Redirects | 5 |
Max hops to follow (also catches loops) |
| Request Method | HEAD |
HEAD is fast & cheap; switch to GET if a server misbehaves on HEAD |
| Check lastmod | on |
Flag URLs missing a <lastmod> element |
| User Agent | (default) | Custom User-Agent for sites sensitive to bot-blocking |
| Only Show Status | (all) | Keep only results whose status is one of the chosen values |
| Only Show Status Codes | (all) | Keep only results with these HTTP codes, e.g. 200 for healthy pages |
| Only Show URLs with Issues | off |
Keep only rows that have at least one issue (the broken ones) |
| Attach Excel Report | off |
Attach a real .xlsx report as binary data on the first output item |
| Excel File Name | sitemap-report.xlsx |
File name of the attached Excel report |
| Show Progress | on |
Report checked/total progress in the run messages and n8n logs while validating |
π‘ Tip: point it at a live sitemap index (e.g.
https://example.com/sitemap.xml) that links to sub-sitemaps β the node follows the whole tree and validates every URL across all of them.
βοΈ Filtering the output
The output fields (statusCode, status, isValid, issues, β¦) are fully filterable by n8n's built-in Filter node, but you can also filter inside this node with the Options β Only Show β¦ settings. For example:
- Only healthy pages β Only Show Status Codes:
200 - Only what broke β Only Show URLs with Issues:
on - Only redirects & server errors β Only Show Status:
redirect, server_error
The report/summary on every item always reflects the whole run, before filtering.
π Excel report
Turn Attach Excel Report on and the first output item carries a real .xlsx file as binary.data β no external library involved. The sheet ships with a frozen header row and column filters, so you can filter the report right inside Excel. Download it with a Write Binary File to Disk node, or email it with the Email / Send Email nodes:
Sitemap Validator βββΊ Write Binary File to Disk (binaryPropertyName: data, fileName: sitemap-report.xlsx)
π€ Output
The node emits one item per URL, each carrying the full validation result plus the sitemap-wide summary:
{
"url": "https://example.com/page",
"lastmod": "2024-01-01",
"hasLastmod": true,
"statusCode": 200,
"finalUrl": "https://example.com/page",
"redirectCount": 0,
"redirectChain": [],
"error": null,
"issues": [],
"isValid": true,
"status": "ok",
"summary": {
"sitemapUrl": "https://example.com/sitemap.xml",
"inputFormat": "url",
"totalUrls": 50,
"checkedUrls": 50,
"valid": 40,
"validCount": 40,
"issueCount": 10,
"successRate": 80,
"limited": false,
"limit": null,
"statusCodes": { "200": 39, "301": 5, "404": 3, "500": 1, "timeout": 2 },
"issues": {
"broken_link_404": 2,
"client_error_4xx": 0,
"server_error_5xx": 1,
"redirect": 3,
"redirect_loop": 0,
"max_redirects": 0,
"timeout": 1,
"missing_lastmod": 2,
"network_error": 0
},
"hasErrors": true,
"durationMs": 12345
}
}
The summary doubles as the final analysis report: successRate, validCount vs issueCount, the statusCodes histogram, the per-issue issues breakdown, and how long the run took (durationMs). When Max URLs to Check trimmed the run, limited is true and limit holds the number that was checked β the summary then reflects only what was actually validated.
status values
ok Β· broken Β· client_error Β· server_error Β· redirect Β· timeout Β· missing_lastmod Β· error Β· redirect_loop Β· max_redirects
issues (a URL can carry several)
broken_link_404 Β· client_error_4xx Β· server_error_5xx Β· redirect Β· redirect_loop Β· max_redirects Β· timeout Β· missing_lastmod Β· network_error
Handy expressions for downstream nodes
- Only broken links:
={{ $json.issues.includes('broken_link_404') }} - Everything unhealthy:
={{ !$json.isValid }} - Abort the run if anything is wrong:
={{ $json.summary.hasErrors }}
π§ͺ Testing
npm test
Spins up a local HTTP fixture server, loads a nested sitemap index + a gzip sitemap, and asserts that every issue type is detected β including redirect loops and redirect chains that exceed the hop limit.
π§ Development
npm run build # compile TypeScript once
npm run build:watch # recompile continuously while you hack
npm run lint # type-check only (no output files written)
npm test # build + integration tests + node smoke test
Architecture notes:
- Manual redirect handling (
redirect: 'manual') instead of auto-following β so the entire chain is recorded and loops are detectable. AbortSignal.timeout()per request for precise timeout detection.- Fixed-size worker pool (
mapWithConcurrency) keeps parallel requests under control and preserves input order. - Gzip detected by magic bytes (
0x1f 0x8b), so it works even without aContent-Encodingheader.
π€ Contributing
Found a bug, or have an idea? Feel free to open an issue or a pull request. Keep it small, test it, and make sure npm test passes.
π License
MIT Β© Mehrdad Ashtari
πΌ Need a custom n8n workflow?
Need a custom n8n workflow?
Get professional n8n development & automation support at