HTML to PDF API Comparison: Price and Print CSS
We earn commissions when you shop through the links below, at no extra cost to you. We only link products we would use ourselves.
Every HTML to PDF API is one of two things underneath, and which one you picked matters more than the price. Most are headless Chromium: same engine as your browser's print dialog, cheap, and limited to what Chromium's print pipeline supports. A few run a dedicated print engine (Prince, WeasyPrint), which costs 10 to 20 times more per document and can do paged-media things Chromium simply cannot. Pick the wrong side of that line and no amount of tuning fixes it.
Below: per-document prices from each vendor's public pricing page (checked August 14, 2026), real requests and responses against our own render API, and a print CSS test we ran on the live endpoint the same day, because the docs do not tell you which paged-media features actually land.
Per-document price, seven options
Prices are the entry plan and the cheapest published rate. "Per PDF" divides the monthly price by the included documents, which is the number that matters when you are choosing, not the sticker.
| Option | Engine | Entry price | Per PDF at entry | Cheapest published |
|---|---|---|---|---|
| Skillforge Render API | Chromium | $10 prepaid, 4,000 units | $0.005 (a PDF is 2 units) | $0.0042 ($50 / 24,000 units) |
| Api2Pdf | Chrome, wkhtmltopdf, LibreOffice | $1/mo + usage | about $0.0006 | same, metered per second |
| Browserless | Chromium | $25/mo, 20,000 units | about $0.00125 | $0.0015/unit overage |
| PDFShift | Chromium | $9/mo, 500 credits | $0.018 | $0.001 ($999 / 1M) |
| DocRaptor | Prince | $15/mo, 125 documents | $0.12 | $0.025 ($1,000 / 40,000) |
| Cloudflare Browser Rendering | Chromium, your code | $5/mo Workers Paid | about $0.0004 | $0.09 per browser hour |
| Gotenberg, self-hosted | Chromium + LibreOffice | $6 to $12/mo droplet | flat, unmetered | flat, unmetered |
Notes that change those numbers in practice:
- PDFShift counts one credit per document or per 5MB of generated data, and unused credits do not roll over month to month. A plan sized to your average month is a plan you overrun in your busiest one.
- Browserless meters units of browser time, not documents: one unit is a block of up to 30 seconds per connection. A typical PDF render fits in one unit, so units and documents roughly match, until a slow page or a reconnect costs you two. That $25 is the annual-billing rate; monthly billing costs more. The free tier is 1,000 units a month.
- DocRaptor is the outlier on price because it is the outlier on engine: it runs Prince, and it is the only hosted API we found that does. Unlimited free test documents make it cheap to evaluate before you commit.
- Api2Pdf is pay per use with a $1/month base: $0.00019551 per second of compute plus $0.001 per MB of bandwidth. A three second render of a small PDF lands around $0.0006, the cheapest hosted number in the table, with the least abstraction over the engine. It is also the only option here that will hand you wkhtmltopdf, which matters only if you have legacy templates written against it.
- Cloudflare is not a PDF product, it is the browser platform most of the cheap ones sit on. Workers Paid ($5/month) includes 10 browser hours, then $0.09 per additional hour, plus $2 per concurrent browser above a monthly average of 10. At roughly three seconds a render, those 10 included hours are about 12,000 PDFs. The free plan gives you 10 minutes of browser time a day and 3 concurrent browsers.
- Gotenberg is MIT-licensed, ships as one Docker image (
gotenberg/gotenberg:8) bundling Chromium and LibreOffice, and turns the whole question into a server bill. See the buy versus build math we ran for screenshots: it applies almost unchanged here.
What Chromium actually honors, tested
This is the part vendors do not document, so we tested it. We rendered the same three-section HTML document through our live /v1/pdf endpoint three times, changing only the @page rule, then inspected the returned PDF bytes (page count, page box, and the number of text-showing operators in the content streams). The harness is ops/render-pdf-probe.js in our repo.
| CSS we asked for | What came back |
|---|---|
break-before: page on each section | 3 pages. Page breaks work. |
@page { @bottom-center { content: "Page " counter(page) " of " counter(pages) } } | Byte-for-byte the same size as the no-footer baseline, same text-run count. The running footer never rendered. |
@page { size: A5 landscape } | Page box flipped to landscape, but stayed A4-sized: 842.88 x 595.92 pt. Orientation honored, size ignored. |
The Producer string in every PDF was Skia/PDF m128, which is the tell: this is a Chromium 128 build. CSS margin boxes (all 16 of them, plus counter(page) and counter(pages)) shipped in Chrome 131. Chromium 128 predates that, so on Cloudflare Browser Rendering today, margin-box footers are not available at all, no matter which API in front of it you are paying. That applies to our endpoint and to anything else built on the same platform, and it is the sort of thing that silently produces a PDF with no page numbers rather than an error.
Two features are not in any browser engine, at any version: string-set with content: string(), which is how you make a running header that repeats the current section title, and target-counter(), which is how you print "see page 14" in a table of contents. Those need Paged.js as a polyfill, or a real print engine like Prince or WeasyPrint. If your document has a table of contents with page numbers, you are on the Prince side of the line and DocRaptor's $0.12 per document is the actual price of the thing you need.
Real requests against a live endpoint
Every response below is from the deployed worker on August 14, 2026, not from a spec. Get a key with no signup (100 trial units, one key per IP per day):
curl -sX POST https://render.skillforge99.com/v1/keys \
-H 'content-type: application/json' -d '{}'
# {"apiKey":"sfr_..."}
Render HTML:
curl -X POST https://render.skillforge99.com/v1/pdf \
-H "Authorization: Bearer $RENDER_KEY" \
-H 'content-type: application/json' \
-d '{"html":"<h1>Invoice 1041</h1><p>Amount due: $240.00</p>"}' \
-o invoice.pdf
That returns 200 application/pdf, 15,558 bytes beginning %PDF-, with the billing state in the headers:
content-type: application/pdf
x-render-units: 2
x-credit-remaining: 98
A URL instead of HTML is the same call with {"url":"https://example.com"} (16,683 bytes in our run). Errors are JSON with a stable code, which is what you actually branch on:
{"error":{"code":"bad_params","message":"Provide exactly one of url, html"}}
{"error":{"code":"bad_url","message":"Private and internal hosts are not allowed"}}
{"error":{"code":"invalid_key","message":"invalid_key"}}
That second one is worth knowing before you build: an HTML to PDF API that will fetch any URL you hand it is a server-side request forgery engine pointed at your own network, so ours refuses private and internal hosts, IPv6 literals, and anything that is not http or https. If you self-host Gotenberg, that filtering is now your job.
Where our endpoint is deliberately thin today: format is pinned to A4 with backgrounds printed, and there are no parameters for margins, header and footer templates, or page ranges. Browserless, Cloudflare's REST endpoint (pdfOptions, headerTemplate, footerTemplate, pageRanges), and PDFShift all expose those. If you need per-request paper geometry, that is a real reason to pick one of them over us, and we would rather say so than have you discover it in production.
Choosing, in one pass
- A table of contents with page numbers, running headers from content, PDF/UA tagging, or mixed page sizes in one document: DocRaptor (Prince), or self-host WeasyPrint. Nothing Chromium-based will get you there.
- Under a few thousand documents a month, and you want it working this afternoon: any of the prepaid or metered Chromium APIs. Ours is $10 for 2,000 PDFs with credits that do not expire; Api2Pdf is cheaper per document if you would rather be metered by the second.
- Bursty volume where a monthly plan is a bad fit: prepaid credits or pay-per-use, not tiers. Overrunning a PDFShift or DocRaptor plan mid-month is the failure mode that makes people hate this category.
- Above roughly 3,000 documents a month, steady: the flat server wins. At our best rate, 3,000 PDFs is about $13 of credit, which is a 2GB DigitalOcean droplet running Gotenberg with room to spare. You take on Chromium patching, memory watching, and URL filtering in exchange.
- Already on Workers: Cloudflare Browser Rendering directly, and skip the middle layer. $5/month covers about 12,000 renders of browser time. You write the Puppeteer code, and you inherit the same Chromium 128 print limits we measured above.
- Need screenshots too: most of these do both. We compared that side separately in screenshot APIs without a subscription.
FAQ
Is there a genuinely free HTML to PDF API? Several, at small volume. PDFShift gives 50 credits a month with no card, DocRaptor 5 documents a month plus unlimited free test documents, Browserless 1,000 units a month, Cloudflare 10 minutes of browser time a day on the free plan, and ours mints a 100-unit trial key (50 PDFs) per IP per day with no signup. All of them are evaluation-sized, not production-sized.
Which HTML to PDF API supports headers and footers? Two different mechanisms, and only one is widely available. Chromium's own headerTemplate and footerTemplate print options work wherever the API exposes them (Cloudflare's REST endpoint, Browserless, PDFShift), and they are separate from your page CSS. CSS margin boxes (@bottom-center and friends) are the standards-based way, and they need Chrome 131 or newer, which as we measured is newer than what Cloudflare Browser Rendering currently runs. Prince has supported both for years.
Do I really need Prince or WeasyPrint? Only for content-derived paged media: headers that echo the current section, cross-references that resolve to page numbers, tagged accessible output, crop marks. If your document is an invoice, a receipt, a report, or a certificate with a fixed layout, Chromium is fine and you should not pay 20 times more per page for capability you will not use.
At what volume should I self-host instead? Compare the flat server bill to your per-document rate. Cheap Chromium APIs land between $0.0006 and $0.005 per PDF, so a $12/month droplet pays for itself somewhere between about 2,400 and 20,000 documents a month depending on which vendor you are comparing against. Below that band, buying is cheaper and you skip the ops. Above it, the crossover is real, and it is the point where memory limits and concurrency start to matter more than the price.