Skip to content

HTML PDF

Page breaks that
don't cut your table in half.

A real browser engine on the server for selectable, vector text and true CSS pagination — and a self-contained renderer in the browser when Chromium isn't there. One API across Node, Bun, and the browser, with no required runtime dependencies.

npm i htmlpdfx

Start here

Two engines, one API

toPdf() behaves the same everywhere. What changes is what's rendering underneath — and that difference is worth understanding before you ship, because it decides whether your text is selectable.

Chromium

high fidelity

The browser's own print-to-PDF, driven by Puppeteer or Playwright. The PDF is the webpage: page breaks, fonts, and layout are correct by construction, and text stays selectable and searchable. The default on Node, Bun, and Deno, and the one to reach for when a person will read the result.

Canvas

best effort

A from-scratch DOM rasterizer for the browser, with no Chromium and nothing to install. It produces a faithful screenshot of your DOM, sliced cleanly across pages — a raster, not a reflow. Use it as graceful degradation, not as a substitute.

auto picks per runtime, so you rarely choose by hand. See what each engine supports for the full matrix, row by row.

What it does differently

No split rows or cards

The slicer backs up to the top of a table row, card, or figure rather than cutting through it — and <thead> repeats on every page a table spans.

Selectable, not screenshotted

Real vector text in the Chromium tier, so readers can search and copy from the PDF, and the file stays small.

No jsPDF, no html2canvas

The PDF writer and the DOM rasterizer are written from scratch. The core has no required runtime dependencies at all.

Modern CSS as-is

Flexbox, grid, custom properties, oklch() and lab() colours, and web fonts — awaited before render, then embedded.

Honest about its limits

Every capability is marked per engine, and the gaps are published rather than glossed over. Knowing a feature is best-effort beats discovering it in a broken PDF.

Familiar on day one

A functional toPdf() plus an html2pdf.js-compatible fluent builder, so migrating is mostly deleting code.

Install

bash
npm i htmlpdfx

On Node and Bun that also brings Puppeteer as an optional dependency, so the high-fidelity engine works without a second step. In the browser there's nothing else to install.

Released under the MIT License. Sponsor.