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 was built on an old Qt WebKit engine — essentially Internet Explorer-era browser technology. By modern web standards, it's severely limited:
| 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) |
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.
# 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)
// 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);
fetch().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)
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.
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.
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 DocsYes. 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.
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.
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.
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.
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.