wkhtmltopdf Alternative

wkhtmltopdf Is Archived. Here's the Modern Replacement.

Published April 5, 2026 — 7 min read

If you're using wkhtmltopdf in production, you've probably noticed: it was archived in 2023. No more updates. No bug fixes. And it's been struggling for years before that — broken CSS Grid support, no JavaScript execution, install nightmares on modern Linux.

This guide covers why developers are replacing wkhtmltopdf with a hosted PDF API, and how to switch your existing code to URLSnap in minutes.

wkhtmltopdf is officially archived: The project was archived on GitHub in August 2023. There are no more releases, no security patches, and no support. If you're running it in production today, you're on borrowed time.

Why wkhtmltopdf Breaks on Modern Stacks

wkhtmltopdf was built on an old Qt WebKit engine — essentially Internet Explorer-era browser technology. By modern web standards, it's severely limited:

No JavaScript: wkhtmltopdf does not execute JavaScript. Any page built with React, Vue, Angular, or even basic JS-rendered content will render as a blank page or skeleton HTML.
Broken CSS: CSS Flexbox, CSS Grid, CSS variables, and most modern layout techniques don't work. Your carefully designed invoice template looks completely different in wkhtmltopdf.
Install hell: On Ubuntu 22.04+, Debian 12+, and Alpine Linux, wkhtmltopdf requires outdated library versions that conflict with modern packages. Many Docker setups have workarounds spanning dozens of lines.
No ARM support: M1/M2 Macs, AWS Graviton, and Raspberry Pi require custom builds. Official ARM binaries don't exist.
Archived, no fixes: Security vulnerabilities discovered in 2024 and 2025 will never be patched. Using it in production is a compliance risk.

wkhtmltopdf vs URLSnap: Side-by-Side

Feature wkhtmltopdf URLSnap API
PDF generation
JavaScript execution✗ (not supported)✓ (real Chromium)
Modern CSS (Flexbox, Grid)✗ (broken)
CSS variables / custom properties
React / Vue / Angular pages
A4 / Letter / Legal formats
Landscape orientation
Works in Docker / Lambda✗ (library issues)✓ (just HTTP)
ARM support (M1, Graviton)✗ (no official build)
Actively maintained✗ (archived 2023)
Security patches✗ (none since 2023)
No binary to install
Free tier✓ (OSS)✓ (20 req/day)

Migration: From wkhtmltopdf to URLSnap

Here's a typical wkhtmltopdf shell call or Node.js wrapper:

# Before: wkhtmltopdf shell command
wkhtmltopdf --page-size A4 https://example.com output.pdf

# Before: Node.js with wkhtmltopdf wrapper
const wkhtmltopdf = require('wkhtmltopdf');
wkhtmltopdf('https://example.com', { pageSize: 'A4' })
  .pipe(fs.createWriteStream('output.pdf'));

Here's the equivalent with URLSnap:

# After: URLSnap (curl)
curl "https://urlsnap.dev/api/pdf?url=https://example.com&format=A4&apiKey=YOUR_KEY" \
  -o output.pdf

// After: Node.js with URLSnap
const response = await fetch(
  `https://urlsnap.dev/api/pdf?url=https://example.com&format=A4&apiKey=YOUR_KEY`
);
const buffer = await response.arrayBuffer();
fs.writeFileSync('output.pdf', Buffer.from(buffer));

No binary to install. No library conflicts. No ARM compatibility issues. One HTTP request from any language, anywhere.

Python Migration

# Before: Python + pdfkit (wkhtmltopdf wrapper)
import pdfkit
pdfkit.from_url('https://example.com', 'output.pdf')

# After: URLSnap
import requests
response = requests.get(
    'https://urlsnap.dev/api/pdf',
    params={'url': 'https://example.com', 'format': 'A4', 'apiKey': 'YOUR_KEY'}
)
with open('output.pdf', 'wb') as f:
    f.write(response.content)

PHP Migration

// Before: PHP + wkhtmltopdf
$pdf = new Knp\Snappy\Pdf('/usr/local/bin/wkhtmltopdf');
$pdf->generate('https://example.com', 'output.pdf');

// After: URLSnap
$response = file_get_contents(
    'https://urlsnap.dev/api/pdf?url=https://example.com&format=A4&apiKey=YOUR_KEY'
);
file_put_contents('output.pdf', $response);

Works Everywhere wkhtmltopdf Doesn't

URLSnap PDF API Reference

GET https://urlsnap.dev/api/pdf

# Required
url=https://example.com     # URL to convert to PDF
apiKey=YOUR_API_KEY

# Optional
format=A4                   # A4 (default), Letter, Legal, A3, A5, Tabloid
landscape=true              # landscape orientation
delay=1000                  # wait N ms after page load (for JS-rendered content)
Response: Raw PDF bytes with Content-Type: application/pdf. Save directly to a file or stream to your users. JavaScript is executed before PDF generation — React, Vue, Angular pages render correctly.

Pricing

URLSnap is cheaper than maintaining your own wkhtmltopdf install — especially when you factor in the ops time:

The free tier alone is enough to evaluate the output quality and prove your migration works before committing a cent.

Ready to replace wkhtmltopdf?

Get your free API key in 30 seconds. 20 PDFs/day free, no credit card. Works from any language or framework.

Get Free API Key View Docs

FAQ

Does URLSnap execute JavaScript like a real browser?

Yes. URLSnap uses headless Chromium — a full modern browser engine. JavaScript runs, CSS Grid and Flexbox render, web fonts load, and SPAs built with React or Vue render correctly. Use ?delay=2000 if your page has async data loading that needs time to complete before PDF generation.

Can I generate PDFs from HTML strings, not just URLs?

The current API accepts URLs. For HTML-to-PDF from a string, host your HTML template on your own server (even a local one tunneled via ngrok during development) and pass the URL to URLSnap. This keeps the API simple and stateless.

What about wkhtmltoimage for screenshots?

URLSnap covers that too — the /api/screenshot endpoint converts any URL to PNG or JPEG, with full JavaScript rendering. It's a complete replacement for both wkhtmltopdf and wkhtmltoimage.

What if my pages need authentication?

For publicly accessible pages, URLSnap works perfectly. For pages behind login, generate a one-time-use public URL or use a pre-signed token in your URL. Pages that can be accessed without credentials are the primary use case.

Is there a wkhtmltopdf wrapper library for URLSnap?

You don't need one — URLSnap is a plain REST API, far simpler than wkhtmltopdf's CLI interface. A single fetch() or requests.get() call is all you need in any language.