Skip to content

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

EngineReq/sp50p99PDF/UA-1Size
pdf-ua-api24772 ms254 msPass17.5 KB
WeasyPrint33606 ms1011 msPass7.6 KB
Gotenberg Chromium21914 ms1607 msFail16.7 KB
Gotenberg LibreOffice73050 ms3432 msFail23.4 KB

medium document

EngineReq/sp50p99PDF/UA-1Size
pdf-ua-api155116 ms388 msPass34.5 KB
WeasyPrint141519 ms7306 msFail14.5 KB
Gotenberg Chromium21936 ms1770 msFail23.5 KB
Gotenberg LibreOffice73346 ms3465 msFail29.9 KB

large document

EngineReq/sp50p99PDF/UA-1Size
pdf-ua-api58320 ms862 msPass52.7 KB
WeasyPrint82424 ms4388 msFail26.2 KB
Gotenberg Chromium23814 ms2436 msFail42.0 KB
Gotenberg LibreOffice63563 ms3991 msFail58.0 KB
  • 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.

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.

Terminal window
cd benchmark
make benchmark

The full harness — corpus, services, and runner — lives in benchmark/.