Both Puppeteer and Playwright generate PDFs with page.pdf(), and both use print CSS by default. Neither official documentation establishes a universal winner for speed, fidelity, reliability, or deployment. Choose according to the browser/runtime you already operate, then compare representative templates on the exact package versions and deployment environment you will ship.
What both libraries actually do
Puppeteer’s Page.pdf() and Playwright’s page.pdf() render a page with the print CSS media type. Both expose controls for paper dimensions, margins, page ranges, backgrounds, scaling, headers and footers, and CSS page-size preferences. The APIs return a PDF (Puppeteer can write directly to a path; Playwright returns a buffer and can also write to a path).
That overlap means the practical decision is usually about your browser automation stack and operational constraints, not a supposedly superior PDF engine. Browser channels, container images, serverless limits, concurrency, authentication flows and your own templates can change the result. Treat the comparison below as a decision framework, then run your own acceptance tests.
Minimal implementations
Puppeteer (Node.js)
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch();
try {
const page = await browser.newPage();
await page.goto('https://example.com', { waitUntil: 'networkidle2' });
await page.pdf({ path: 'document.pdf', format: 'A4', printBackground: true });
} finally {
await browser.close();
}
})();
Puppeteer’s PDF guide shows the same launch, navigation, page.pdf(), and close sequence. Its documentation says PDF generation waits for fonts by default. Confirm that behavior against the package version installed in your project; the current API reference retrieved for this comparison identifies Puppeteer 25.12.0.
#1 Best Overall
Playwright (Node.js)
const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch();
try {
const page = await browser.newPage();
await page.goto('https://example.com', { waitUntil: 'networkidle' });
await page.pdf({ path: 'document.pdf', format: 'A4', printBackground: true });
} finally {
await browser.close();
}
})();
Playwright’s API returns a buffer even when a path is supplied. The retrieved reference does not establish a font-wait default equivalent to Puppeteer’s statement, so make font readiness an explicit test in your pipeline rather than assuming the defaults match.
Print CSS versus screen appearance
Print media is intentional: styles inside @media print apply, and browsers may alter colors for printing. If the PDF should look like the on-screen page, emulate screen media before calling page.pdf().
Puppeteer
await page.emulateMediaType('screen');
await page.pdf({ path: 'screen-style.pdf', printBackground: true });
Playwright
await page.emulateMedia({ media: 'screen' });
await page.pdf({ path: 'screen-style.pdf', printBackground: true });
For exact colors, use CSS such as -webkit-print-color-adjust: exact where appropriate. Keep this choice in the template contract: print layouts often hide navigation and adapt column widths, while screen emulation preserves visual styling that may paginate poorly.
Page size and geometry
You can specify a named paper format such as A4 or Letter, provide explicit width and height, and define dimensions in CSS with @page. Conflicts are easy to miss: a paper format can cause content to be scaled to fit even when the stylesheet declares a different size.
Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Fix the driver behind crashes, sound loss and screen glitches3Repair Windows errors before they cause bigger problemsRank #2
- HTML CSS Design and Build Web Sites
- Comes with secure packaging
- It can be a gift option
Let CSS control the sheet
await page.pdf({
path: 'invoice.pdf',
preferCSSPageSize: true,
printBackground: true,
margin: { top: '12mm', right: '12mm', bottom: '15mm', left: '12mm' }
});
Playwright documents that CSS page size does not take precedence by default; content is scaled to the selected paper size unless preferCSSPageSize is enabled. Puppeteer documents the same option. Set it deliberately and include a test page with a known @page size.
Let the API control the sheet
await page.pdf({
path: 'report.pdf',
format: 'Letter',
landscape: true,
scale: 0.95,
printBackground: true
});
Do not combine an API format and CSS dimensions casually. Decide which layer owns geometry, then verify physical dimensions in the generated artifact.
Options that affect production output
| Concern | Puppeteer | Playwright | Implementation advice |
|---|---|---|---|
| Paper size | Format, width and height | Format, width and height | Choose one source of truth and test units. |
| CSS page size | preferCSSPageSize |
preferCSSPageSize |
Enable when @page must win. |
| Margins | Supported | Supported | Reserve space for headers and footers. |
| Headers and footers | HTML templates | HTML templates | Test printed margins, escaping and page numbering. |
| Background graphics | printBackground (default false) |
printBackground (default false) |
Set true when colored panels or images are required. |
| Page ranges | Supported | Supported | Validate ranges such as 1-3 against short documents. |
| Scale | Supported | Supported | Check text legibility and overflow after changing it. |
| Tagged output | Documented; check package version | Documented, marked added in v1.42 | Run an accessibility checker; an option alone is not proof of conformance. |
| Outlines | Documented as experimental | Not established by the retrieved reference | Verify support in the exact installed release before relying on it. |
Defaults matter. Backgrounds are off by default in both references, and print color adjustment can change the visual result. Set every output-critical option explicitly.
Fonts, images and deterministic pagination
Puppeteer explicitly states that Page.pdf() waits for fonts to load. The Playwright reference reviewed here does not state an equivalent default. In either library, wait for application data and images before capture, and inspect output with the fonts used in production.
Rank #3
await page.goto(url, { waitUntil: 'networkidle' });
await page.evaluate(() => document.fonts.ready);
await page.waitForSelector('[data-pdf-ready]');
await page.pdf({ path: 'ready.pdf', printBackground: true });
- Use a readiness marker after API data, charts and client-side rendering finish.
- Give images intrinsic dimensions so late loading does not reflow pages.
- Use print-specific breaks such as
break-inside: avoidfor cards and tables, and test long rows. - Pin browser and library versions in CI; small engine changes can alter line wrapping or pagination.
Headers, footers and page ranges
Both APIs accept header and footer HTML templates and page ranges. Templates have restricted styling and often require explicit margins. Build a fixture containing a long title, a two-page table and a footer with page numbers. Check that the header does not overlap body content, that blank trailing pages are absent, and that selecting a range does not unexpectedly change counters or layout.
Accessibility and document validation
Both references list tagged PDF output. Playwright’s displayed option is marked as added in v1.42 and defaults to false; Puppeteer’s reference also identifies tagged output and marks some capabilities experimental. Verify option availability in your installed versions. Then inspect the resulting PDF with the accessibility and archival checks required by your organization. A boolean API option does not establish correct reading order, semantics, language metadata or conformance.
How to choose between Puppeteer and Playwright
Choose Puppeteer when
- Your existing automation, browser management and test fixtures are already Puppeteer-based.
- You want the documented font-wait behavior and have validated the rest of the PDF contract.
- Your deployment is built around the Chromium channel and Puppeteer’s release cadence.
Choose Playwright when
- Your application already uses Playwright for cross-browser automation and you want one API and fixture system.
- You need Playwright’s browser and context model elsewhere in the same service.
- Your team is prepared to verify font readiness, tagged output and PDF options against the installed release.
When neither has a documented advantage
The reviewed documentation contains no controlled benchmark proving a speed, memory, reliability or visual-quality winner. Test both against representative invoices, reports, charts, long tables, non-Latin fonts, authenticated pages and your actual container or serverless runtime. Measure cold start, steady-state latency, failure rate, memory and pixel or text differences under the concurrency you expect.
A practical comparison plan
- Pin one Puppeteer version and one Playwright version, including browser revisions or channels.
- Use identical HTML, CSS, assets, viewport, locale, timezone and data.
- Set media type, paper geometry, margins, backgrounds, scale and CSS page-size preference explicitly.
- Wait for application readiness and fonts, then generate multiple runs from a cold browser and a reused browser.
- Compare page count, dimensions, text extraction, links, colors, font substitution, table breaks, headers, footers and tagged structure.
- Repeat inside the production OS, container or serverless environment and at planned concurrency.
- Adopt the library that passes your acceptance checks with the operational cost and maintenance profile your team can support.
Troubleshooting common failures
PDF uses the wrong colors
Print media and print color adjustment are active. Either keep print styling and add -webkit-print-color-adjust: exact where needed, or emulate screen media before page.pdf(); also set printBackground: true.
Recommended Free Tools
Rank #4
- Brand: Wiley
- Set of 2 Volumes
- A handy two-book set that uniquely combines related technologies Highly visual format and accessible language makes these books highly effective learning tools Perfect for beginning web designers and front-end developers
CSS dimensions are ignored
The API paper format is winning. Enable preferCSSPageSize: true, remove the conflicting format, or intentionally use the API dimensions.
Fonts are substituted
The font request may still be pending, blocked or unavailable in the runtime. Await document.fonts.ready, confirm network or bundled font access, add a readiness marker, and inspect the PDF on the deployment image.
Content is missing or truncated
Capture began before client rendering or lazy assets completed. Wait for a semantic ready selector, use an appropriate navigation wait condition, and ensure images have loaded before generating.
Headers overlap the body
Increase the corresponding margin and simplify the template’s CSS. Verify the template in a multi-page fixture rather than a one-page sample.
Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchPC 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 & 11Best Value
Pagination differs between machines
Browser revision, fonts, OS libraries, viewport, locale or timezone may differ. Pin versions and assets, set environment values explicitly, and compare artifacts in the same container.
Tagged or outline output is unavailable
Check the installed package version and its API reference. Puppeteer documents outline generation as experimental; Playwright’s tagged option is documented as added in v1.42. Do not depend on either without an artifact-level validation step.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Or skip the browser setup
If your requirement is simply a clean PDF or screenshot from a URL, ScreenshotNeo provides a single HTTP endpoint and an MCP server for AI agents. It accepts consent banners before capture and removes more than 60 known consent platforms, newsletter popups and chat widgets; each cleanup step can be disabled. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads and cache hits are not billed, and response headers identify the page verdict and billing status. Its MCP tools—take_screenshot, get_page_info and capture_pdf—work with Claude, Cursor and other MCP clients.
For PDF capture, see the ScreenshotNeo documentation and call:
Free tools Windows power users keep installed
One-click scans. No signup required.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
The same endpoint is available from Python:
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
And Node.js:
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
The Free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account.
Frequently Asked Questions
Do both libraries support PDF output without installing a separate PDF renderer?
Yes. Their documented page.pdf() methods generate the PDF through the automated browser; you still need the library’s supported browser runtime installed and available to your process.
Can I use a custom paper size instead of A4 or Letter?
Yes. Both APIs document explicit width and height values. Keep units consistent and test the resulting physical dimensions.
Which library should a new project standardize on?
There is no documentation-based universal winner. Standardize on the library that best fits your existing automation and deployment, after comparing your real templates on pinned versions.
The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →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.

