A Puppeteer alternative for business-document PDFs
Generating invoice and receipt PDFs with Puppeteer (or Playwright) means running headless Chrome in production. For structured business paper, that's a lot of moving parts to maintain. Here's the honest breakdown of when it's worth it — and when it isn't.
What Puppeteer actually costs you in production
- Deploy weight: a ~300MB Chromium binary, usually wrapped in a Lambda layer or a fat container image.
- Cold starts: booting a browser per render adds latency that's hard to make predictable.
- Memory & crashes: headless Chrome is memory-hungry and fails in ways that are painful to reproduce.
- Template ownership: you author and version the HTML/CSS, then fight print quirks (page breaks, margins, fonts).
Keep Puppeteer when…
- The document genuinely is a web page — a custom report or marketing one-pager with bespoke layout.
- You need to screenshot or capture an existing URL exactly as a browser renders it.
- Designers iterate constantly on the layout and live in HTML/CSS.
Reach for a JSON API when…
- The document is structured business paper — invoices, receipts, statements — where the layout is already solved and only the data changes.
- You'd rather not ship, patch, and pay for a browser just to lay out a table of line items.
- Predictable latency matters: no browser boot means a faster, steadier render.
The same job, both ways
With Puppeteer:
// The Puppeteer path: ~300MB of Chromium, a Lambda layer,
// cold starts, and an HTML template you now own forever.
import chromium from "@sparticuz/chromium";
import puppeteer from "puppeteer-core";
const browser = await puppeteer.launch({
args: chromium.args,
executablePath: await chromium.executablePath(),
headless: true,
});
const page = await browser.newPage();
await page.setContent(renderInvoiceHtml(data)); // you maintain this
const pdf = await page.pdf({ format: "A4", printBackground: true });
await browser.close();With Slipstack:
// The Slipstack path: no browser, no template, one request.
const res = await fetch("https://slipstack.dev/api/v1/pdf", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.SLIPSTACK_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ template: "invoice", data }),
});
const pdf = Buffer.from(await res.arrayBuffer()); // ~200ms, doneThe trade-off in one sentence
Puppeteer gives you unlimited layout freedom and makes you operate a browser to get it; a JSON API like Slipstack gives you a professionally-designed invoice or receipt layout for free and asks only for your data. Tax, discounts, and totals are computed for you, and you can brand each document with a logo and accent color.
Delete the Chromium layer
POST your line items, get a finished PDF. Free tier: 50 documents/month, no card.
See the API