How To

Install wkhtmltopdf on Ubuntu 26.04 / 24.04 and Debian 13 / 12

wkhtmltopdf is discontinued. The GitHub repository is archived, the last upstream release dates from 2020 (the last packaged build from May 2023), and Ubuntu 26.04 and Debian 13 no longer package it at all. Plenty of invoice jobs, reporting scripts and ERP installs still call it, though, so this guide gets the patched build running on current Ubuntu and Debian releases and shows what to move to next.

Original content from computingforgeeks.com - post 35406

To install wkhtmltopdf on Ubuntu or Debian today, you need the right package from the archived wkhtmltopdf packaging releases, because the distro builds are either gone or unpatched. The steps below fix the “has no installation candidate” error and the 404 that older guides hit. They also cover local file access, page numbers, wkhtmltoimage and pdfkit. Every command was run on Ubuntu 26.04, Ubuntu 24.04, Debian 13 and Debian 12 in October 2026.

wkhtmltopdf is archived: what that means for you

The binary still works. Nothing else about it will change. The main repository is archived, and the packaging repository that builds the patched-Qt binaries is archived too. The maintainer’s status page is blunt about it: the WebKit engine has not been updated since 2012, and untrusted HTML can lead to a full takeover of the server running it.

That warning is not theoretical. CVE-2022-35583 is a CVSS 9.8 SSRF in 0.12.6, and no fix will come. Run it only on HTML your own application generates. For anything new, read our benchmark of wkhtmltopdf alternatives first. It tests eleven replacements on the same invoice and report documents.

Choose the right wkhtmltopdf package

Two builds exist and they behave differently. The distro package links against the stock Qt WebKit and ignores headers, footers, the table of contents and several page options. The patched build from the packaging repo bundles its own patched Qt and supports all of them. Each release is in a different state:

ReleaseDistro package (apt)Patched build to install
Ubuntu 26.04 LTSNone, apt reports Candidate: (none)jammy .deb
Ubuntu 24.04 LTS0.12.6-2build2, unpatched Qtjammy .deb
Debian 13 (trixie)None, apt reports Candidate: (none)bookworm .deb
Debian 12 (bookworm)0.12.6-2+b1, unpatched Qtbookworm .deb

No builds exist for the noble (24.04), resolute (26.04) or trixie (13) codenames. The jammy package runs on both current Ubuntu LTS releases, and the bookworm package runs on both Debian releases. That is the whole trick.

The unpatched distro build announces its limits on the first run. On Ubuntu 24.04, a footer flag produced this warning and a PDF without any footer:

The switch --footer-center, is not support using unpatched qt, and will be ignored.QStandardPaths: XDG_RUNTIME_DIR not set, defaulting to '/tmp/runtime-josphat'

Debian 12’s package printed the same line. If which wkhtmltopdf returns /usr/bin/wkhtmltopdf, you have the distro build. Remove it before you continue:

sudo apt purge -y wkhtmltopdf

Install the patched wkhtmltopdf build

Start with the tools the install needs:

sudo apt update
sudo apt install -y curl poppler-utils

The release tag, the package suite and the CPU architecture all go into the download URL. Detect all three instead of typing them. The suite is jammy on Ubuntu and its derivatives and bookworm on Debian. The fallback tag only applies if the GitHub API rate limit returns nothing, and the archived repo will never publish a newer one:

. /etc/os-release
case " $ID $ID_LIKE " in
  *" ubuntu "*) WK_SUITE=jammy ;;
  *" debian "*) WK_SUITE=bookworm ;;
  *) echo "Unsupported distribution: $ID" ;;
esac
ARCH=$(dpkg --print-architecture)
WK_TAG=$(curl -s https://api.github.com/repos/wkhtmltopdf/packaging/releases/latest | grep -oP '"tag_name": "\K[^"]+')
WK_TAG=${WK_TAG:-0.12.6.1-3}  # pin: archived repo, last tag https://github.com/wkhtmltopdf/packaging/releases
echo "$WK_TAG $WK_SUITE $ARCH"

If the first line prints Unsupported distribution, stop here: the packaging repo only builds for Debian and Ubuntu families. On Ubuntu 26.04 the three values came back as:

0.12.6.1-3 jammy amd64

Debian 12 and 13 print bookworm in the middle. Download the matching package and install it with apt, which pulls the font and X11 libraries it depends on:

curl -fsSLO "https://github.com/wkhtmltopdf/packaging/releases/download/${WK_TAG}/wkhtmltox_${WK_TAG}.${WK_SUITE}_${ARCH}.deb"
sudo apt install -y "./wkhtmltox_${WK_TAG}.${WK_SUITE}_${ARCH}.deb"

The package lands as wkhtmltox, and both binaries go to /usr/local/bin. Confirm the patched build is the one on your PATH:

wkhtmltopdf --version
which wkhtmltopdf wkhtmltoimage

The version string must say “with patched qt”:

wkhtmltopdf 0.12.6.1 (with patched qt)
/usr/local/bin/wkhtmltopdf
/usr/local/bin/wkhtmltoimage

The same output appeared on all four releases. The packaging repo also publishes arm64 builds for jammy and bookworm, and the ARCH variable selects them on ARM hosts.

Error: E: Package ‘wkhtmltopdf’ has no installation candidate

This is what sudo apt install wkhtmltopdf prints on Debian 13 and Ubuntu 26.04. Debian removed the package from testing in February 2025, before trixie shipped, and Ubuntu dropped it in 25.04, so 26.04 is the first LTS without it. apt knows the name only because other packages still mention it. Check it yourself:

apt-cache policy wkhtmltopdf

An empty candidate confirms there is nothing to install from the archive:

wkhtmltopdf:
  Installed: (none)
  Candidate: (none)
  Version table:

The fix is the patched .deb from the install section above. There is no repository to add.

Error: curl: (22) The requested URL returned error: 404

Many guides, including an older version of this one, build the download URL from lsb_release -cs. Of the four releases tested here, that works on Debian 12 only. Ubuntu 26.04 resolves to resolute, Ubuntu 24.04 to noble and Debian 13 to trixie, and the packaging repo never published those files:

curl: (22) The requested URL returned error: 404

Map the release to jammy or bookworm as shown above and the download succeeds. If you searched for the “jammy deb on Ubuntu 24.04” question, the answer is yes: it installs and passes every test in this guide.

Convert an HTML file to PDF

Create a working directory with a small invoice that references a local logo, which is where most real templates trip:

mkdir -p ~/invoices && cd ~/invoices
vim invoice.html

Paste the template and save it. Put any PNG named logo.png next to it:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Invoice 2026-118</title>
<style>
body { font-family: "DejaVu Sans", sans-serif; padding: 24px; }
h1 { color: #2c3e50; }
table { border-collapse: collapse; width: 100%; }
th, td { border: 1px solid #ccc; padding: 8px; text-align: left; }
th { background: #f4f4f4; }
</style>
</head>
<body>
<img src="logo.png" width="64" alt="logo">
<h1>Invoice 2026-118</h1>
<p>Billed to: Example Corp</p>
<table>
<tr><th>Item</th><th>Price</th></tr>
<tr><td>VPS hosting (12 months)</td><td>$240.00</td></tr>
<tr><td>Managed backups</td><td>$60.00</td></tr>
<tr><td><strong>Total</strong></td><td><strong>$300.00</strong></td></tr>
</table>
</body>
</html>

Convert it with the plain two-argument form first:

wkhtmltopdf invoice.html invoice.pdf

It writes a PDF, but without the logo, and exits with status 1:

Warning: Blocked access to file /home/josphat/invoices/logo.png
Error: Failed to load about:blank, with network status code 301 and http status code 0 - Protocol "about" is unknown
Exit with code 1 due to network error: ProtocolUnknownError

Since 0.12.6, wkhtmltopdf blocks local file access by default. Scripts that worked on older builds break here, and a cron job that checks the exit code will report a failure every night. Allow it explicitly for templates you control:

wkhtmltopdf --enable-local-file-access invoice.html invoice.pdf
pdfimages -list invoice.pdf
pdfinfo invoice.pdf | grep -E "Pages|Page size|Producer"

The logo is now embedded, and the producer line shows the Qt build doing the work:

page   num  type   width height color comp bpc  enc interp  object ID x-ppi y-ppi size ratio
--------------------------------------------------------------------------------------------
   1     0 image     128   128  rgb     3   8  image  no         6  0   240   240  291B 0.6%
Producer:        Qt 4.8.7
Pages:           1
Page size:       595 x 842 pts (A4)

Qt 4.8.7 is the engine inside the patched build, and it explains most of wkhtmltopdf’s CSS limits. Flexbox, grid and CSS variables do not exist there. Never pass --enable-local-file-access when the HTML comes from users, since it lets the HTML load any local file the process can read.

Add page numbers, margins and a PDF title

Headers and footers are the main reason to insist on the patched build. Page size, orientation and margins are flags too:

wkhtmltopdf --enable-local-file-access \
  --page-size A4 --orientation Portrait \
  --margin-top 20mm --margin-bottom 20mm \
  --title "Invoice 2026-118" \
  --footer-center "Page [page] of [topage]" --footer-font-size 8 \
  invoice.html invoice-styled.pdf

Check that the title and the footer text made it into the file:

pdfinfo invoice-styled.pdf | grep -E "Title|Pages"
pdftotext invoice-styled.pdf - | grep "Page 1"

Both are present:

Title:           Invoice 2026-118
Pages:           1
Page 1 of 1

The flags you will reach for most often:

FlagWhat it doesExample
–page-sizePaper size (A4, A3, Letter, Legal)–page-size Letter
–orientationPortrait or Landscape–orientation Landscape
–margin-top / -bottom / -left / -rightPage margins in mm, cm or in–margin-top 20mm
–header-center, –footer-centerHeader or footer text; [page] and [topage] expand to numbers–footer-center “Page [page] of [topage]”
–header-html, –footer-htmlUse an HTML file as the header or footer–footer-html footer.html
–titlePDF metadata title–title “Invoice 2026-118”
–javascript-delayMilliseconds to wait for scripts (default 200)–javascript-delay 1000
–enable-local-file-accessAllow file:// images, CSS and fonts–enable-local-file-access
-qSilence the progress bars in logs-q

Render a web page URL to PDF

Pass a URL instead of a file. The -q flag keeps the progress bars out of your logs:

wkhtmltopdf -q https://example.com example.pdf
ls -lh example.pdf
pdftotext example.pdf - | head -3

The page text is in the PDF:

-rw-r--r-- 1 josphat josphat 5.5K Oct  8 10:32 example.pdf
This domain is for use in documentation examples without
needing permission. This is not a service; avoid relying on
it for testing and monitoring purposes.

Static pages are fine. Single-page apps are not. The 2012 WebKit cannot parse modern JavaScript, so React and Vue dashboards come out blank or half drawn no matter how long --javascript-delay waits. In our tests even ES2020 optional chaining failed. Those pages need a real browser, such as Chrome headless with –print-to-pdf or Playwright.

Render HTML to an image with wkhtmltoimage

The same package ships wkhtmltoimage, which writes PNG, JPG or SVG. Width is yours to set, and height follows the content:

wkhtmltoimage --enable-local-file-access --format png --width 1024 invoice.html invoice.png
file invoice.png

The result is a 1024 pixel wide PNG:

invoice.png: PNG image data, 1024 x 392, 8-bit/color RGBA, non-interlaced

Call wkhtmltopdf from Python with pdfkit

Most applications reach wkhtmltopdf through a wrapper. For Python that is pdfkit, which maps a dictionary onto the CLI flags. Install it in a virtual environment, since Ubuntu and Debian block system-wide pip installs:

sudo apt install -y python3-venv
python3 -m venv ~/pdfkit-env
~/pdfkit-env/bin/pip install pdfkit

Create the render script in the invoices directory:

vim ~/invoices/render.py

Add the following. The None value turns a flag without an argument on:

import pdfkit

options = {
    "page-size": "A4",
    "margin-top": "20mm",
    "margin-bottom": "20mm",
    "footer-center": "Page [page] of [topage]",
    "encoding": "UTF-8",
    "title": "Invoice 2026-118",
    "enable-local-file-access": None,
}

pdfkit.from_file("invoice.html", "invoice-python.pdf", options=options)
print("Wrote invoice-python.pdf")

Run it and inspect the result:

cd ~/invoices
~/pdfkit-env/bin/python render.py
pdfinfo invoice-python.pdf | grep -E "Title|Pages"

pdfkit found the binary in /usr/local/bin without extra configuration:

Wrote invoice-python.pdf
Title:           Invoice 2026-118
Pages:           1

pdfkit.from_string() and pdfkit.from_url() take an HTML string or a URL instead of a file, which suits Jinja2, Django and Flask templates. pdfkit has not shipped a release since November 2021 either, so plan the migration for both at once.

Replace wkhtmltopdf: pick the successor for your job

The install above buys time. It does not fix the frozen engine or the open CVE. We benchmarked the replacements on the same invoice, report and JavaScript dashboard, and the full wkhtmltopdf alternatives comparison has the numbers. The short version, with a tested setup guide for each:

Your wkhtmltopdf jobMove toWhy
Invoices and reports from your own templatesWeasyPrintFull CSS paged media: running headers, page counters, footnotes. No browser needed.
A PDF service several apps callGotenberg in DockerHTTP API over Chromium and LibreOffice, blocks file:// reads by default
JavaScript-heavy pages and dashboardsPlaywright or PuppeteerReal Chromium, header and footer templates, waits for the page to finish
Shell scripts and cron jobsChrome headless –print-to-pdfOne command, and the headless shell build matched wkhtmltopdf’s 0.29 s per-run time in our tests
PHP applicationsDompdfPure PHP via Composer, no external binary

Header and footer flags have direct equivalents in most of them, so the migration is mostly moving --footer-center into an @page rule or a footer template. If Odoo or another platform calls wkhtmltopdf for you, keep this patched build until the platform ships its own replacement, and keep untrusted HTML away from it.

Keep reading

Upgrade Ubuntu 24.04 to Ubuntu 26.04 LTS (Step by Step) Ubuntu Upgrade Ubuntu 24.04 to Ubuntu 26.04 LTS (Step by Step) UFW Firewall Commands with Examples on Ubuntu 26.04 / 24.04 Security UFW Firewall Commands with Examples on Ubuntu 26.04 / 24.04 Configure Samba File Share on Debian 13 / 12 Debian Configure Samba File Share on Debian 13 / 12 Upgrade a Single Package on Ubuntu / Debian with apt Debian Upgrade a Single Package on Ubuntu / Debian with apt CapRover Docker Install on Debian 13: Deploy Your First App Containers CapRover Docker Install on Debian 13: Deploy Your First App Install Oracle JDK 21 on Ubuntu 24.04/22.04 Ubuntu Install Oracle JDK 21 on Ubuntu 24.04/22.04

8 thoughts on “Install wkhtmltopdf on Ubuntu 26.04 / 24.04 and Debian 13 / 12”

  1. Thanks for a nice explanation. it helped me a lot

    was facing an issue while installing the lib.

    The following packages have unmet dependencies:
    wkhtmltox : Depends: libpng12-0 but it is not installed
    Depends: libssl1.0.0 but it is not installed
    Depends: xfonts-75dpi but it is not installed
    Depends: xfonts-base but it is not installed

    but fixed it by running

    apt –fix-broken install

    Reply
  2. Gracias por la ayuda, lo solucione en Odoo 13 con servidor Debian, el eror era, que al imprimir no mostraba el encabezado ni el pie de pagina, ademas de no ostrar el logo.

    Gracias

    Reply

Leave a Comment

Press ESC to close