PDFPipe

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

PDFPipehtml-pdf-node
Install size0 bytes~150 MB Chromium download
Alpine DockerWorksRequires workarounds or larger base image
Memory per renderNone in your processChromium child process per call
ConcurrencyHandled by the APIManual pool management required
Browser versionAlways currentPinned to package version
Serverless / EdgeYesNo (binary can't run in Lambda or Edge)
MaintenanceActiveInfrequently 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

javascript
// 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
javascript
// 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 →