Engineering9 min read

react-pdf vs Puppeteer: an honest comparison

When to use @react-pdf/renderer vs Puppeteer for PDFs in React and Next.js. Bundle size, layout correctness, serverless limits, and when HTML-to-PDF still wins.

Two approaches dominate PDF generation in React apps: print HTML with a headless browser (Puppeteer / Playwright / Chromium), or lay the document out with @react-pdf/renderer. Teams pick the wrong one, then spend months paying for it in broken invoices or failed deploys.

This is an honest comparison. Bundle size and layout correctness first. No "always faster" marketing. For the full map of PDF families, see How to generate PDFs in React in 2026.

The short answer

Use @react-pdf/renderer for structured business documents (invoices, receipts, reports, certificates) in React/Next.js: ~2 MB deploy weight, deterministic layout, and no Chromium process. Use Puppeteer when you must reproduce existing HTML/CSS pixel-for-pixel or the content is arbitrary rich HTML you cannot map to react-pdf primitives. Most SaaS document features should start with react-pdf.

Side-by-side

Dimension @react-pdf/renderer Puppeteer / Chromium
Mental model Document components (Document, Page, View, Text) Render HTML, then page.pdf()
Deploy weight ~2 MB ~50–150 MB depending on Chromium package
Vercel / Lambda fit Fits typical function limits Often needs layers, external browsers, or fails size checks
Pagination Layout engine; rows can still tear unless wrap={false} Browser print pipeline; tables and headings often orphan
CSS surface Flexbox subset, no full CSS Near-full CSS (what Chromium supports)
Data residency Renders in your process Same if self-hosted; many teams outsource to Browserless
Best for Data-driven docs with stable layout Pixel clones of existing web/print CSS

Sources for the size story: @react-pdf/renderer vs a default Puppeteer + Chromium install. Slim options like @sparticuz/chromium reduce weight but still bring browser memory and cold-start cost. Details: Puppeteer is too big for Vercel.

How does layout correctness differ?

Puppeteer prints a webpage. The browser decides page breaks the way print CSS does. Long tables split mid-row. Headings sit alone at the bottom of a page. Fonts differ between your laptop and the Lambda image unless you ship them carefully.

react-pdf is not a browser. It lays out primitives top to bottom. You control unbreakable units. The sharp edge is tables: without wrap={false} on rows, react-pdf can still tear a line item. That is a one-prop fix, not a reason to go back to Chromium. Walkthrough: Why your react-pdf table splits across pages.

What about speed?

Warm Puppeteer renders can be fast. Cold starts and memory are where serverless bills and timeouts show up. react-pdf avoids booting a browser, which removes that class of cost. We do not claim react-pdf is universally "faster than Puppeteer" across every document. Measure your own p95 on your hardware. Prefer the comparison that actually decides production: does it deploy, paginate correctly, and keep fonts stable?

For invoice-at-volume economics (cold starts, memory, font drift), see Stop using HTML-to-PDF for invoices.

When Puppeteer is the right call

Keep Puppeteer (or Gotenberg / Browserless) when:

  1. Design already exists as HTML/CSS and must match pixel-for-pixel.
  2. Content is user-authored rich HTML you cannot reasonably map to Views.
  3. You already run a dedicated render fleet outside the serverless size envelope.

Do not pick Puppeteer because "HTML is easier." That ease expires after the first multi-page invoice with dynamic rows.

When react-pdf is the right call

Start with react-pdf when:

  1. The layout is stable and the data changes (classic SaaS invoices, statements, certificates).
  2. You deploy on Vercel, Netlify, or Lambda and cannot spare a Chromium layer.
  3. Customer PII should never leave your app for a render hop.
  4. Your team already ships React and wants templates in git.

Minimal examples

react-pdf (Route Handler):

import { renderToBuffer } from "@react-pdf/renderer";
import { InvoiceDocument } from "./InvoiceDocument";
 
export async function GET() {
  const pdf = await renderToBuffer(<InvoiceDocument data={invoice} />);
  return new Response(pdf, {
    headers: { "Content-Type": "application/pdf" },
  });
}

Puppeteer (sketch):

import puppeteer from "puppeteer-core";
// plus a Chromium binary / @sparticuz/chromium on serverless
 
const browser = await puppeteer.launch({ /* args */ });
const page = await browser.newPage();
await page.setContent(html);
const pdf = await page.pdf({ format: "A4" });
await browser.close();

The second path always carries a browser lifecycle. The first path is a library call.

How do visual builders fit?

Hand-writing react-pdf flex layouts is tedious. Hosted HTML builders (PDFMonkey, CraftMyPDF, and similar) remove the tedium but keep templates and renders in their cloud. A third path: design visually, export owned react-pdf TSX, render yourself.

That is what PDFx Builder does. Preview is the real react-pdf engine. Export is typed source. Optional hosted API on paid plans. Compare hosted lock-in directly:

Ready-made starting points with owned react-pdf export: SaaS subscription invoice, EU VAT invoice, payment receipt. Browse everything in the template gallery.

Decision checklist

Ask two questions:

  1. Must the output match existing HTML/CSS? Yes → Puppeteer. No → react-pdf.
  2. Must this deploy inside a small serverless function? Yes → react-pdf (or an external browser service, not Chromium-in-function).

If both answers push opposite directions, split the workload: Puppeteer for the marketing PDF that clones a webpage; react-pdf for the billing documents that run ten thousand times a day.

Summary

  • react-pdf wins on bundle size, serverless fit, and structured-document layout.
  • Puppeteer wins on pixel fidelity to existing HTML/CSS.
  • Fix react-pdf table tears with wrap={false}; do not treat that as a reason to ship Chromium.
  • Measure latency yourself; decide production on deployability and correctness.

Going deeper

Build one of these yourself.

Start free at pdfxbuilder.com. Three templates, no credit card.

Open PDFx Builder