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

The right JavaScript PDF method depends on where your HTML is rendered. For a Node.js process that controls Chromium, use Puppeteer or Playwright. For conversion inside a user’s browser, use html2pdf.js. These are different execution models: browser automation can print a fully rendered page, while html2pdf.js converts a selected element in the client.

Choose the execution model first

Approach Runs where Best fit Important behavior
Puppeteer page.pdf() Node.js with automated Chromium Server-side reports, invoices and documents Uses print CSS by default; supports paper, margins, ranges, backgrounds and font readiness options
Playwright page.pdf() Node.js with a Playwright-controlled browser Projects already using Playwright Returns a PDF buffer and uses print CSS by default
html2pdf.js The end user’s browser A download button for one page element Uses html2canvas and jsPDF; its documentation states it does not run in Node.js

Neither the available documentation nor a controlled benchmark establishes that one approach is universally faster or more accurate. Validate the generated PDF with the actual fonts, images, charts and CSS used by your application.

Generate a PDF with Puppeteer in Node.js

Install and create a minimal document

Install Puppeteer in your project. Its bundled Chromium makes the example self-contained, although your deployment must still allow the browser process to start.

npm install puppeteer

This complete script loads HTML, waits for the page to settle, chooses screen or print styling, and writes a PDF:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
#1 Best Overall
PDF Extra 2024| Complete PDF Reader and Editor | Create, Edit, Convert, Combine, Comment, Fill & Sign PDFs | Lifetime License | 1 Windows PC | 1 User [PC Online code]
  • EDIT text, images & designs in PDF documents. ORGANIZE PDFs. Convert PDFs to Word, Excel & ePub.
  • READ and Comment PDFs – Intuitive reading modes & document commenting and mark up.
  • CREATE, COMBINE, SCAN and COMPRESS PDFs
  • FILL forms & Digitally Sign PDFs. PROTECT and Encrypt PDFs
  • LIFETIME License for 1 Windows PC or Laptop. 5GB MobiDrive Cloud Storage Included.
const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch();
  try {
    const page = await browser.newPage();
    await page.setContent(`
      <!doctype html>
      <html>
        <head>
          <meta charset="utf-8">
          <style>
            @page { size: A4; margin: 16mm; }
            body { font: 14px/1.5 Arial, sans-serif; color: #222; }
            h1 { break-after: avoid; }
            .invoice { border: 1px solid #ddd; padding: 24px; }
          </style>
        </head>
        <body>
          <article class="invoice">
            <h1>Quarterly report</h1>
            <p>Rendered from HTML in Node.js.</p>
          </article>
        </body>
      </html>`, { waitUntil: 'networkidle0' });

    // page.pdf() uses print media by default. Uncomment when screen CSS is required.
    // await page.emulateMediaType('screen');

    await page.pdf({
      path: 'report.pdf',
      format: 'A4',
      printBackground: true,
      preferCSSPageSize: true,
      margin: { top: '16mm', right: '16mm', bottom: '16mm', left: '16mm' },
      waitForFonts: true,
      timeout: 90000
    });
  } finally {
    await browser.close();
  }
})();

Run it with node generate-pdf.js. The result is report.pdf in the current directory.

Print CSS versus screen CSS

Puppeteer generates with the print CSS media type by default. If your layout is designed for the screen, call await page.emulateMediaType('screen') immediately before page.pdf(). Do not assume that a responsive screen layout will paginate correctly without print rules.

Use print-specific CSS for page behavior:

@page {
  size: Letter;
  margin: 12mm;
}

@media print {
  .no-print { display: none !important; }
  .keep-together { break-inside: avoid; }
  h2 { break-after: avoid; }
}

Key Puppeteer options

  • format selects a paper preset such as A4 or Letter.
  • width and height provide custom dimensions; use these instead of format when the document has a nonstandard size.
  • margin controls each page edge.
  • printBackground includes CSS background colors and images.
  • preferCSSPageSize honors the document’s @page size instead of scaling it to the selected format.
  • pageRanges limits output to ranges such as 1-3.
  • landscape rotates the selected paper orientation.
  • waitForFonts waits for fonts used by the page before printing.
  • timeout prevents a request from hanging indefinitely.

Set only the options your document requires, then inspect the PDF in the target paper size. A page that looks correct in a browser window can still overflow or split at an undesirable point when printed.

Generate a PDF with Playwright

Playwright’s page.pdf() returns a PDF buffer rather than requiring a file path. It also uses print CSS by default, and screen styling can be selected with media emulation.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
const { chromium } = require('playwright');
const fs = require('node:fs/promises');

(async () => {
  const browser = await chromium.launch();
  try {
    const page = await browser.newPage();
    await page.setContent(`
      <html><head>
        <style>@page { size: A4; margin: 15mm; } body { font-family: sans-serif; }</style>
      </head><body><h1>Playwright PDF</h1><p>Generated as a buffer.</p></body></html>`,
      { waitUntil: 'networkidle' });

    // Print CSS is the default. Use this line for screen CSS instead.
    // await page.emulateMedia({ media: 'screen' });

    const pdf = await page.pdf({
      format: 'A4',
      printBackground: true,
      preferCSSPageSize: true,
      margin: { top: '15mm', right: '15mm', bottom: '15mm', left: '15mm' }
    });
    await fs.writeFile('playwright-report.pdf', pdf);
  } finally {
    await browser.close();
  }
})();

Use Playwright when the rest of your test or automation stack already controls pages with it. The documented API does not establish categorical superiority over Puppeteer.

Generate a PDF in the browser with html2pdf.js

html2pdf.js is for a different job: a browser page converts an element through html2canvas and jsPDF, then saves the result. Its project documentation states that it runs in a browser, not Node.js.

<button id="download">Download PDF</button>
<article id="document">
  <h1>Client-side report</h1>
  <p>Only this element is converted.</p>
</article>
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2pdf.js/0.10.1/html2pdf.bundle.min.js"></script>
<script>
  document.querySelector('#download').addEventListener('click', () => {
    const element = document.querySelector('#document');
    const options = {
      margin: 12,
      filename: 'client-report.pdf',
      image: { type: 'jpeg', quality: 0.95 },
      html2canvas: { scale: 2, useCORS: true },
      jsPDF: { unit: 'mm', format: 'a4', orientation: 'portrait' },
      pagebreak: { mode: ['css', 'legacy'] }
    };
    html2pdf().set(options).from(element).save();
  });
</script>

This route is convenient when no server-side browser is available and the user should initiate the download. It is not a drop-in replacement for Puppeteer or Playwright: it renders through a canvas/image pipeline rather than Chromium’s print operation. Keep images same-origin or configure CORS, and test long documents for page-break behavior.

Make the output reliable

Wait for content that is not immediately available

  • Use waitUntil: 'networkidle0' (Puppeteer) or waitUntil: 'networkidle' (Playwright) for pages that load data before printing.
  • Wait for a specific selector when it is a stronger readiness signal than network idleness.
  • Wait for fonts; otherwise fallback metrics can change line wrapping and page count.
  • Ensure images have loaded and have stable dimensions before calling the PDF API.

Control page breaks and backgrounds

Define @page, margins and print rules explicitly. Use break-inside: avoid for cards or table rows where supported, and include printBackground: true when color or background images carry meaning. Always open the resulting PDF, not just the source HTML.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #2
Sale
MobiPDF Lifetime - Professional PDF Editor for Windows | Edit, Sign & Convert PDFs | Best Adobe Acrobat Pro Alternative | Lifetime License
  • Edit PDFs with Ease. Modify text, images, and layouts directly within your PDF documents.
  • Convert & Organize. Export PDFs to Word, Excel, or ePub, and organize files with ease.
  • Read & Annotate. Enjoy intuitive reading modes and powerful tools to comment, highlight, and mark up PDFs.
  • Create & Manage PDFs. Create new PDFs, combine multiple files, scan documents, and compress for easy sharing.
  • Fill & Sign Forms. Complete forms and digitally sign documents with secure e-signature tools.

Security and deployment

Never pass untrusted HTML directly into a privileged browser context without considering script execution and network access. In production, restrict navigation targets, use resource limits, close every browser in a finally block, and set a timeout. Containerized Chromium may require the runtime dependencies documented for your base image.

Troubleshooting

The PDF is blank

The page may still be rendering, may have navigated to an error page, or may be hidden by application logic. Wait for a known content selector, verify the URL and inspect the page text before calling pdf().

Fonts or icons look wrong

Wait for fonts, serve font files successfully, and check that the PDF process can reach them. A network request that works on your laptop may fail in a restricted server.

Background colors are missing

Enable Puppeteer’s or Playwright’s printBackground. For print CSS, also verify that a rule is not disabling color adjustment.

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

Screen styles are ignored

That is the default print-media behavior. Emulate screen media before generating the PDF, then add print-specific pagination rules.

Content is clipped or scaled

Check the paper format, custom dimensions, margins and preferCSSPageSize. A wide element can force scaling or overflow; constrain it in print CSS.

html2pdf.js fails on images or produces unexpected breaks

Check CORS and image loading, reduce the canvas scale for memory-heavy documents, and use CSS page-break rules on the selected element. For very large or sensitive documents, move conversion to a controlled server-side browser.

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

Or skip the browser setup

ScreenshotNeo can return a rendered page as a PDF through one GET request, so you do not have to install or manage Chromium. Its cleanup step accepts cookie and consent banners and removes more than 60 known consent platforms, newsletter popups and chat widgets before capture; each cleanup step can be disabled. Bot checks, blank pages, timeouts, failed loads and cache hits are not billed, and the response identifies the result with X-Page-Verdict and X-Billed headers. An MCP server provides take_screenshot, get_page_info and capture_pdf tools for Claude, Cursor and other MCP clients.

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

cURL:

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

For PDF output, add the service’s PDF parameter to your request as documented in the ScreenshotNeo API documentation.

Rank #3
Scrivar PDF Pro - Organize, Edit, Compress, Convert, Merge, eSign, OCR & 30+ tools | Lifetime License
  • EVERY PDF TOOL UNLOCKED - 30+ tools in one app: edit text and images, convert, merge, split, compress, sign, OCR, redact, watermark, batch process, and more. No feature gates, no upsells, nothing held back.
  • PAY ONCE, OWN FOREVER — A one-time purchase, not a subscription. Other apps runs $240/year — Scrivar is yours for life, with free updates included.
  • UNLIMITED eSIGN, BUILT IN — Send contracts and forms for signature and track every step. Recipients sign in their browser with no account or app needed. Replace DocuSign and save hundreds a year.
  • PC, MAC, AND WEB — Install on any Win 10/11 PC or macOS 11+ Mac (Intel or Apple Silicon), or work in your browser at scrivar.com. Same tools, same account, everywhere you work.
  • OCR + FULL OFFICE CONVERSION — Turn scanned documents into searchable, selectable text, and convert PDFs to and from Word, Excel, and PowerPoint with formatting kept intact.

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)

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}`);

Every plan includes the features. The Free plan provides 1,000 shots each month with no card; paid plans start at $5 for 3,000 shots. Start with the free ScreenshotNeo account.

FAQ

Can I call html2pdf.js from a Node.js backend?

No. Its documentation describes a browser-only workflow. Use Puppeteer or Playwright for Node.js rendering.

Which API returns bytes I can send in an HTTP response?

Playwright’s page.pdf() returns a PDF buffer. Puppeteer writes to a path when path is supplied, while you can adapt its output handling to your server response.

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.

Should I use print or screen media?

Use print media for a document designed for paper and screen media only when the PDF must preserve the screen presentation. Both choices require checking pagination.

Frequently Asked Questions

Can html2pdf.js preserve selectable text?

Its documented pipeline renders through html2canvas and jsPDF; validate text selection and accessibility requirements in your generated file before adopting it for formal documents.

Can these tools create a PDF from a URL instead of an HTML string?

Yes. Navigate the automated page to the URL before calling the PDF method, or set the page content directly when your application owns the HTML.

The Bottom Line

Use Puppeteer or Playwright when a Node.js service controls Chromium; use html2pdf.js when the conversion must happen in the browser. Make media type, page dimensions, readiness waits and print CSS explicit, then inspect the actual PDF.

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.

Quick Recap

Bestseller No. 1
PDF Extra 2024| Complete PDF Reader and Editor | Create, Edit, Convert, Combine, Comment, Fill & Sign PDFs | Lifetime License | 1 Windows PC | 1 User [PC Online code]
PDF Extra 2024| Complete PDF Reader and Editor | Create, Edit, Convert, Combine, Comment, Fill & Sign PDFs | Lifetime License | 1 Windows PC | 1 User [PC Online code]
READ and Comment PDFs – Intuitive reading modes & document commenting and mark up.; CREATE, COMBINE, SCAN and COMPRESS PDFs
$99.99
SaleBestseller No. 2
MobiPDF Lifetime - Professional PDF Editor for Windows | Edit, Sign & Convert PDFs | Best Adobe Acrobat Pro Alternative | Lifetime License
MobiPDF Lifetime - Professional PDF Editor for Windows | Edit, Sign & Convert PDFs | Best Adobe Acrobat Pro Alternative | Lifetime License
Edit PDFs with Ease. Modify text, images, and layouts directly within your PDF documents.; Convert & Organize. Export PDFs to Word, Excel, or ePub, and organize files with ease.
$74.99

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.