Comparison
A serverless alternative to html-pdf
The html-pdf npm package is a Node.js wrapper around wkhtmltopdf. It requires a system binary compiled against Qt WebKit, a browser engine that received its last security update in 2019. Deploying it to Lambda, a Docker container based on Alpine, or an ARM machine requires either a custom binary or a fat layer that adds 150 MB to your deployment. PDFPipe is a hosted API. There is no binary, no native dependency, and nothing to install on your server.
html-pdf versus a hosted PDF API
| PDFPipe | html-pdf | |
|---|---|---|
| Rendering engine | Modern browser engine | wkhtmltopdf / Qt WebKit 2019 |
| System binary required | No | Yes (wkhtmltopdf) |
| Works on AWS Lambda | Yes | Only with custom layer (+150 MB) |
| Works on Alpine Linux | Yes | No (glibc dependency) |
| Works on ARM64 | Yes | Requires cross-compiled binary |
| CSS Grid / Flexbox | Full support | Partial |
| JavaScript in templates | Yes | No |
| Active maintenance | Yes | Deprecated |
| AI agents | First-class MCP server | Not applicable |
The wkhtmltopdf binary problem
html-pdf calls wkhtmltopdf as a child process. This means your deployment machine must have the binary present and executable. On cloud functions, that binary is not in the base image. The common workarounds (Lambda layers, Docker base images with wkhtmltopdf baked in, or mounting it from S3 at cold-start) each add complexity, increase cold-start time, and create a version-pinned dependency you need to audit for CVEs yourself.
Beyond the deployment friction, wkhtmltopdf uses a browser engine that was forked from Chrome in 2012 and is no longer maintained for security. It does not support CSS Grid, Flexbox, modern web fonts, or JavaScript execution inside templates.
Migrating from html-pdf
The migration is a straightforward replacement of the html-pdf call with a fetch to the PDFPipe API. The HTML you were passing to html-pdf goes into the request body unchanged.
const pdf = require("html-pdf");
pdf.create(html, { format: "A4" }).toBuffer((err, buffer) => {
if (err) return res.status(500).send(err);
res.set("Content-Type", "application/pdf");
res.send(buffer);
});const response = 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, options: { format: "A4" } }),
});
if (!response.ok) {
const { detail } = await response.json();
return res.status(502).send(detail);
}
res.set("Content-Type", "application/pdf");
response.body.pipe(res);No binary to install. No native module to compile. No Lambda layer to build. The HTML renders with a modern browser engine on every request.
500 free documents a month
The Hobby tier is free, permanently, with no credit card. 500 documents a month is enough for development, staging, and light production workloads. Paid plans start at $19/month with flat per-document pricing and no overage charges.