Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
For a person downloading the page they are viewing, call window.print() and let the browser offer Save as PDF. For automatic conversion in Node.js, use a real browser through Puppeteer or Playwright: load the page, wait for its content, then call page.pdf(). Both libraries use print CSS by default; select screen media explicitly if you need the PDF to follow the screen stylesheet.
Choose the right JavaScript approach
| Need | Starting point | Why |
|---|---|---|
| A person saves the page they are viewing | window.print() |
No server-side browser is needed, and the user retains control of destination and print settings. |
| A backend converts a URL or template automatically | Puppeteer or Playwright | A browser renders the page’s CSS and JavaScript before producing the PDF. |
| PDF output as a stream or buffer | Puppeteer createPDFStream() or Playwright page.pdf() |
Both APIs expose programmatic output; Playwright’s method returns a buffer, while Puppeteer documents a PDF stream API. |
| Screen-style rather than print-style output | Emulate screen media before export | The default for both libraries is print media. |
Use the browser print workflow when the user should decide how the document is saved. Use browser automation when conversion must run unattended, produce a file or bytes for another service, or apply consistent output settings. The trade-off is that automated conversion requires a browser runtime and careful handling of loading, failures, and resource use.
Let a visitor save the current page
For a page you control, provide a button that opens the browser’s print dialog:
const exportButton = document.querySelector('#export-pdf');
exportButton.addEventListener('click', () => {
window.print();
});
Pair it with print styles so the PDF contains the document rather than its controls:
#1 Best Overall
@media print {
nav,
#export-pdf,
.cookie-banner,
.interactive-controls {
display: none !important;
}
body {
color: #000;
background: #fff;
}
}
The browser and the user’s settings determine the exact print dialog and output. This approach uses the visitor’s current browser session, which is useful for pages behind their login, and lets them choose destination and print options. It does not silently save a PDF to a location chosen by your JavaScript.
Convert a URL with Puppeteer
Puppeteer’s documented flow is to launch a browser, create a page, navigate to the target, call page.pdf(), and close the browser. Install Puppeteer in a Node.js project, then save this as an ES module such as convert.mjs:
import puppeteer from 'puppeteer';
const url = process.argv[2] ?? 'https://example.com';
const browser = await puppeteer.launch();
try {
const page = await browser.newPage();
await page.goto(url, { waitUntil: 'networkidle2' });
await page.pdf({
path: 'page.pdf',
format: 'A4',
printBackground: true,
});
} finally {
await browser.close();
}
Run it with node convert.mjs https://example.com. It writes page.pdf in the current working directory. The example uses A4 paper and includes background graphics; change these deliberately to suit your output. In particular, printBackground controls whether background graphics are printed.
Recommended Free Tools
page.pdf() generates a PDF with the print CSS media type. Puppeteer’s guide says it waits for fonts by default. If the PDF should use screen CSS instead, switch media before exporting:
await page.emulateMediaType('screen');
await page.pdf({ path: 'page.pdf', format: 'A4', printBackground: true });
See the Puppeteer Page.pdf() API and the Puppeteer PDF-generation guide for the current API details and supported output options.
Convert a URL with Playwright
Playwright exposes the same core PDF operation. Its page.pdf() method returns a buffer, so write that buffer to disk with Node’s file system API:
import { chromium } from 'playwright';
import { writeFile } from 'node:fs/promises';
const url = process.argv[2] ?? 'https://example.com';
const browser = await chromium.launch();
try {
const page = await browser.newPage();
await page.goto(url, { waitUntil: 'networkidle' });
const pdf = await page.pdf({ format: 'A4', printBackground: true });
await writeFile('page.pdf', pdf);
} finally {
await browser.close();
}
Run with node convert.mjs https://example.com after installing Playwright and its browser. Playwright also defaults to print CSS media. To generate a PDF using screen media, call await page.emulateMedia({ media: 'screen' }) before page.pdf(). Consult the Playwright Page API for the current method behavior.
Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Clear out junk files and repair common Windows errors3Fix the driver behind crashes, sound loss and screen glitchesChoose one library based on your existing project and deployment environment; both examples follow the same practical sequence. Do not assume that a URL being reachable means its app has finished rendering. For client-side pages, wait for the relevant application content or selector before exporting, rather than relying only on a navigation event.
Make the PDF match the page you intend to deliver
Print CSS versus screen CSS
Both libraries generate PDFs with print media by default. That is often desirable: sites can use @media print to hide navigation and controls, alter page breaks, and simplify the document. If the task is specifically to preserve the on-screen appearance, explicitly emulate screen media before calling the PDF method. Check the result on representative pages; switching media changes which CSS rules apply, not just colors.
Paper, margins, orientation, backgrounds, and page ranges
Set output options explicitly when predictable documents matter. The examples specify A4 and background printing. Puppeteer and Playwright offer PDF options for layout details such as margins and page ranges; use the API documentation for the precise option names and accepted values for your installed version. Decide whether the output should be portrait or landscape and whether a page range is appropriate. For user-driven printing, these decisions may remain in the browser dialog.
Fonts and visual assets
Puppeteer documents that PDF generation waits for fonts by default. That does not establish that every remote font or image will load successfully: the target page, network, authentication, and browser environment still matter. Use print-ready CSS and verify the actual PDF, especially when typography or brand assets are important.
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 matchWindows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallDynamic data, lazy content, and authenticated pages
Navigation completion and application readiness are different things. A client-rendered chart may appear after the document has loaded; lazy images may load only after scrolling; an authenticated route may redirect to a login page in a fresh browser context. Wait for the application’s meaningful ready state or a specific selector, and configure the browser context with the necessary session where appropriate. Cross-origin images, charts, and protected routes are cases to test in your own application; the cited API documentation does not guarantee how every site renders them.
Rank #4
Troubleshoot missing or incorrect PDF content
- The PDF is blank or shows a loading screen: navigation may have completed before the application rendered. Wait for a page-specific selector or a reliable application-ready condition before exporting.
- Content or images are missing: check whether assets load only after scrolling, depend on cross-origin access, or require a session. Test those conditions in the same browser context used for conversion.
- The PDF looks different from the browser: print media is the default. Add or correct
@media printrules, or emulate screen media before calling the PDF method if screen styling is the actual requirement. - Background colors or graphics disappear: enable
printBackground: trueand inspect the page’s print CSS. - Fonts differ: verify that the font files are reachable and actually used by the page. Puppeteer waits for fonts by default, but that cannot make an unavailable font load.
- Pages break in awkward places: review print-specific layout and page-break behavior, and set paper size and margins intentionally. Screen layouts are not automatically good paginated documents.
- The automation hangs or takes too long: a page may keep network activity open or depend on a stalled request. Choose a suitable navigation wait condition, add an application-specific readiness check, and handle navigation and browser errors in production code.
- The PDF file is not produced: ensure the output directory is writable, await the PDF operation, and close the browser in a
finallyblock so cleanup occurs when conversion fails.
Performance, reliability, and cost in an automated service
Browser-based PDF conversion has to load and render the page before it can serialize the result. In a backend, treat each conversion as work that can fail: set an operational timeout, capture useful error information, and make sure browser processes are closed after success or failure. Reuse or isolate browser processes according to your deployment’s security and reliability needs; do not let one failed navigation prevent cleanup.
For predictable output, standardize the browser version, paper settings, media type, and waiting condition in the environment that generates the PDFs. Test a representative set of routes, including authenticated pages and dynamic content. The official documentation explains the APIs, but does not establish universal rendering guarantees for third-party sites or a fixed conversion time or cost: those depend on the pages and infrastructure you operate.
Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server that can return a screenshot or PDF. Its API accepts one GET request with a URL; the example below saves a WebP screenshot. See the ScreenshotNeo documentation for PDF output and available settings.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
It can remove cookie and consent banners, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers report the page verdict and billing status. An MCP server provides screenshot tools for AI agents, and the free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000. If that fits your workflow, sign up free for 1,000 screenshots a month, with no card required.
Frequently Asked Questions
Can browser JavaScript silently save a PDF without opening a dialog?
For a visitor-triggered export, window.print() hands control to the browser’s print workflow; it is not a silent save-to-file API. Use a server-side browser library for unattended file generation.
Which is better for Node.js, Puppeteer or Playwright?
Both support browser-rendered PDF generation. Pick the one that fits your existing automation stack and deployment; the key workflow—navigate, wait for content, set media and PDF options, then save output—is similar.
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.

