HTML to PDF — one API call instead of running your own Headless Chrome
Convert any HTML (incl. CSS, web fonts, images and tables) into a clean PDF. Optionally on your company stationery, optionally PDF/A-compliant — always without deploying your own browser.
What it does
The API accepts an HTML string (or a URL) and returns a PDF. The rendering engine handles modern CSS — Flexbox, Grid, web fonts, @media print — just like a recent Chromium, only server-side and stateless.
Minimal request
curl -X POST https://api.dokmatiq.com/v1/convert/html-to-pdf \
-H "Authorization: Bearer $DOKMATIQ_KEY" \
-H "Content-Type: application/json" \
-d '{
"html": "<!doctype html><html><body><h1>Invoice 2026-0042</h1><p>Total: €960.00</p></body></html>",
"format": "A4",
"margins": { "top": "20mm", "bottom": "20mm", "left": "20mm", "right": "20mm" }
}' \
-o invoice.pdf
Response: Content-Type: application/pdf, status 200, body = finished PDF.
Common options
{
"html": "...",
"format": "A4",
"orientation": "portrait",
"margins": { "top": "20mm", "bottom": "20mm", "left": "20mm", "right": "20mm" },
"header": { "html": "<div style=\"font-size:9pt\">Invoice 2026-0042</div>", "height": "15mm" },
"footer": { "html": "<div style=\"font-size:9pt\">Page <span class=\"pageNumber\"></span> of <span class=\"totalPages\"></span></div>", "height": "15mm" },
"outputProfile": "PDF/A-3b",
"waitUntil": "networkidle0"
}
For stationery overlay: set the matching content areas in the DocGen request (stationery field) rather than in the HTML — keeping the HTML free of layout and letting the stationery be exactly what the design agency delivered.
Input limits
| Limit | |
|---|---|
| Maximum HTML size | 25 MB |
| Maximum response size | 200 MB |
| Render timeout | 60 s |
| External URLs (images, fonts) | follows https:// and data: |
| JavaScript execution | opt-in via executeJs: true |
By default the API renders without JavaScript execution — significantly faster and more predictable than a full headless browser. If you need dynamic content (charts, client-side rendering), enable it via a flag.
What it’s used for
- Invoice PDFs from template engines like Liquid, Handlebars, Twig
- Reports from dashboard templates that already render HTML
- Email attachments (order confirmation, shipping notification) from existing mail templates
- Business letters on company stationery, generated from CMS content
- Datasheets, quotes, contracts from structured data
Comparison with alternatives
| Dokmatiq HTML-to-PDF | Own Headless Chrome | wkhtmltopdf | Pandoc | |
|---|---|---|---|---|
| Setup time | 1 API call | container, browser, queue | install binary | install binary |
| Modern CSS (Grid, Flex) | yes | yes | partial | limited via LaTeX |
| Web fonts | yes | yes | yes | limited |
| Scaling | API-side | on you | on you | on you |
| Stationery overlay | yes (via stationery) | build yourself | no | no |
| PDF/A output | direct flag | extra post-processing | extra post-processing | via LaTeX |
| JS rendering | opt-in | always | no | no |
A self-hosted Chrome is almost always tempting — until the first pod goes OOM, a font request hangs, or Chrome ships a breaking update. That’s when the operational cost shows up.
Common pitfalls
- Web fonts not loaded — force
waitUntil: "networkidle0"or embed fonts asdata:URLs - Page breaks ignored — set
page-break-after: alwaysorbreak-after: page(modern CSS) explicitly - Relative URLs — the API doesn’t know which domain the HTML originated from; switch images/fonts to absolute URLs
- Header/footer too small — header and footer HTML render at a smaller scale; set
font-sizeexplicitly (at least 8–9pt)
Try it now
100 conversions per month for free. No credit card. Stateless REST — you send, you receive.