Comparison
A Node.js alternative to html-pdf-node
html-pdf-node is a thin wrapper around Puppeteer that launches a headless Chromium process for every render request. Installing it pulls in a 150 MB Chromium binary that breaks in Alpine-based Docker images, requires additional system packages on Debian, and spawns a new OS process every time you generate a PDF. PDFPipe moves the rendering off your server entirely: one HTTP call, no binary, no process management.
Side by side
| PDFPipe | html-pdf-node | |
|---|---|---|
| Install size | 0 bytes | ~150 MB Chromium download |
| Alpine Docker | Works | Requires workarounds or larger base image |
| Memory per render | None in your process | Chromium child process per call |
| Concurrency | Handled by the API | Manual pool management required |
| Browser version | Always current | Pinned to package version |
| Serverless / Edge | Yes | No (binary can't run in Lambda or Edge) |
| Maintenance | Active | Infrequently updated |
The serverless problem
html-pdf-node and Puppeteer cannot run in AWS Lambda, Vercel Functions, Cloudflare Workers, or any Edge environment because they require a real OS process and filesystem. Teams that start with html-pdf-node on a traditional server eventually hit this wall when they try to move to serverless infrastructure. PDFPipe is an HTTP call and works everywhere fetch works.
Migration
// Before: html-pdf-node (Chromium binary required)
const htmlPdf = require("html-pdf-node");
const file = { content: "<h1>Invoice</h1>" };
const options = { format: "A4" };
const buffer = await htmlPdf.generatePdf(file, options);
// 150 MB Chromium process per render, no connection pooling// After: one fetch call, no binary
const res = await fetch("https://api.pdfpipe.xyz/v1/pdf", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.PDFPIPE_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
html: "<h1>Invoice</h1>",
options: { format: "A4" },
}),
});
const buffer = await res.arrayBuffer();Full Node.js guide on the Node.js page.
See pricing →