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

Choose based on where your code runs: use Puppeteer or Playwright when a Node.js process controls a rendered Chromium page; use html2pdf.js when conversion should happen in a visitor’s browser. These are different rendering approaches, not interchangeable APIs. Puppeteer and Playwright generate PDFs using print CSS by default, while html2pdf.js converts a selected page element through html2canvas and jsPDF.

Choose the right JavaScript PDF approach

Approach Where it runs Best fit Important distinction
Puppeteer page.pdf() Node.js-controlled browser page Automated rendering or server-side generation Print CSS is the default; the API has options for paper, margins, page ranges, backgrounds and more.
Playwright page.pdf() Playwright-controlled page A Playwright workflow that needs PDF bytes as a buffer Print CSS is the default; screen media can be emulated before PDF generation.
html2pdf.js Web browser Client-side conversion of a selected element Uses html2canvas and jsPDF; its project documentation says it does not run in Node.js.

The cited API documentation establishes these behaviors, not a controlled speed or fidelity ranking. Choose based on runtime, output handling and layout requirements, then inspect the resulting PDF in the environment that matters to you.

Generate a PDF with Puppeteer

Puppeteer is a practical choice when your Node.js program can open the page in a browser and control its rendering. The API documentation consulted labels Puppeteer 25.12.0; check the current documentation when pinning an implementation to a particular version.

Install and render a URL

Install Puppeteer in your project, then save a script such as pdf.mjs. This example opens a page and writes a PDF file:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
import puppeteer from 'puppeteer';

const browser = await puppeteer.launch();
try {
  const page = await browser.newPage();
  await page.goto('https://example.com', { waitUntil: 'networkidle0' });
  await page.pdf({ path: 'page.pdf', format: 'A4', printBackground: true });
} finally {
  await browser.close();
}

Run it with node pdf.mjs. Replace the example URL with a page you are authorized to access. The script waits for network activity to settle before printing, but that alone cannot guarantee that every application-specific chart, image or delayed widget has finished rendering.

Choose print or screen styling

page.pdf() uses the print CSS media type by default. That means print-specific rules such as @media print may affect layout even if the page looks different on screen. If the intended PDF should follow screen styling, emulate screen media before calling page.pdf():

await page.emulateMediaType('screen');
await page.pdf({ path: 'screen-layout.pdf', printBackground: true });

If the document should be a print-ready artifact, leave print media active and design or adjust the page’s print styles instead. Decide which result you want before tuning margins or scaling; changing media can change the content layout.

Set the page dimensions and print options deliberately

Puppeteer documents options for paper format or explicit width and height, margins, page ranges, background printing, CSS page-size preference, font readiness and timeouts. Set the values that match the document rather than assuming a screen viewport will automatically translate to paper. For example:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
await page.pdf({
  path: 'report.pdf',
  format: 'A4',
  printBackground: true,
  preferCSSPageSize: true,
  margin: {
    top: '12mm',
    right: '12mm',
    bottom: '16mm',
    left: '12mm'
  },
  pageRanges: '1-5',
  waitForFonts: true,
  timeout: 30000
});

Use either a paper format such as A4 or explicit dimensions when your design needs a custom page size. preferCSSPageSize lets CSS page sizing take precedence over the format or dimensions supplied to the PDF call. A margin reserves printable space around page content; verify that it does not clip the intended layout. pageRanges limits output to selected pages. printBackground includes background graphics, which otherwise may be absent from the PDF. waitForFonts waits for fonts to be ready before creating the document.

For a reusable implementation, make output choices explicit and keep browser cleanup in a finally block. If a page’s own print styles determine page size, test the CSS and the chosen options together: dimensions and margins interact with how content paginates.

Generate a PDF with Playwright

Playwright’s Page.pdf() also uses print CSS by default and returns a PDF buffer. That makes it suitable when a Playwright-controlled page needs PDF data in memory or needs to be written to a chosen destination.

Write the returned buffer to a file

With Playwright installed and a browser available to your project, an ES module can render a page and save the returned bytes:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
import { chromium } from 'playwright';
import { writeFile } from 'node:fs/promises';

const browser = await chromium.launch();
try {
  const page = await browser.newPage();
  await page.goto('https://example.com', { waitUntil: 'networkidle' });
  const pdf = await page.pdf({ format: 'A4', printBackground: true });
  await writeFile('page.pdf', pdf);
} finally {
  await browser.close();
}

The buffer can also be passed to another part of your Node.js application instead of being written to disk. The API behavior described here does not establish that Playwright is categorically faster or more faithful than Puppeteer; if you already use Playwright, using its page API avoids introducing a second browser automation workflow.

Emulate screen styling when needed

To create a PDF using screen rather than print media styling, set the media type before generating the PDF:

await page.emulateMedia({ media: 'screen' });
const pdf = await page.pdf({ format: 'A4', printBackground: true });

Otherwise, retain the default print behavior and make the page’s print CSS fit the intended paper layout. As with Puppeteer, inspect the actual result rather than inferring the PDF’s appearance from the browser viewport.

Generate a PDF in the browser with html2pdf.js

Use html2pdf.js when the conversion belongs in the user’s browser and the target is a page or a specific element. Its documented workflow uses html2canvas and jsPDF. The project README states that it runs in a browser, not Node.js, so it is not a substitute for a Node-controlled page renderer.

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

Select the element to convert

After including the library in a browser page, select the element that should become the PDF and invoke the documented worker chain:

const element = document.querySelector('#invoice');

if (!element) {
  throw new Error('Could not find #invoice');
}

html2pdf()
  .set({ filename: 'invoice.pdf' })
  .from(element)
  .save();

This is a browser-side workflow: the page provides the DOM element, and the library’s documented conversion chain proceeds through a container, canvas, image and PDF before saving output. It is not the same operation as printing a rendered page with Chromium’s print CSS. Select the content intentionally; converting a large wrapper can include controls, navigation or other material that should not appear in the document.

Prepare the page and verify the result

PDF generation is a separate rendering step, so layout on screen is not proof that the document will paginate or print as intended. Before relying on the file, inspect it in the target environment and check the content that matters to your use case.

  • Choose the media type: use print styling for a print-oriented document, or explicitly emulate screen styling if the PDF should follow screen rules.
  • Set page size and margins: align the selected paper dimensions with the document’s CSS and keep important content inside the printable area.
  • Check backgrounds: enable background printing when colors or background graphics are part of the design.
  • Check fonts and images: ensure assets needed by the document have loaded. Puppeteer’s documented waitForFonts option can wait for fonts, but the documentation does not promise that every external asset or application widget is ready.
  • Review pagination: inspect page breaks, clipped content and the last page, especially for long or dynamic documents.
  • Validate the delivered file: open the generated PDF and check representative pages, links or other requirements relevant to your application.

The cited documentation describes API options and output behavior rather than exhaustive compatibility testing. Do not assume identical results across pages, fonts, browser environments or rendering methods without checking your own output.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Troubleshooting common PDF-generation problems

The PDF layout differs from the screen

Cause: Puppeteer and Playwright use print CSS by default, so print media rules can alter the layout. Fix: decide whether the document should use print or screen styling. Emulate screen media before generating the PDF if screen rules are desired; otherwise inspect and adjust print styles.

Background colors or graphics are missing

Cause: background printing was not enabled. Fix: set printBackground: true in Puppeteer or Playwright’s PDF options and regenerate the file.

Content is clipped or breaks awkwardly

Cause: the paper dimensions, margins, CSS sizing and content flow do not work together. Fix: set an appropriate paper format or dimensions, review the margins, and inspect page-size CSS and page breaks in the resulting PDF. For Puppeteer, consider whether preferCSSPageSize should let CSS page sizing take precedence.

Fonts or images look incomplete

Cause: required resources may not be ready when PDF generation begins. Fix: wait for the relevant resources before calling the PDF API and inspect the generated document. Puppeteer documents waitForFonts; it should not be treated as a general guarantee that images or application-specific rendering are complete.

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

The html2pdf.js import or invocation fails in Node.js

Cause: the project documentation describes html2pdf.js as browser-only. Fix: run it in a browser context, or use a browser automation approach such as Puppeteer or Playwright for a Node.js workflow.

Or skip the browser setup

If your goal is a PDF capture of a live webpage rather than a PDF generated by your own JavaScript runtime, ScreenshotNeo can return a PDF from one GET request. This is a separate route from the Puppeteer, Playwright and html2pdf.js examples above. The API accepts page-capture options; see the ScreenshotNeo API documentation for PDF settings and request details.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.pdf

Use an API key in place of YOUR_API_KEY. ScreenshotNeo accepts cookie or 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 cost nothing, and the response identifies page verdict and billing status in headers. Its MCP server provides take_screenshot, get_page_info and capture_pdf tools for AI agents and MCP clients. The Free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots.

Sign up for ScreenshotNeo’s free plan to get 1,000 screenshots a month without a card.

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

Frequently Asked Questions

Can html2pdf.js run in Node.js?

No. Its project documentation describes it as a browser-side library; use Puppeteer or Playwright for a Node.js-controlled browser workflow.

Do Puppeteer and Playwright use screen CSS when making a PDF?

No. Both use print CSS by default. Emulate screen media before generating the PDF if screen styling is the intended output.

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.