wkhtmltopdf alternative: html2pdf.app compared
Facts checked on . html2pdf.app is not affiliated with the wkhtmltopdf project.
wkhtmltopdf is no longer maintained: its repository was archived on 2 January 2023, its last release is 0.12.6 from June 2020, and its own documentation warns against using it with untrusted HTML. html2pdf.app is a hosted HTML to PDF API that renders with Chromium, so you send HTML or a URL in one HTTPS request instead of installing and patching a binary. wkhtmltopdf is still the better choice if you need to convert offline, at no cost, or without sending documents to anyone else.
What happened to wkhtmltopdf
wkhtmltopdf is an open-source command-line tool, licensed under the LGPL v3, that renders HTML to PDF with the Qt WebKit engine. Libraries such as pdfkit for Python, Snappy for PHP and wicked_pdf for Ruby on Rails run it for you. It was free, ran anywhere and was the default choice for years.
- Repository
- Archived on 2 January 2023 and read-only. GitHub
- Last release
- 0.12.6, published on 10 June 2020. Release notes
- Rendering engine
- Qt WebKit, which “hasn't been updated since 2012”. Status page
- Security
- CVE-2022-35583, a server-side request forgery flaw rated 9.8 (critical), with no later release. NVD
The project's status page advises: “Do not use wkhtmltopdf with any untrusted HTML”. For pages that rely on JavaScript it suggests Puppeteer, and for reports built from HTML you control, WeasyPrint or Prince.
wkhtmltopdf and html2pdf.app side by side
| wkhtmltopdf | html2pdf.app | |
|---|---|---|
| Maintenance | Archived since 2 January 2023. Last release 0.12.6, June 2020. | Maintained. Changes are listed in the changelog. |
| Rendering engine | Qt WebKit, last updated in 2012. | Chromium (headless Chrome). |
| Security fixes | None since June 2020. CVE-2022-35583 (critical) is unfixed. | You don't run a browser yourself; html2pdf.app runs the rendering service. |
| Where it runs | On your servers, from a binary you install. | A hosted API. Documents are processed on servers in the EU and are not permanently stored. |
| Headers and footers | --header-html, --footer-html with page variables. | Header and footer templates with page numbers. |
| Password protection | Not in the documented options. | Passwords and permissions. |
| Pages behind a login | Cookies, custom headers and HTTP login. | Not available: public URLs only, or send the HTML. |
| Table of contents | Generated table of contents and PDF outline. | Not available. |
| Cost | Free and open source. You pay for the servers that run it. | 100 free credits a month, then from $9 a month for 1,000 credits. |
Which one to choose
When wkhtmltopdf is the better choice
- Documents must not leave your servers, or you need to convert offline.
- You convert large volumes of HTML that you control, and you already run wkhtmltopdf in an isolated environment.
- The pages you convert sit behind a login and you rely on cookies or custom headers to fetch them.
- You need a generated table of contents or PDF outline.
When html2pdf.app is the better choice
- You want a Chromium renderer instead of an engine last updated in 2012, especially for pages built with modern CSS and JavaScript.
- You would rather not install, isolate and update a binary and its fonts on every server.
- Your application converts HTML that users can influence. wkhtmltopdf's maintainers advise against that, and with an API the rendering does not happen on your servers.
- You need password-protected PDFs, which wkhtmltopdf does not offer.
Other wkhtmltopdf alternatives
If your documents must stay on your own servers, you do not have to stay on an archived tool. These maintained tools replace wkhtmltopdf on your own infrastructure, and each released a new version in September or October 2026. Other hosted APIs are not listed here.
| Tool | What it is | Runs JavaScript | License | Choose it if |
|---|---|---|---|---|
| Puppeteer | Node.js library that drives Chrome or Firefox | Yes | Apache-2.0 | Your code runs on Node.js and you can run and update a browser on your servers. |
| Playwright | Browser automation library for JavaScript, Python, Java and .NET, which makes PDFs with headless Chromium | Yes | Apache-2.0 | You want headless Chromium from Python, Java or .NET, not only Node.js. |
| Gotenberg | Docker image with an HTTP API, using Chromium for HTML and LibreOffice for Office files | Yes | MIT | You want an HTTP API on your own infrastructure, or you also convert Word, Excel or PowerPoint files. |
| WeasyPrint | Python library and command-line tool with a CSS layout engine written for pagination | No | BSD-3-Clause | Your HTML needs no JavaScript and you want print CSS such as running headers and footnotes. |
| Prince | Commercial HTML to PDF converter for servers and desktops | Partly: off by default, mostly ES5 | Commercial. Free for non-commercial use, with a logo on the first page | You publish print-quality documents such as books or reports and can pay for a license. |
| html2pdf.app | Hosted API that renders with Chromium | Yes | Paid service, with 100 free credits a month | You would rather not run a browser or converter on your servers at all. |
Map your wkhtmltopdf options
Most wkhtmltopdf options have a direct equivalent. Send them as JSON in a POST request to https://api.html2pdf.app/v1/generate, with your API key in the X-API-Key header. The html parameter takes either a public URL or the HTML itself.
See every parameter in the documentation and the size and plan limits under Limits.
Migrate your code
Each example converts a URL. To convert HTML you generate yourself, put the markup in html instead.
Command line
A wkhtmltopdf command such as this one:
wkhtmltopdf --page-size A4 -O Landscape --print-media-type \
https://example.com document.pdfbecomes a single request:
curl -X POST https://api.html2pdf.app/v1/generate \
-H 'Content-Type: application/json' \
-H 'X-API-Key: <your-api-key>' \
-d '{
"html": "https://example.com",
"format": "A4",
"landscape": true,
"media": "print"
}' \
--output document.pdfPython: replacing pdfkit
With pdfkit, wkhtmltopdf options go in a dictionary:
import pdfkit
options = {
'page-size': 'A4',
'orientation': 'Landscape',
'margin-top': '10mm',
'margin-bottom': '10mm',
'print-media-type': None,
}
pdfkit.from_url('https://example.com', 'document.pdf', options=options)With html2pdf.app the same options go in the JSON body. The 10 mm margins become 38 pixels, and the API key comes from an environment variable:
import os
import requests
response = requests.post(
"https://api.html2pdf.app/v1/generate",
headers={"X-API-Key": os.environ["HTML2PDF_API_KEY"]},
json={
"html": "https://example.com",
"format": "A4",
"landscape": True,
"marginTop": 38,
"marginBottom": 38,
"media": "print",
},
timeout=60,
)
response.raise_for_status()
with open("document.pdf", "wb") as file:
file.write(response.content)Where you used pdfkit.from_string(), send the HTML string in html. More examples are in the Python guide.
PHP: replacing Snappy
With Snappy, each wkhtmltopdf option is set on the generator:
<?php
use Knp\Snappy\Pdf;
$snappy = new Pdf('/usr/local/bin/wkhtmltopdf');
$snappy->setOption('page-size', 'A4');
$snappy->setOption('orientation', 'Landscape');
$snappy->setOption('margin-top', '10mm');
$snappy->setOption('margin-bottom', '10mm');
$snappy->setOption('print-media-type', true);
$snappy->generate('https://example.com', '/tmp/document.pdf');With html2pdf.app the options go in the JSON body and the PDF comes back in the response:
<?php
$payload = json_encode([
'html' => 'https://example.com',
'format' => 'A4',
'landscape' => true,
'marginTop' => 38,
'marginBottom' => 38,
'media' => 'print',
]);
$curl = curl_init('https://api.html2pdf.app/v1/generate');
curl_setopt_array($curl, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'X-API-Key: ' . getenv('HTML2PDF_API_KEY'),
],
]);
$pdf = curl_exec($curl);
$status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
if ($status !== 200) {
throw new RuntimeException("PDF generation failed with status $status: $pdf");
}
file_put_contents('/tmp/document.pdf', $pdf);Where you used generateFromHtml(), send the HTML in html. More examples are in the PHP guide.
Every language
If your code calls wkhtmltopdf through one of these libraries, the guide for your language has complete html2pdf.app examples, from a first request to a callback.
| Language | wkhtmltopdf library | html2pdf.app guide |
|---|---|---|
| Python | pdfkit | Python guide |
| PHP | Snappy | PHP guide |
| Node.js | wkhtmltopdf (npm package) | Node.js guide |
| Ruby | wicked_pdf | Ruby guide |
| Java | java-wkhtmltopdf-wrapper | Java guide |
| C# / .NET | DinkToPdf | C# / .NET guide |
| Go | go-wkhtmltopdf | Go guide |
Frequently asked questions
Is wkhtmltopdf still maintained?
No. Its repository was archived on 2 January 2023 and is read-only, and the last release, 0.12.6, came out on 10 June 2020.
Is wkhtmltopdf safe to use?
Only with HTML you fully control. Its maintainers advise against converting untrusted HTML, and CVE-2022-35583, a critical server-side request forgery flaw in 0.12.6, has no fix from the project.
What are the free alternatives to wkhtmltopdf?
Puppeteer, Playwright and Gotenberg convert with a headless browser on your own servers, and WeasyPrint converts HTML that needs no JavaScript. All four are open source and maintained. See other wkhtmltopdf alternatives.
Can html2pdf.app convert HTML that is not on a public URL?
Yes. Put the HTML itself in the html parameter, up to 5 MB per request.
How do I add page numbers?
Use a footerTemplate containing <span class="pageNumber"></span> and <span class="totalPages"></span>, and set a bottom margin to make room for it.
What does html2pdf.app cost?
100 free credits a month, then from $9 a month for 1,000 credits. Each 5 MB of a generated PDF uses one credit. See all plans.