Best wkhtmltopdf Alternative in 2026: Fast, Modern, and Zero Vulnerabilities
For more than a decade, wkhtmltopdf was the default choice for generating PDF documents from HTML. Wrappers like KnpLabs/Snappy in PHP, wicked_pdf in Ruby, and pdfkit in Python powered millions of invoice and receipt systems.
However, wkhtmltopdf is officially archived and obsolete. The project was built on a frozen, unmaintained fork of Qt WebKit from 2012. It carries multiple unpatched CVE security vulnerabilities, crashes unpredictably under multi-threading, and lacks support for modern CSS standards like Flexbox and CSS Grid.
Why wkhtmltopdf Broke Down
The core architectural flaw of wkhtmltopdf is that HTML and CSS were never designed for physical pages. Web browsers prioritize continuous vertical scrolling. Translating that into fixed A4 or Letter physical pages causes severe rendering bugs:
- Broken Table Splits: Multi-page billing tables frequently slice table rows in half across page margins.
- No CSS Flexbox or Grid: The 2012 WebKit engine fails to render modern layouts, forcing teams to write obsolete HTML table tags.
- CVE Security Hazards: Outdated WebKit has severe vulnerabilities allowing malicious template inputs to read local server files like
/etc/passwd. - High Latency: Generating a single 3-page invoice requires 400ms to 900ms per invocation.
Detailed Benchmark: Rubrol vs wkhtmltopdf
Here is an empirical comparison across standard production metrics on an AWS c6i.large instance:
| Architecture Metric | wkhtmltopdf (Deprecated) | Headless Chromium (Puppeteer) | Rubrol (Native Typst) |
|---|---|---|---|
| P95 Render Latency | 680 ms | 1,450 ms | 8.4 ms |
| Memory Usage (RAM) | 95 MB per process | 450 MB - 1.2 GB | < 28 MB |
| Modern CSS / Layout | Broken (2012 WebKit) | Full Web CSS | Deterministic Typst Engine |
| Page Break Precision | Unreliable / Row Slicing | Hacky CSS rules | Mathematical Print Layout |
| Security Status | Archived (Unpatched CVEs) | High Attack Surface | Isolated Memory-Safe Rust |
| PDF/A-3b Compliance | None | Requires Ghostscript pipeline | Native ISO 19005-3 + Factur-X |
How Rubrol Solves Document Compilation
Rather than spinning up an obsolete browser engine, Rubrol is engineered in native Rust around the Typst layout compiler. Typst was conceived specifically for physical page typesetting rather than web browser scrolling.
This architectural shift provides three massive advantages:
- Sub-10ms Compilation: Documents compile in single-digit milliseconds, enabling real-time on-demand downloads without background job queues.
- Deterministic Pagination: Table headers automatically repeat across pages, kerning is calculated to the point, and rows never get cut in half.
- Enterprise E-Invoicing: Rubrol automatically attaches and embeds compliant XML (CII / UBL) into PDF/A-3b files, meeting the mandatory European EN 16931 and Factur-X standards out of the box.
Step-by-Step Migration Example
Migrating from a legacy wkhtmltopdf script to Rubrol takes less than ten minutes. Here is how a standard backend pipeline transitions:
Before: Legacy wkhtmltopdf Subprocess Call (Slow & Vulnerable)
# Old approach: invoking deprecated WebKit binary
import subprocess
def generate_pdf(html_path, output_path):
subprocess.run([
"wkhtmltopdf",
"--enable-local-file-access", # Dangerous security risk!
"--page-size", "A4",
html_path,
output_path
], check=True)
# Average execution: 750ms, 110MB RAM
After: High-Performance Rubrol Invocation (Sub-10ms)
# Modern approach: sub-10ms native compilation
import requests
def generate_pdf(invoice_data, output_path):
response = requests.post(
"http://localhost:8080/v1/compile",
json={
"template": "invoice",
"data": invoice_data,
"compliance": "factur-x" # Optional PDF/A-3b XML embedding
}
)
with open(output_path, "wb") as f:
f.write(response.content)
# Average execution: 8.4ms, 18MB RAM
Ready to Retire wkhtmltopdf for Good?
Test the Rubrol layout compiler live right now inside your browser. No installation or registration required.
Test the Live Compiler in StudioFrequently Asked Questions
Can I use my existing HTML and CSS templates?
While Typst uses its own concise, clean markup language, Rubrol includes template converters and direct SVG injection. Most developers find that rewriting complex HTML templates into Typst takes less than an hour and eliminates hundreds of lines of hacky CSS pagination workarounds.
Does Rubrol support multi-page tables with repeating headers?
Yes. Repeating headers and footers on multi-page tables work natively without custom JavaScript hacks or CSS page-break polyfills.
Is Rubrol open-source?
Yes. The core Rubrol engine is licensed under LGPL-3.0. You can run the standalone CLI or deploy the official container sidecar on your own infrastructure with zero cloud lock-in.