Free tools Windows power users keep installed
One-click scans. No signup required.
Use Playwright’s page.pdf() to save each URL as a paginated PDF; use page.screenshot({ fullPage: true }) when you need a single tall image instead. The script below processes a URL list sequentially, gives each output a deterministic filename, and closes each page before continuing. PDF export uses print CSS by default, so switch to screen media explicitly if that is the layout you need.
Choose PDF or a full-page screenshot
Playwright has separate methods for these outputs. page.pdf() generates a PDF with paper dimensions and page breaks. page.screenshot({ fullPage: true }) captures the page’s scrollable area as one raster image, not a paginated document. Use page.screenshot() without fullPage for a viewport capture, or screenshot options to capture an element.
As an Amazon Associate I earn from qualifying purchases.
PDF generation is supported in Chromium according to the Playwright Page API. Check the installed Playwright and browser versions when choosing your runtime.
Recommended Free Tools
Install Playwright and prepare a URL list
The following Node.js example uses Playwright’s Chromium browser. Install the package and its browser before running the script:
#1 Best Overall
npm install playwrightnpx playwright install chromium- Save the script below as
capture-pdfs.mjs, then run it withnode capture-pdfs.mjs.
The example creates one PDF per URL in the current directory. Its filenames combine an index and sanitized hostname, so repeated hostnames still get separate files. Replace the sample URL list with your own. This is an implementation pattern based on the documented APIs, not a tested script; readiness checks and error handling may need adjustment for the sites you capture.
Capture multiple URLs as separate PDFs
import { chromium } from 'playwright';
const urls = [
'https://example.com/',
'https://playwright.dev/',
];
const browser = await chromium.launch();
const context = await browser.newContext();
try {
for (const [index, url] of urls.entries()) {
const page = await context.newPage();
try {
await page.goto(url, { waitUntil: 'load' });
// Add a site-specific readiness condition where needed.
const hostname = new URL(url).hostname.replace(/[^a-z0-9.-]/gi, '_');
const filename = `capture-${String(index + 1).padStart(3, '0')}-${hostname}.pdf`;
await page.pdf({
path: filename,
format: 'A4',
printBackground: true,
});
console.log(`Saved ${filename}`);
} catch (error) {
console.error(`Failed to capture ${url}:`, error);
} finally {
await page.close();
}
}
} finally {
await context.close();
await browser.close();
}
The loop is sequential, which keeps resource use predictable for a modest batch. A BrowserContext can host multiple pages, and context.pages() exposes the pages in that context. For higher throughput, use a bounded worker pool and measure resource use in the target environment; Playwright does not specify a universal safe concurrency limit.
Set PDF styling, paper size, and pagination
PDF output uses print CSS media by default. Websites may hide navigation, restyle text, or change layout for print. To use screen styling instead, call page.emulateMedia({ media: 'screen' }) before page.pdf().
Rank #2
await page.emulateMedia({ media: 'screen' });
await page.pdf({ path: 'screen-layout.pdf', format: 'A4', printBackground: true });
Relevant PDF controls include:
formatselects a paper format, such as'A4'. Alternatively, specify page width and height.marginsets page margins. CSS@pagerules may take precedence whenpreferCSSPageSizeis enabled.printBackground: trueincludes background graphics, which print output otherwise may omit.scaleadjusts the content scale.pageRangesselects pages to include.preferCSSPageSizelets a page’s CSS page size take precedence over the API’s paper dimensions.
For exact print colors, the page’s CSS can use -webkit-print-color-adjust. If you need a screen-style PDF, emulate screen media; the resulting document still has PDF page dimensions and pagination.
Capture a full-page image instead
When the deliverable should be an image rather than a paper document, use the screenshot API. This example saves the entire scrollable page as a PNG:
await page.screenshot({ path: 'full-page.png', fullPage: true });
Screenshot controls include output path, image type, quality where supported, scale, clipping, and animation handling. A full-page capture can be very tall; a PDF is usually a better fit when readers need page-sized output or printing.
Rank #3
Make batch captures more reliable
Wait for the content that matters
waitUntil: 'load' waits for the page load event, but that does not guarantee that client-rendered content, lazy-loaded images, or a particular component is ready. Add a site-specific condition, such as waiting for a known selector:
Do these 3 things before closing this tab:
1Fix the driver behind crashes, sound loss and screen glitches2Repair Windows errors before they cause bigger problems3Scan for outdated or missing drivers - takes under a minuteawait page.goto(url, { waitUntil: 'load' });
await page.locator('main article').waitFor({ state: 'visible' });
Use a selector that exists on the pages you capture. For lazy-loaded content, the page may need scrolling or other site-specific preparation before saving; the basic loop does not perform that work automatically.
Handle authentication and consent deliberately
Pages that require authentication need the appropriate context state, cookies, or credentials. Cookie banners can cover content or alter the page; decide whether to accept, reject, or preserve the banner for the purpose of your capture. Do not assume a generic readiness wait will handle either case.
Keep runs comparable
Rendering can vary with host operating system, browser version and settings, hardware, power source, and headless mode. For repeatable bulk work, keep the runtime and environment controlled, then inspect representative PDFs and images before relying on a large run.
Handle failures and diagnose unexpected output
- Navigation times out or fails: check the URL and network access, and determine whether the site is slow or unavailable. Add a timeout or retry policy appropriate to your workload rather than treating every failure as a successful capture.
- The PDF has print styling instead of the on-screen layout: this is the default. Call
page.emulateMedia({ media: 'screen' })before PDF generation if screen CSS is required. - Background colors or images are missing: set
printBackground: true; check the site’s print CSS if the result still differs. - Content or images are missing: wait for a site-specific selector or readiness condition. Check whether content is loaded only after scrolling or requires authentication.
- Output is clipped, scaled oddly, or split unexpectedly: review paper format or dimensions, margins, scale, page ranges, and CSS
@pagerules. TrypreferCSSPageSizewhen the site defines its own page dimensions. - The batch consumes too much memory or slows down: keep the sequential loop, close each page after capture, and avoid unbounded parallel work. If you add workers, measure resource use on the actual host.
- The PDF method is unavailable in the chosen runtime: verify that the installed browser is Chromium and check the installed Playwright/browser versions against the current Page API.
Use the CLI for one-off captures
Playwright’s CLI includes screenshot, screenshot --full-page, and pdf commands with optional filenames. The CLI is convenient for a single capture; a URL-driven script is more suitable when you need a repeatable batch, per-URL naming, and site-specific readiness logic.
Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server for developers. One GET request can return a PNG, JPEG, WebP, or PDF. Its capture flow accepts consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the page verdict and billing status in headers. AI agents can use its MCP server tools, including take_screenshot, get_page_info, and capture_pdf.
For a PDF capture, use the API’s PDF options as documented. This one-call example requests an image, adapting only the target URL as needed. See the ScreenshotNeo API documentation for output and PDF parameters.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
ScreenshotNeo is available at screenshotneo.com. The Free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 screenshots. Sign up for free.
Frequently Asked Questions
Can one Playwright PDF contain several URLs?
The example creates one PDF per URL. Combining separate pages into one PDF requires an additional document-assembly step; Playwright’s page PDF method exports the current page.
Can I inspect the pages currently open in a context?
Yes. Playwright’s BrowserContext API exposes them through context.pages().
Is there an official maximum number of URLs or workers for a batch?
The cited Playwright documentation establishes multiple-page support but does not state a universal batch-size or concurrency limit.
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.




