Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Scan for outdated or missing drivers - takes under a minute3Clear out junk files and repair common Windows errorsYou can use Node.js and Playwright to fetch a sitemap, expand any sitemap indexes it references, and save a screenshot for each listed page URL. The script below records successes and failures separately so one broken page does not hide the rest of the run.
It captures URLs in the sitemap files it processes—not necessarily every page on the site. A sitemap is a submitted list, not proof of complete site coverage, and its entries are not a guarantee that pages are canonical, available, or permitted to crawl.
As an Amazon Associate I earn from qualifying purchases.
What the script does
The workflow starts with a sitemap URL. It fetches and parses the XML, distinguishes a regular sitemap from a sitemap index, follows index entries, removes duplicate locations, and filters page URLs to the original site’s origin by default. It then navigates to each accepted URL in a Playwright page and saves a screenshot using a stable filename. A JSONL log records the result for every URL.
The script uses viewport screenshots by default for more consistent image dimensions. Set FULL_PAGE=1 to capture the full scrollable document instead. Playwright’s screenshot API accepts a file path and a fullPage option; see the Page screenshot API and navigation API.
#1 Best Overall
- CRISP CLARITY: This 23.8″ Philips V line monitor delivers crisp Full HD 1920x1080 visuals. Enjoy movies, shows and videos with remarkable detail
- INCREDIBLE CONTRAST: The VA panel produces brighter whites and deeper blacks. You get true-to-life images and more gradients with 16.7 million colors
- THE PERFECT VIEW: The 178/178 degree extra wide viewing angle prevents the shifting of colors when viewed from an offset angle, so you always get consistent colors
- WORK SEAMLESSLY: This sleek monitor is virtually bezel-free on three sides, so the screen looks even bigger for the viewer. This minimalistic design also allows for seamless multi-monitor setups that enhance your workflow and boost productivity
- A BETTER READING EXPERIENCE: For busy office workers, EasyRead mode provides a more paper-like experience for when viewing lengthy documents
Check access and sitemap coverage first
Use this workflow only when you have permission and a legitimate reason to capture the pages. Inspect the site’s applicable crawl rules and avoid sending more requests than the site can reasonably handle. The Robots Exclusion Protocol is crawler guidance, not access authorization; a robots.txt file does not grant access to protected content. RFC 9309 also specifies how crawler rules are interpreted and addresses unavailable, unreachable, redirected, and cached robots.txt responses. See RFC 9309.
A sitemap may be named in robots.txt. Google documents this discovery route in its sitemap guidance; RFC 9309 says crawlers may interpret records such as Sitemap. This example accepts an explicit sitemap URL rather than treating robots.txt as permission to crawl.
The Sitemap Protocol allows up to 50,000 URLs and 50 MB per sitemap file, and up to 50,000 sitemap entries and 50 MB per sitemap index. These are format limits, not a promise that processing such a set will be quick or small. Larger jobs can take considerable time and storage, so the example uses a configurable, bounded number of workers. See the Sitemap Protocol.
Set up the project
-
Install a supported Node.js release for your environment. The documentation consulted for this guide does not establish a minimum Node.js version; check the current Playwright setup documentation before choosing one.
-
Create a directory, initialize a project, and install Playwright plus an XML parser:
mkdir sitemap-shots && cd sitemap-shots
npm init -y
npm install playwright fast-xml-parser
npx playwright install chromiumRank #2
Philips 22 Inch Computer Monitor FHD 100Hz VA VESA Flicker-Free, 221V8LB- CRISP CLARITY: This 22 inch class (21.5″ viewable) Philips V line monitor delivers crisp Full HD 1920x1080 visuals. Enjoy movies, shows and videos with remarkable detail
- 100HZ FAST REFRESH RATE: 100Hz brings your favorite movies and video games to life. Stream, binge, and play effortlessly
- SMOOTH ACTION WITH ADAPTIVE-SYNC: Adaptive-Sync technology ensures fluid action sequences and rapid response time. Every frame will be rendered smoothly with crystal clarity and without stutter
- INCREDIBLE CONTRAST: The VA panel produces brighter whites and deeper blacks. You get true-to-life images and more gradients with 16.7 million colors
- THE PERFECT VIEW: The 178/178 degree extra wide viewing angle prevents the shifting of colors when viewed from an offset angle, so you always get consistent colors
-
Save the following code as
screenshot-sitemap.mjs. It uses ES modules and Chromium, keeps concurrency low by default, and writes images toscreenshots/.What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Runnable Node.js script
import fs from 'node:fs/promises';
import path from 'node:path';
import crypto from 'node:crypto';
import { chromium } from 'playwright';
import { XMLParser } from 'fast-xml-parser';
const sitemapUrl = process.env.SITEMAP_URL;
if (!sitemapUrl) {
console.error('Set SITEMAP_URL to a sitemap or sitemap-index URL.');
process.exit(1);
}
const outputDir = process.env.OUTPUT_DIR ?? 'screenshots';
const concurrency = Math.max(1, Number.parseInt(process.env.CONCURRENCY ?? '2', 10) || 2);
const fullPage = process.env.FULL_PAGE === '1';
const navigationTimeoutMs = Math.max(1000, Number.parseInt(process.env.TIMEOUT_MS ?? '30000', 10) || 30000);
const allowExternal = process.env.ALLOW_EXTERNAL === '1';
const parser = new XMLParser({
ignoreAttributes: false,
attributeNamePrefix: '@_',
removeNSPrefix: true,
trimValues: true,
});
function asArray(value) {
if (value == null) return [];
return Array.isArray(value) ? value : [value];
}
function getLocs(entries) {
return asArray(entries).map((entry) => {
const loc = typeof entry === 'string' ? entry : entry?.loc;
return typeof loc === 'string' ? loc.trim() : '';
}).filter(Boolean);
}
function safeName(url) {
const parsed = new URL(url);
const readable = `${parsed.hostname}${parsed.pathname}`
.replace(/[^a-zA-Z0-9._-]+/g, '_')
.replace(/^_+|_+$/g, '')
.slice(0, 120) || 'page';
const hash = crypto.createHash('sha256').update(url).digest('hex').slice(0, 12);
return `${readable}-${hash}.png`;
}
async function fetchXml(url) {
const response = await fetch(url, { redirect: 'follow' });
if (!response.ok) throw new Error(`Sitemap fetch returned HTTP ${response.status}: ${url}`);
return parser.parse(await response.text());
}
async function collectSitemap(sitemap, allowedOrigin, seenSitemaps, pageUrls) {
const normalized = new URL(sitemap).href;
if (seenSitemaps.has(normalized)) return;
seenSitemaps.add(normalized);
const xml = await fetchXml(normalized);
if (xml.sitemapindex) {
const childSitemaps = getLocs(xml.sitemapindex.sitemap);
for (const child of childSitemaps) {
await collectSitemap(new URL(child, normalized).href, allowedOrigin, seenSitemaps, pageUrls);
}
return;
}
if (xml.urlset) {
for (const loc of getLocs(xml.urlset.url)) {
let page;
try {
page = new URL(loc, normalized);
} catch {
continue;
}
if (!['http:', 'https:'].includes(page.protocol)) continue;
if (!allowExternal && page.origin !== allowedOrigin) continue;
pageUrls.add(page.href);
}
return;
}
throw new Error(`Unrecognized sitemap XML root in ${normalized}`);
}
async function main() {
const start = new URL(sitemapUrl);
const pageUrls = new Set();
const seenSitemaps = new Set();
await collectSitemap(start.href, start.origin, seenSitemaps, pageUrls);
const urls = [...pageUrls].sort();
await fs.mkdir(outputDir, { recursive: true });
const logPath = path.join(outputDir, 'results.jsonl');
await fs.writeFile(logPath, '');
if (urls.length === 0) {
console.error('No in-scope page URLs found. Check the sitemap URL and ALLOW_EXTERNAL setting.');
return;
}
const browser = await chromium.launch({ headless: true });
let next = 0;
let failures = 0;
async function worker() {
const page = await browser.newPage({ viewport: { width: 1365, height: 900 } });
page.setDefaultNavigationTimeout(navigationTimeoutMs);
try {
while (true) {
const index = next++;
if (index >= urls.length) break;
const url = urls[index];
const file = path.join(outputDir, safeName(url));
try {
const response = await page.goto(url, { waitUntil: 'load' });
if (!response) throw new Error('Navigation returned no main-resource response');
await page.screenshot({ path: file, fullPage });
await fs.appendFile(logPath, `${JSON.stringify({ url, status: 'ok', httpStatus: response.status(), file })}n`);
console.log(`OK ${url} -> ${file}`);
} catch (error) {
failures++;
await fs.appendFile(logPath, `${JSON.stringify({ url, status: 'error', error: String(error) })}n`);
console.error(`FAIL ${url}: ${String(error)}`);
}
}
} finally {
await page.close();
}
}
try {
await Promise.all(Array.from({ length: Math.min(concurrency, urls.length) }, () => worker()));
} finally {
await browser.close();
}
console.log(`Processed ${urls.length} unique in-scope URLs; ${failures} failed. Results: ${logPath}`);
if (failures > 0) process.exitCode = 2;
}
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});
Run it and choose the capture behavior
Pass the sitemap URL through an environment variable:
SITEMAP_URL="https://example.com/sitemap.xml" node screenshot-sitemap.mjs
For a sitemap index, use the index URL; the script follows the referenced sitemap files and gathers their page entries. It tracks visited sitemap URLs to avoid fetching the same child more than once. The output filename combines a readable hostname and path with a hash of the full URL, which prevents collisions when distinct URLs share a path but differ in query string or other components.
| Setting | Default | Effect |
|---|---|---|
SITEMAP_URL |
Required | URL of a sitemap or sitemap index to process. |
OUTPUT_DIR |
screenshots |
Directory for PNG files and results.jsonl. |
CONCURRENCY |
2 |
Maximum number of pages navigating and capturing at the same time. Keep it modest and adjust to the site and job. |
FULL_PAGE |
Off | Set to 1 to save the full scrollable page instead of the viewport. |
TIMEOUT_MS |
30000 |
Navigation timeout in milliseconds. Increase it for slow pages; this does not make a page load successfully. |
ALLOW_EXTERNAL |
Off | Set to 1 to include sitemap page URLs whose origin differs from the sitemap URL’s origin. |
Example with options:
SITEMAP_URL="https://example.com/sitemap.xml" CONCURRENCY=1 FULL_PAGE=1 OUTPUT_DIR=full-shots node screenshot-sitemap.mjs
Viewport or full-page screenshots?
A viewport capture gives each page a fixed visible-screen frame, which is useful for quick site-wide review and more directly comparable image dimensions. A full-page capture includes the scrollable document, but long pages can generate very tall images and larger files. Pages with lazy-loaded media or dynamic content may not have everything ready merely because navigation reached the load event; inspect captures and add page-specific waits or scrolling if your target site requires them.
Rank #3
- Clear visuals. Fluid motion: A 144Hz refresh rate and 1ms MPRT deliver smooth, tear‑free motion across work, gaming, and streaming for clearer, more fluid viewing.
- Eye comfort: TÜV Rheinland 3‑star* certification reduces harmful blue light while preserving stunning color quality without compromise. *TÜV Rheinland 3-star eye comfort certification.
- Wide viewing angle: Get consistent views across a wide 178° /178° viewing angle.
- In-Plane Switching (IPS): See excellent color accuracy and consistency across wide viewing angles with In-plane Switching (IPS) technology.
- Ultra-thin bezels: Maximize your viewing experience with thin bezels.
The sample waits for the browser’s load event, then captures. A page that keeps loading network requests indefinitely can make stricter network-idle waits unreliable, so use a selector wait or a short delay only when you know what condition indicates readiness. Playwright’s screenshot API also supports format, quality, scale, clipping, and style controls, documented in the screenshot options.
Failures, logs, and recovery
Each URL produces one JSON object per line in results.jsonl. Successful rows include the response status and output path; failed rows include the error string. The process continues after individual navigation or screenshot errors and exits with status 2 if any page failed. A sitemap fetch or parse failure stops the run, because the URL list may be incomplete.
-
HTTP error fetching a sitemap: confirm the URL, redirects, and whether the server permits your request. The script treats non-success HTTP responses as fatal.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy. -
Unrecognized sitemap XML root: the parser expects a Sitemap Protocol
<urlset>or<sitemapindex>. Check that the URL is actually a sitemap rather than an HTML page or an unsupported feed. -
Navigation timeout: try a larger
TIMEOUT_MS, but verify that the page is not hanging or blocking automation before increasing it across a large run. -
Access denied, bot check, or CAPTCHA: do not attempt to bypass access controls. Stop or obtain authorization and an approved way to access the pages.
Rank #4
SaleSamsung 27" Essential S3 (S36GD) Series FHD 1800R Curved Computer Monitor | 100Hz, Game Mode, Advanced Eye Comfort, HDMI and D-sub Ports (LS27D366GANXZA)- CURVED FOR ENHANCED ENGAGEMENT: An immersive viewing experience with a curved monitor that wraps more closely around your field of vision; It creates a wider view, enhancing depth perception and minimizing peripheral distraction
- SMOOTH PERFORMANCE FOR SEAMLESS CONTENT: Stay in the action when playing games, watching videos, or working on creative projects; The 100Hz refresh rate reduces lag and motion blur so you don't miss a thing in fast-paced moments¹
- MORE GAMING POWER: Gain the edge with optimizable game settings; Color and image contrast can be adjusted to see scenes more vividly and spot enemies hiding in the dark; Game Mode adjusts any game to fill the screen so you can view every detail²
- KEEP IT EASY ON THE EYES: Care for your eyes and stay comfortable, even during long sessions; Advanced eye comfort technology certified by TÜV reduces eye strain by minimizing blue light and reducing irritating screen flicker²
- INCREASED VERSATILITY: Connect to more; Plug devices straight into your monitor for increased flexibility, making your computing environment even more convenient
-
Missing or unexpectedly incomplete images: the screenshot may have run before lazy content appeared. Use a site-specific readiness selector or deliberate scrolling and waiting, and review the result rather than assuming every page behaves alike.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy. -
No URLs found: verify that the sitemap contains URL entries and that they match the sitemap origin. Only set
ALLOW_EXTERNAL=1when including other origins is intended and authorized. -
Disk space or runtime grows too large: reduce the sitemap scope or process it in batches. A protocol size limit is not a practical resource recommendation.
Performance, reliability, and repeatable comparisons
Concurrency trades elapsed time against load placed on the site and local resource use. Start with the default of two workers, monitor the destination and machine, and lower it for sensitive or rate-limited sites. Each worker reuses one page for its URLs, while separate workers use separate pages in the same browser process.
For visual comparisons, keep the browser version, operating system, viewport, device scale, settings, and execution conditions stable. Playwright notes that “Browser rendering can vary based on the host OS, version, settings, hardware, power source (battery vs. power adapter), headless mode, and other factors.” See its visual comparisons guidance. This script does not claim pixel-identical results across machines or runs.
Recommended Free Tools
To avoid silently treating a partial run as complete, retain the JSONL file, inspect failures, and rerun only failed URLs after checking their cause. If repeatability matters, pin the browser and dependencies in your project’s lockfile and run in a consistent environment. Do not infer that every sitemap entry is crawlable just because it appears in XML.
Best Value
- 【INTEGRATED SPEAKERS】Whether you're at work or in the midst of an intense gaming session, our built-in speakers provide rich and seamless audio, all while keeping your desk clutter-free.
- 【EASY ON THE EYES】 Protect your eyes and enhance your comfort with Blue-Light Shift technology. This feature reduces harmful blue light emissions from your screen, helping to alleviate eye strain during long hours of use and promoting healthier viewing habits.
- 【WIDEN YOUR PERSPECTIVE】Our sleek minimal bezel design ensures undivided attention. The nearly bezel-free display seamlessly connects in a dual monitor arrangement, delivering an unobstructed view that lets you focus on more at once, completely distraction-free.
Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server for developers. A single GET request returns an image or PDF, and its API can handle the browser setup and capture job:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com -o shot.webp
See the ScreenshotNeo API documentation for request options. ScreenshotNeo removes cookie/consent banners, newsletter popups, and chat widgets before capture; bot checks, blank pages, and failed loads are not billed. Its MCP server lets AI agents take screenshots, and the free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000.
Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minutePC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Sign up free for ScreenshotNeo.
Frequently Asked Questions
Does a sitemap include every page on a site?
No. It lists URLs supplied in that sitemap; it does not establish complete coverage of all reachable pages.
Can I capture URLs on another domain listed in the sitemap?
The sample excludes them by default. Set ALLOW_EXTERNAL=1 only when cross-origin capture is intentional and authorized.
Why does the script save PNG files when Playwright can save other formats?
PNG is the explicit format chosen by the sample’s filename extension. Playwright’s screenshot API also supports JPEG and other documented options.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.
Free tools Windows power users keep installed
One-click scans. No signup required.




