Generate PDF from HTML in Node.js: Puppeteer vs playwright-pdf
Compare Puppeteer and Playwright for HTML-to-PDF generation in Node.js. Covers CSS print styles, page size, headers and footers, and performance benchmarks.
Generating pixel-perfect PDF documents such as invoices, certificates, and compliance reports from HTML and CSS is best achieved using headless Chrome via Puppeteer.
Setting Up Puppeteer
npm install puppeteer
Download our standard 1MB sample PDF to compare against your Puppeteer rendering output.
Download 1MB PDF Sample →Rendering HTML to PDF with Puppeteer
import puppeteer from 'puppeteer';
export interface PdfRenderOptions {
htmlContent: string;
outputPath?: string;
format?: 'A4' | 'Letter';
}
export async function generatePdfFromHtml({
htmlContent,
outputPath,
format = 'A4',
}: PdfRenderOptions): Promise<Buffer> {
const browser = await puppeteer.launch({
headless: true,
args: ['--no-sandbox', '--disable-setuid-sandbox'], // Required in Linux Docker containers
});
try {
const page = await browser.newPage();
// Set HTML content and wait until network connections idle
await page.setContent(htmlContent, { waitUntil: 'networkidle0' });
const pdfBuffer = await page.pdf({
format: format,
printBackground: true, // Crucial for CSS backgrounds and colors
margin: {
top: '20mm',
right: '15mm',
bottom: '20mm',
left: '15mm',
},
path: outputPath,
});
return Buffer.from(pdfBuffer);
} finally {
await browser.close();
}
}
Styling Rules for Print PDFs
- Use
@pageCSS: Control paper size and margins with standard CSS:CSS@page { size: A4 portrait; margin: 1.5cm; } - Avoid page break splits: Prevent tables and headers from splitting across pages using
page-break-inside: avoid;.
Nguyen Dai Long
AuthorBackend Lead • Distributed Systems & Cloud Edge Architecture Specialist
4+ years designing high-throughput file ingestion pipelines, database architectures, and distributed edge storage on Cloudflare R2 & AWS S3. Founder of FileDummy and the NDL Ecosystem.
Was this article helpful?
Click Like to support the author and help other developers discover this guide.
Engineering Discussion & Feedback (0)
Share benchmark results, report edge cases, or ask technical questions.
No comments yet. Be the first developer to start the discussion!
Frequently Asked Questions
Which is faster: Puppeteer or Playwright for PDF generation?â–¾
Both use the same Chromium rendering engine, so PDF generation performance is nearly identical. Playwright offers a slightly cleaner API and better multi-browser support. Choose based on your existing toolchain.
How do I add page numbers in Puppeteer-generated PDFs?â–¾
Use the headerTemplate and footerTemplate options in page.pdf(). These accept HTML strings with special CSS classes: .pageNumber renders the current page, .totalPages renders the total. Inline styles are required since templates have isolated CSS scope.
How do I prevent page breaks mid-table?â–¾
Add page-break-inside: avoid (or break-inside: avoid) to table rows and sections. Use @media print CSS rules or pass custom CSS via page.addStyleTag().