AIIPWorld

A wkhtmltopdf alternative: headless Chromium over an API

wkhtmltopdf's own status page and repository tell you where the project stands. This guide maps its common options to a headless Chromium PDF API and shows the same job as code you can run.

Why people are moving

None of this means your existing PDFs are wrong. It is a reason to plan a move, and to test your own templates before you do.

Option mapping

wkhtmltopdf options are from its usage page (wkhtmltopdf.org/usage/wkhtmltopdf.txt, checked 2026-10-09). The API options go inside options of POST /v1/render.

wkhtmltopdfAPI optionNote
-s, --page-size A4format: "A4"Also width and height for custom sizes (wkhtmltopdf: --page-width, --page-height).
-O Landscapelandscape: true
-T / -B / -L / -Rmargin: { top, bottom, left, right }wkhtmltopdf lists a default of 10 mm for left and right. Ours defaults to 10 mm on all four sides.
--print-media-typemedia: "print"wkhtmltopdf uses screen styles unless you pass this flag. Ours prints with print styles by default, so send media: "screen" to keep the wkhtmltopdf behaviour.
--background / --no-backgroundprint_background: true | falseOn by default in both.
--javascript-delay <ms>delay_ms (up to 10000)Also wait_until and wait_for_selector. These are not exact equivalents.
--header-html, --footer-htmldisplay_header_footer: true, header_template, footer_templateTemplates are HTML strings. Page numbers use spans with the classes pageNumber and totalPages. Leave room in the margins.
--zoom <float>scaleThe closest equivalent. Check the result against your layout.
--disable-smart-shrinkingno direct equivalentCompare your output and adjust the CSS.

Before and after

A typical wkhtmltopdf call:

wkhtmltopdf --page-size A4 --orientation Portrait \
  --margin-top 20mm --margin-bottom 20mm --margin-left 15mm --margin-right 15mm \
  report.html report.pdf

The same job against the API. Set AIIPWORLD_API_KEY to a key from your dashboard. The cURL version needs jq.

import { readFile, writeFile } from "node:fs/promises";

const API = "https://api.aiipworld.com";
const headers = { Authorization: `Bearer ${process.env.AIIPWORLD_API_KEY}`, "Content-Type": "application/json" };

const html = await readFile("report.html", "utf8");
const submit = await fetch(`${API}/v1/render`, {
  method: "POST",
  headers,
  body: JSON.stringify({
    html,
    output: "pdf",
    options: {
        "format": "A4",
        "landscape": false,
        "media": "screen",
        "margin": { "top": "20mm", "bottom": "20mm", "left": "15mm", "right": "15mm" }
      },
  }),
});
const { job_id } = await submit.json();

let job;
do {
  await new Promise((r) => setTimeout(r, 500));
  job = await (await fetch(`${API}/v1/jobs/${job_id}`, { headers })).json();
} while (job.status === "queued" || job.status === "running");

if (job.status !== "succeeded") throw new Error(`${job.status}: ${job.error}`);
const pdf = await (await fetch(job.download_url)).arrayBuffer();
await writeFile("report.pdf", Buffer.from(pdf));

Headers and footers: add display_header_footer: true with header_template and footer_template, as in the PDF API example. The sample below was made that way.

Example output

PDF with header and page number footer (page 1)
Output of the request in this guide. Generated by this site's own engine. Page 1 shown. Open the PDF.

Things to check when you switch

Prefer to run it yourself? Headless Chromium driven by Playwright or Puppeteer is the common self-hosted route. Our HTML to PDF tool lets you try the output without an account.

Questions

Is wkhtmltopdf still maintained?

Its GitHub repository was archived by the owner on 2 January 2023 and is read-only (checked 2026-10-09 on github.com/wkhtmltopdf/wkhtmltopdf). Its status page also says it uses Qt WebKit, which was deprecated in 2015 and removed in 2016, and advises against using it with untrusted HTML (wkhtmltopdf.org/status.html, checked 2026-10-09).

Will my existing HTML render the same?

Not necessarily. The rendering engine is different, so layouts can shift. Run your real templates through both and compare before you switch, and fix differences in your CSS.

How do I convert a local HTML file with relative images and CSS?

The API loads public http and https addresses only, not files on your machine. Inline images and styles with data URLs, point them at absolute https URLs, or send base_url so relative paths resolve against a public site.

Are my fonts available?

Fonts installed on your own server are not on ours. The render server has the Noto and Liberation font families and colour emoji. For other fonts, load them with @font-face from a public URL or a data URL.

Do I have to send my HTML to a third party?

With the API, yes: the HTML is sent to our servers and deleted after the retention period of your plan. If that is not acceptable for your documents, running headless Chromium yourself is the alternative.

How do page numbers work?

Pass footer_template HTML containing spans with the classes pageNumber and totalPages, set display_header_footer to true and leave room in the top and bottom margins.

Related tools