Puppeteer PDF alternative
Puppeteer is not a worse tool. It is the same rendering engine — this service drives Chromium too — so there is no CSS-support argument to make. Anything Puppeteer renders, this renders identically.
The entire difference is who operates the browser.
What operating it actually costs
Not theory. These are the things teams hit:
- Image size. A Node service that would ship in ~150MB becomes 500MB or more with Chromium inside it. Every base-image bump is a fresh set of shared libraries to chase.
--no-sandbox. In most containers Chromium will not start without it, so a security boundary gets removed in order to print a document — and then justified in a review.- Concurrency is yours. Each render is a tab with real memory cost. You decide the cap, build the queue, and choose what request 51 is told.
- Lifecycle is yours. Browsers crash. Reaping zombies, bounding memory, and stopping one pathological document from taking the process down all become your application's problem.
- Cold starts. Launching a browser per render is seconds; keeping one warm is a pool to manage.
None of that is hard. All of it is work that recurs, and none of it is your product.
The honest table
| Renderpaper | Puppeteer | |
|---|---|---|
| Engine | Chromium | Chromium |
| CSS support | Identical | Identical |
| Documents leave your infrastructure | Yes | No |
| Cost | Plan allowance | Free — you pay in infrastructure |
| Control over Chromium flags and version | No | Total |
| Full page-interaction API before printing | No | Yes — click, wait, log in, scrape |
| Image size | N/A | +300–400MB |
| Process supervision and concurrency | Ours | Yours |
| Stored templates, editable without a deploy | Yes | No |
When to keep Puppeteer
Documents must not leave your network. This ends the discussion, and it should.
You need the browser anyway. If you already run Puppeteer for scraping, screenshots or end-to-end tests, the marginal cost of PDF generation is nearly zero and paying for an API makes no sense.
Your document requires interaction before printing. Log in, click through a wizard, wait for a specific network call, then print. That is Puppeteer's territory; a render API takes a document and prints it.
You need a pinned Chromium version or specific flags. Full control is a real requirement in some environments and you cannot have it here.
When Renderpaper fits better
The browser exists only to print documents. That is a lot of operational surface for an invoice.
You would otherwise build the pool. The queueing, the memory ceiling, the crash-recovery — that is a week of work and then permanent maintenance.
Somebody non-engineering owns the design. With Puppeteer the document lives in your repository, so a margin change is a deploy. Stored templates move it out.
Migrating from Puppeteer
Your HTML does not change — same engine, same CSS. Replace page.setContent() plus
page.pdf() with one HTTP call, and map the options:
| Puppeteer | Here |
|---|---|
format: 'A4' |
@page { size: A4 } in the CSS, or the paper option |
margin: {...} |
@page { margin: … } |
printBackground: true |
on by default |
landscape: true |
@page { size: A4 landscape } |
headerTemplate / footerTemplate |
no equivalent — see below |
That last row is the one to check first. Renderpaper has no header or footer
options. If you are using headerTemplate you are probably already fighting it —
Chromium renders it in an isolated context that cannot see your stylesheet — and
the repeating-header recipe is the technique
that replaces it, with measurements.
Try it
https://renderpaper.com/try — paste the HTML you currently pass to setContent.