A feature comparison of the PDF tools most often used from PHP. For the full tc-lib-pdf capability index, see /features/ .
Two classes of tool are compared separately, because they solve different problems: libraries that write PDF from PHP, and renderers that drive a browser engine and return its print output.
Versions, licences, and PHP requirements come from Packagist. Capabilities come from each project’s own documentation and source, cover what the package itself provides without third-party extensions, and were checked on 2026-08-31. Corrections are welcome: open an issue on tc-lib-pdf .
Table of contents
Packages
| Package | Version | PHP | Licence | Approach |
|---|---|---|---|---|
| tc-lib-pdf | 8.73 | ^8.2 | LGPL-3.0-or-later | Typed document API over a stack of focused packages |
| TCPDF (legacy) | 7.0 | >=8.2 | LGPL-3.0-or-later | Single-class library (Deprecated) |
| FPDF | 1.9 | none declared | Permissive, no attribution clause | Minimal primitive drawing and text |
| mPDF | 8.3 | ^5.6 to ~8.5 | GPL-2.0-only | HTML and CSS to PDF, FPDF-derived core |
| Dompdf | 3.1 | ^7.1 || ^8.0 | LGPL-2.1 | CSS 2.1 layout engine in PHP |
| HTML2PDF | 5.3 | ^7.2 || ^8.0 | OSL-3.0 | HTML front end built on legacy TCPDF |
| FPDI | 2.6 | >=7.2 | MIT | Page import add-on for FPDF, TCPDF, and others |
Capabilities
The legacy TCPDF is left out below: it is deprecated and not a candidate for new projects, so comparing against it would say nothing useful. HTML2PDF is left out for the same reason, since it wraps that codebase. FPDI is an import add-on rather than a generator, so it appears only in the import row.
| Capability | tc-lib-pdf | mPDF | Dompdf | FPDF |
|---|---|---|---|---|
| Font formats | TrueType, OpenType with TrueType outlines, Type1, CID-0, core | TrueType, TrueType collections, OpenType with TrueType outlines | TrueType and Type1; OpenType unreliable, CFF outlines unsupported | core fonts, TrueType and Type1 in single-byte encodings |
| Font embedding | full embedding, subsetting, or neither | embedding and subsetting | embedding and subsetting, unreliable for OpenType | embedding, no subsetting |
| Unicode text | full, Unicode 17 data, Identity-H with generated ToUnicode CMaps | full | full, with the bundled DejaVu fonts | only through the tFPDF fork |
| Characters above the BMP | with fonts converted for the full cmap subtable | all planes, with a less compact embedding | no | no |
| Bidirectional text | UAX #9, validated against the official conformance suite; rule L3 not implemented | yes, with OTL enabled | no | no |
| Complex-script shaping | Arabic by Joining_Type, Devanagari reordering, Hangul composition | OpenType Layout (GSUB and GPOS), font driven | no | no |
| HTML and CSS | wide subset: cascade and shorthands, selector combinators, pseudo-classes and pseudo-elements, floats and positioning, table layout, paged media, form controls mapped to widgets | wide subset, parts of CSS3 | CSS 2.1, parts of CSS3 | no |
| CSS flexbox and grid | no | no | no | no |
| SVG | paths, markers, text anchoring, style inheritance | gradients, clip paths and use; no filters, markers or patterns | basic, through php-svg-lib | no |
| Barcodes | linear and postal families, plus Aztec, Datamatrix, PDF417 and QR Code | linear and postal; QR needs mpdf/qrcode | no | no |
| PDF/A | parts 1, 2 and 3, at levels a, b and u | A-1b and A-3b | no | no |
| PDF/X | X-1a, X-3, X-4 and X-5 | X-1a | no | no |
| PDF/UA, tagged output | UA-1 and UA-2 | no | no | no |
| Factur-X, ZUGFeRD, Order-X | all four profiles, XMP extension schema written for you | attach the file and hand-build the XMP RDF yourself | no | no |
| Digital signatures | detached CMS, plus PAdES B-B to B-LTA | no | no | no |
| RFC 3161 timestamps | verified before embedding | no | no | no |
| LTV validation material | DSS and VRI, with OCSP and CRL each validated | no | no | no |
| Signing with an external key | two-phase, for HSM and remote keys | no | no | no |
| Encryption | RC4-40, RC4-128, AES-128, AES-256 R5 and R6 | RC4-40 and RC4-128 | RC4, through the CPDF adapter | no |
| Import existing PDF pages | built in, with box selection and N-up placement | through FPDI | no | through FPDI |
| Reproducible byte output | dates and file identifier pinnable | no | no | no |
| Typed enums for options | across the whole package stack | no | no | no |
| External runtime dependency | none | none | none | none |
Renderers That Delegate to a Browser
The following are not PHP PDF libraries: none of them writes a PDF in PHP. Each is a Composer package that you call from PHP and that hands the work to a program outside it. They are here because they are what a team weighs a library against when the document starts as HTML.
| Package | Version | Licence | What produces the PDF |
|---|---|---|---|
| Browsershot | 5.4 | MIT | Chromium, through Node and Puppeteer, spawned as a child process |
| Snappy | 1.7 | MIT | the wkhtmltopdf
binary, spawned as a child process |
| Gotenberg PHP | 2.25 | MIT | a Gotenberg HTTP service running Chromium and LibreOffice |
They are the right answer when the document is a web page and the layout depends on modern CSS. What you take on in exchange:
- A browser engine to install, patch, and keep running next to the application, or a service to operate and reach over the network.
- Output that changes when the engine updates, which rules them out where the same input has to produce the same bytes.
- Little control over the PDF itself. Conformance modes, signatures, spot colours, and page boxes are either absent or bolted on afterwards with a second tool.
- wkhtmltopdf specifically was archived upstream in January 2023 and renders with Qt WebKit, which predates most of CSS3.
A common arrangement is to use a renderer for marketing collateral and a library for the documents that carry legal or archival weight.