Benchmark
This benchmark compares HTML-to-PDF conversion over HTTP. Each engine receives the same HTML corpus and the same load profile: 20 concurrent clients for 30s, after 50 warmup requests.
The current run was measured on 2026-06-01 on a MacBook Pro with an M1 Max.
It uses WeasyPrint 63.1 in its pdf/ua-1 variant and
Gotenberg 8.33.0 through both its Chromium and LibreOffice
converters. Treat the numbers as a repeatable local snapshot, not a universal
ranking.
For this benchmark, pdf-ua-api is called with embedColorProfile set to
false. That keeps PDF/UA tagging enabled
but omits the PDF/A output intent, which makes the size comparison easier to
read. The API default remains true.
small document
| Engine | Req/s | p50 | p99 | PDF/UA-1 | Size |
|---|---|---|---|---|---|
| pdf-ua-api | 247 | 72 ms | 254 ms | Pass | 17.5 KB |
| WeasyPrint | 33 | 606 ms | 1011 ms | Pass | 7.6 KB |
| Gotenberg Chromium | 21 | 914 ms | 1607 ms | Fail | 16.7 KB |
| Gotenberg LibreOffice | 7 | 3050 ms | 3432 ms | Fail | 23.4 KB |
medium document
| Engine | Req/s | p50 | p99 | PDF/UA-1 | Size |
|---|---|---|---|---|---|
| pdf-ua-api | 155 | 116 ms | 388 ms | Pass | 34.5 KB |
| WeasyPrint | 14 | 1519 ms | 7306 ms | Fail | 14.5 KB |
| Gotenberg Chromium | 21 | 936 ms | 1770 ms | Fail | 23.5 KB |
| Gotenberg LibreOffice | 7 | 3346 ms | 3465 ms | Fail | 29.9 KB |
large document
| Engine | Req/s | p50 | p99 | PDF/UA-1 | Size |
|---|---|---|---|---|---|
| pdf-ua-api | 58 | 320 ms | 862 ms | Pass | 52.7 KB |
| WeasyPrint | 8 | 2424 ms | 4388 ms | Fail | 26.2 KB |
| Gotenberg Chromium | 23 | 814 ms | 2436 ms | Fail | 42.0 KB |
| Gotenberg LibreOffice | 6 | 3563 ms | 3991 ms | Fail | 58.0 KB |
What the numbers say
Section titled “What the numbers say”- Throughput. pdf-ua-api is the fastest engine in this run for the small, medium, and large documents. Gotenberg Chromium outpaces WeasyPrint on the large mixed fixture. Gotenberg LibreOffice is slower for this HTML corpus.
- Accessibility. pdf-ua-api passes PDF/UA-1 for every fixture in the corpus. WeasyPrint passes on the simplest document and fails validation on the two more structured fixtures. Gotenberg is measured as a rendering baseline here; these routes are not producing PDF/UA output.
- File size. The size column is measured with pdf-ua-api’s color profile disabled. That removes the PDF/A output intent from this comparison while keeping tags enabled. With the normal API default, pdf-ua-api files are larger because they contain the ICC profile, PDF/A output intent, and accessibility tag tree in one PDF.
Methodology
Section titled “Methodology”All engines run as HTTP services in Docker. pdf-ua-api and WeasyPrint receive
JSON requests. Gotenberg Chromium receives the same HTML as a multipart
index.html upload with preferCssPageSize=true and printBackground=true.
Gotenberg LibreOffice receives the same HTML as a multipart document.html
upload through the LibreOffice conversion route. pdf-ua-api’s rate limiter is
disabled for the run so the load test measures renderer throughput, not request
throttling.
The corpus has three document shapes: a small text document, a medium invoice, and a larger mixed report with paragraphs, figures, callouts, and a limited number of tables. The large fixture is not a table stress test.
The containers ship Liberation Sans, so font choice is not the main size
variable. Throughput and latency come from
oha. Every output PDF is validated by
pdf-ua-api’s veraPDF /validate endpoint. File size is the output PDF byte
length.
Run it yourself
Section titled “Run it yourself”cd benchmarkmake benchmarkThe full harness — corpus, services, and runner — lives in
benchmark/.