Getting started
Install, render, save. On Node and Bun you get the high-fidelity Chromium engine without a second step; in the browser there's nothing extra to install at all.
Install
npm i htmlpdfxOn Node and Bun this also brings Puppeteer — which bundles Chromium — as an optional dependency, so Chromium works out of the box.
Because it's optional, the install stays resilient: if the Chromium download is unavailable (CI caches, offline, browser-only targets), npm i htmlpdfx still succeeds and the built-in renderer is used instead.
Prefer a different driver? Install one and htmlpdfx detects it automatically:
npm i playwright # or: playwright-core / puppeteer-coreRender your first PDF
import { toPdf } from "htmlpdfx";
const pdf = await toPdf("<h1>Hello</h1>", { format: "a4", margin: 15 });
await pdf.save("hello.pdf");import { toPdf } from "htmlpdfx";
const pdf = await toPdf(
{ element: document.getElementById("invoice")! },
{ format: "a4", margin: 12 },
);
await pdf.download("invoice.pdf");import htmlpdfx from "htmlpdfx";
await htmlpdfx()
.from(document.getElementById("invoice")!)
.set({ margin: 10, pageBreak: { avoid: [".row"] } })
.save("invoice.pdf");Take the bytes wherever you need them
Every render returns a PdfResult, so the same call works for a file, an HTTP response, or a download:
const pdf = await toPdf(html);
pdf.bytes; // Uint8Array
pdf.pageCount; // number of pages
pdf.engine; // "chromium" | "canvas" — which tier actually ran
await pdf.save("out.pdf"); // Node / Bun: write to disk
await pdf.download("out.pdf"); // Browser: trigger a download
pdf.toBlob(); // Blob
pdf.toDataUrl(); // data: URL
pdf.toArrayBuffer(); // ArrayBufferInputs
Pass a string, a URL, a file, or a live DOM node. The input decides which engines can serve it:
toPdf("<h1>hi</h1>"); // HTML string — either engine
toPdf({ html, baseUrl: "https://cdn.example.com/" }); // HTML + base URL — either engine
toPdf({ url: "https://example.com" }); // live URL — chromium
toPdf({ file: "/abs/report.html" }); // local file — chromium
toPdf({ element: domNode }); // DOM node — canvas (browser)Runtime support
| Runtime | Default engine | Needs |
|---|---|---|
| Node ≥ 18 | chromium | puppeteer or playwright |
| Bun | chromium | puppeteer or playwright |
| Browser | canvas | nothing (built in) |
Force one with { engine: "chromium" } or { engine: "canvas" }; the default auto picks per runtime.
Without a bundler
A prebuilt UMD/IIFE global ships in the package and is served by the CDNs, so the browser needs no npm at all:
<!-- Global build → window.htmlpdfx -->
<script src="https://unpkg.com/htmlpdfx"></script>
<script>
htmlpdfx
.toPdf(document.getElementById("invoice"))
.then((pdf) => pdf.download("invoice.pdf"));
</script>
<!-- …or ES modules straight from a CDN -->
<script type="module">
import { toPdf } from "https://esm.sh/htmlpdfx";
</script>