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, done

The 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