Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
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:

@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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Choose 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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Dynamic 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.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

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 print rules, or emulate screen media before calling the PDF method if screen styling is the actual requirement.
  • Background colors or graphics disappear: enable printBackground: true and 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 finally block 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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
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.

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.