Shotkiln Get a free key
HTML to PDF API

HTML to PDF API

An HTML to PDF API turns HTML or a URL into a PDF. Shotkiln prints with headless Chromium, so CSS grid, web fonts and JavaScript charts come out the way Chrome prints them.

Endpoint
GET or POST /v1/pdf
Input
url (GET or POST) or html up to 1 MB (POST)
Paper
A3, A4, A5, Letter, Legal, Tabloid; portrait or landscape
Margins
one value or per side, in px, mm, cm or in (default 10mm)
Backgrounds
CSS backgrounds printed by default (print_background)
Privacy
PDFs from your HTML are cached only for your key; cache_ttl=0 keeps nothing
Price
same quota as screenshots: 100 free a month, $9 for 2,000

Generate an invoice PDF from HTML

Render your invoice template to HTML in your own code, then POST it. Set cache_ttl to 0 so the document is not kept.

nodeapplication/pdf
const html = renderInvoice(order); // your template
const res = await fetch("https://shotkiln.com/v1/pdf", {
  method: "POST",
  headers: { "x-api-key": process.env.SHOTKILN_KEY, "content-type": "application/json" },
  body: JSON.stringify({ html, format: "A4", margin: "18mm", cache_ttl: 0 }),
});
if (!res.ok) throw new Error((await res.json()).error.message);
await fs.writeFile(`invoice-${order.id}.pdf`, Buffer.from(await res.arrayBuffer()));

Convert a URL to PDF

For an existing page, pass the URL. This prints the page as Chrome would, using the site's print stylesheet if it has one.

curlapplication/pdf
curl "https://shotkiln.com/v1/pdf?url=https://en.wikipedia.org/wiki/PDF&format=Letter&landscape=true" \
  -H "x-api-key: $SHOTKILN_KEY" -o page.pdf

Print CSS that works

Chromium honours standard print CSS. These four rules cover most documents:

css
@page { size: A4; margin: 18mm; }
h2 { break-after: avoid; }
tr, figure { break-inside: avoid; }
@media print { .no-print { display: none; } }

The format and margin parameters override @page when both are set.

Limits

HTML bodies can be up to 1 MB. A page may load up to 25 MB of resources and 300 requests. The time budget is 20 seconds on the free plan and 30 seconds on paid plans. Free PDFs carry a small footer label; paid plans do not.

Frequently asked questions

Can I convert a URL to PDF as well as HTML?
Yes. Send url instead of html and Chromium prints the live page after its JavaScript runs. Use GET for URLs and POST for up to 1 MB of HTML.
Does JavaScript run before the PDF is printed?
Yes. Scripts run and the PDF prints after the load event. For charts or web fonts that draw later, add a delay of up to 10,000 ms.
How do I control page breaks, headers and margins?
Use print CSS: @page for size and margin, break-before and break-inside for breaks. The margin parameter sets all sides or each one; custom header and footer templates aren't supported yet.
Is the HTML I send stored?
Your PDF is cached for cache_ttl seconds, one hour by default, and only your key can receive it. Set cache_ttl=0 for invoices and nothing is kept after the response.
Can the HTML load images and fonts?
Yes, from public http and https URLs; private and localhost assets are blocked. For the most reliable output, inline small images and fonts as data URIs.

Related pages