Free and open source · MIT · Linux, Windows, macOS

The drop-in replacement for wkhtmltopdf

wkhtmltopdf is archived: its last release dates from June 2020, on a Qt WebKit that gets no security fixes. pdfkiln answers to the same command line with a current, sandboxed Chromium. Your code does not change, and your templates keep their page count.

Install pdfkiln Source on GitHub

Install

One program answers to two names: called wkhtmltopdf, it takes wkhtmltopdf 0.12.6’s command line; called pdfkiln, it offers its own interface, with print defaults taken from the page’s CSS. Chromium’s sandbox stays on: run it as an unprivileged user, not root.

Debian and Ubuntu

Debian 12 and 13, Ubuntu 22.04 and later, amd64 and arm64. From the signed APT repository, which brings Chromium’s security fixes with apt upgrade. It installs /usr/bin/pdfkiln and /usr/bin/wkhtmltopdf and replaces the official wkhtmltox package.

curl -fsS https://apt.pdfkiln.org/pdfkiln-archive-keyring.asc | sudo tee /usr/share/keyrings/pdfkiln-archive-keyring.asc > /dev/null
printf 'Types: deb\nURIs: https://apt.pdfkiln.org\nSuites: stable\nComponents: main\nSigned-By: /usr/share/keyrings/pdfkiln-archive-keyring.asc\n' \
  | sudo tee /etc/apt/sources.list.d/pdfkiln.sources
sudo apt update && sudo apt install pdfkiln

Windows

x64; ARM runs it in emulation. From the latest release, the installer, or the zip, which holds wkhtmltopdf\bin\wkhtmltopdf.exe as the old installer did: both go in C:\Program Files\wkhtmltopdf, the path pdfkit and most guides use. Uninstall wkhtmltopdf first. Windows Server needs the Desktop Experience, not Server Core.

The programs are not signed yet: SmartScreen warns about the installer. Check it against the release’s SHA256SUMS.

Docker

amd64 and arm64, on Debian 13 slim, as an unprivileged user. Docker’s default seccomp profile stops Chromium’s sandbox; seccomp.json is that profile plus the namespaces the sandbox needs.

curl -fsSO https://raw.githubusercontent.com/Jamalofski/pdfkiln/main/docker/seccomp.json
docker run --rm -i --security-opt seccomp=seccomp.json ghcr.io/jamalofski/pdfkiln wkhtmltopdf - - < page.html > page.pdf

PHP (Composer)

PHP 7.4 or later. Puts wkhtmltopdf and wkhtmltoimage in vendor/bin and downloads the program of the platform on first use, its SHA-256 checked. On a Linux server, prefer the Debian package or the Docker image: they bring Chromium’s system libraries.

composer require pdfkiln/pdfkiln

npm

Node.js 22.12 or later. Chromium is downloaded on first use into the user’s cache, its SHA-256 checked.

npx @pdfkiln/pdfkiln wkhtmltopdf page.html page.pdf
npm install -g @pdfkiln/pdfkiln    # pdfkiln, wkhtmltopdf and wkhtmltoimage

Linux and macOS archives

Linux x64 and ARM64, macOS ARM64, from the latest release: the program, its Chromium, and wkhtmltopdf and wkhtmltoimage beside it. On Linux, Chromium needs the system libraries of the Debian package; pdfkiln names those missing. On Debian 13 and Ubuntu 24.04:

sudo apt install libasound2t64 libatk-bridge2.0-0t64 libatk1.0-0t64 libatspi2.0-0t64 libdbus-1-3 libexpat1 libgbm1 \
  libglib2.0-0t64 libnspr4 libnss3 libudev1 libx11-6 libxcb1 libxcomposite1 libxdamage1 libxext6 libxfixes3 \
  libxkbcommon0 libxrandr2 fontconfig fonts-liberation

Every release is built and tested by CI, then published by hand, with SHA-256 sums and build provenance attestations: gh attestation verify <file> --repo Jamalofski/pdfkiln.

Migrate in five minutes

Point the library at pdfkiln’s wkhtmltopdf, never at pdfkiln: called by that name, it switches to its own interface. With the Debian package, /usr/bin/wkhtmltopdf is already in the PATH, and libraries that read the version keep working.

Secure by default

wkhtmltopdf’s defaults are kept, it is the compatibility contract: a page reads no local file but itself unless --enable-local-file-access or --allow <path> says so, and neither .. nor a symbolic link gets around --allow. On top of them:

  • --kiln-block-private-network: no loopback, private or link-local address, cloud metadata included, checked after DNS resolution.
  • --kiln-timeout: the conversion and Chromium stop after 120 s by default.
  • Chromium’s sandbox is on, and nothing is shared between two calls: a fresh profile, or with pdfkiln serve a browser context of its own, deleted at the end.

Measured, not promised

A complete call on the two-page Odoo invoice of the corpus, median of the runs, against the official wkhtmltopdf 0.12.6:

SystemDelaywkhtmltopdfpdfkiln
Ubuntu 24.04200 ms0.52 s1.11 s
Ubuntu 24.041000 ms, Odoo’s2.13 s1.14 s
Windows 11 PC200 ms1.36 s1.80 s
Windows 11 PC1000 ms, Odoo’s2.91 s1.85 s

Ubuntu on GitHub Actions, CI run of 24 October 2026; Windows 11 on a 20-thread PC; node dist/bench/call.js --delay 200, then without --delay. wkhtmltopdf always waits the whole --javascript-delay; pdfkiln stops as soon as nothing can change the page. pdfkiln serve keeps Chromium open and saves its start-up: 0.17 s per call on Ubuntu.

pdfkiln Pro · in preparation

Factur-X, PDF/A, written guarantees?

pdfkiln stays free, without limits. pdfkiln Pro adds what companies need on top: PDF/A-3 and Factur-X from your current HTML templates, Chromium updates tested against your templates, and written fix and response times.

See pdfkiln Pro