Replaces mpdf + FPDI with a single MIT package — no GPL friction, and faster. Pure-PHP toolkit to generate, read, and merge PDFs: a GPL-free mpdf alternative for HTML→PDF and a free FPDI alternative for import/stamp — including xref-stream and encrypted sources. Migration is mechanical: from mpdf · from FPDI.
- Why this library
- Installation
- Quick start
- Feature highlights
- Documentation
- The php-pdf family
- Performance
- Requirements
- Testing
- License
Licensing. MIT is the most permissive PHP license — use the code anywhere, including closed-source products. Compare with the main PHP PDF stack:
| Library | License | OEM / proprietary bundle |
|---|---|---|
| dskripchenko/php-pdf | MIT | ✅ no friction |
| mpdf/mpdf | GPL-2.0-only | ❌ requires GPL bundle or commercial license |
| tecnickcom/tcpdf | LGPL-2.1+ | |
| dompdf/dompdf | LGPL-2.1 | |
| setasign/fpdf | re-licensable | ✅ but extras are proprietary |
Engineering.
- Modern PHP 8.2+ — readonly classes, enums, named arguments, strict types. Clean, type-safe API surface.
- Two-layer design —
Pdf\Documentfor low-level emission,Build\*fluent builders for high-level documents,Document::fromHtml()for HTML/CSS input. - Strong typography — Knuth–Plass line breaking, TTF subsetting with kerning, GSUB ligatures, ToUnicode CMaps, variable font instances, Bidi (UAX#9), Arabic shaping, basic Indic shaping, vertical writing.
- Widest barcode coverage — 12 linear + 4 2D formats including rare Pharmacode, MSI Plessey, ITF-14, EAN-2/5 add-ons.
- Production cryptography — RC4-128, AES-128, AES-256 (V5 R5 and R6 per ISO 32000-2 / PDF 2.0).
- PAdES signing (B-B, B-T with an RFC 3161 timestamp) — RSA, ECDSA and
GOST R 34.10-2012, PEM / PKCS#12 / your own
Signer(token, HSM), or two-phase signing outside the server (CryptoPro plug-in, HSM, signing service) — with a visible signature stamp filled from the certificate; sign existing PDFs incrementally (several signers, certification, field locks) and long-term validation (B-LT DSS, B-LTA document timestamps); signature validation against the known PDF signature attacks; detached CAdES signatures (.p7s) of any bytes, signed and verified. Ready-made signers for PKCS#11 tokens and HSMs (php-pdf-pkcs11), cloud KMS — AWS, Google, Azure (php-pdf-cloud-kms) — and CryptoPro CSP on the server (php-pdf-cryptopro). - PDF/A-1a, 1b, 2b, 2u and 3b (validated with veraPDF in CI) and PDF/X-1a / 3 / 4 conformance with embedded ICC profile and XMP metadata.
- Tagged PDF / PDF/UA-ready structure tree with H1–H6, Table/TR/TD, L/LI, custom RoleMap, ParentTree number tree.
- Streaming output to a stream resource for large documents.
- XRef streams (PDF 1.5+) and Object Streams for compact output.
composer require dskripchenko/php-pdfPHP 8.2 or later. Required extensions: mbstring, zlib, dom. Add
openssl for AES encryption or digital signatures.
use Dskripchenko\PhpPdf\Document;
$doc = Document::fromHtml(<<<'HTML'
<h1>Invoice #1234</h1>
<p>Customer: <strong>Acme Corp</strong></p>
<table>
<thead><tr><th>Item</th><th>Price</th></tr></thead>
<tbody>
<tr><td>Widget</td><td>$10.00</td></tr>
<tr><td>Gadget</td><td>$25.00</td></tr>
</tbody>
</table>
HTML);
$doc->toFile('invoice.pdf');use Dskripchenko\PhpPdf\Build\DocumentBuilder;
use Dskripchenko\PhpPdf\Build\RowBuilder;
use Dskripchenko\PhpPdf\Build\TableBuilder;
DocumentBuilder::new()
->heading(1, 'Quarterly report')
->paragraph('Q1 revenue exceeded the forecast by 12%.')
->table(function (TableBuilder $t) {
$t->headerRow(fn (RowBuilder $r) => $r->cells(['Quarter', 'Revenue']));
$t->row(fn (RowBuilder $r) => $r->cells(['Q1', '$330,000']));
$t->row(fn (RowBuilder $r) => $r->cells(['Q2', '$310,000']));
})
->toFile('report.pdf');use Dskripchenko\PhpPdf\Pdf\Document;
use Dskripchenko\PhpPdf\Pdf\StandardFont;
use Dskripchenko\PhpPdf\Style\PaperSize;
$doc = Document::new(PaperSize::A4);
$page = $doc->addPage();
$page->showText('Hello, world!', 72, 720, StandardFont::TimesRoman, 12);
file_put_contents('hello.pdf', $doc->toBytes());- HTML5 subset parser via
Document::fromHtml(). - Block tags
<p>,<h1>–<h6>,<ul>/<ol>/<li>, tables (with<thead>/<tbody>/<tfoot>and<caption>),<blockquote>,<hr>,<pre>,<dl>/<dt>/<dd>. - Inline tags
<b>/<strong>,<i>/<em>,<u>,<s>/<del>,<sup>/<sub>,<br>,<a>,<span>, plus<code>,<kbd>,<samp>,<tt>,<var>,<mark>,<small>,<big>,<ins>,<cite>,<dfn>,<q>,<abbr>. - HTML5 semantic blocks (
<header>,<footer>,<article>,<nav>,<section>, etc.) and legacy<center>/<font>. - CSS from
<style>blocks andstyleattributes, with the cascade: type, class, id and attribute selectors,:first-child,:last-child,:nth-child(),:not(), descendant />/+/~combinators, specificity,!important— no CSS inliner needed. @media printapplied,@media screenskipped;@pagesize and margins.- Inheritance as in a browser: color, font, text-align, line-height and
the like set on
body, adivor atdreach the text inside. divcontainers with margin, padding, background and border;display: flex(rows,flex-wrap,flex-direction: column,gap),display: grid(grid-template-columnswith lengths,%,fr,repeat(),minmax();grid-column: span n;gap),display: none.float: left / rightwithclear;position: absoluteandfixed(a fixed element repeats on every page);break-inside: avoidkeeps a block on one page.::before/::afterwithcontent(strings,attr(), quotes);<link rel="stylesheet">to local files anddata:URLs;font-familylists (the first family that can be used).- Table styles:
width,table-layout: auto,border-collapse/border-spacing, cellpaddingandvertical-align,<col>widths;<thead>rows repeat on every page. page-break-*/break-*,white-space: pre/pre-wrap/pre-line; solid, dashed, dotted and double borders.- Approximations: text beside a float does not run on under it;
position: relativeonly anchors its absolute children (its own offsets are not applied); remote style sheets are not fetched. Not supported:grid-template-areasand explicit row placement,@import,:hoverand other dynamic pseudo-classes.
- Knuth–Plass box–glue–penalty line breaker with adaptive penalty.
- Multi-column layout (
ColumnSet) with column-first flow. - Tables with rowspan, colspan, border collapse, double, dashed and dotted borders, border radius, cell padding.
- Headers, footers, watermarks (text and image), section breaks.
- Footnotes with page-bottom positioning.
- 14 Adobe base-14 fonts (WinAnsi).
- TrueType-outline fonts (
.ttf, TrueType-flavoured.otf) with on-demand subsetting; CFF-based OpenType (.otf) embedded whole, without subsetting; CFF2 (variable CFF) is not supported. - Kerning, basic GSUB ligatures, ToUnicode CMap.
- Variable font instances (fvar, gvar, MVAR, HVAR, avar).
- Bidi (UAX#9), Arabic shaping, basic Indic shaping.
- Ready-made Liberation bundle (metric-compatible Arial / Times New Roman / Courier New): dskripchenko/php-pdf-fonts-liberation.
- Linear: Code 128 (A/B/C auto, GS1-128), Code 39, Code 93, Code 11, Codabar, ITF/ITF-14, MSI Plessey, Pharmacode, EAN-13/EAN-8 with 2/5- digit add-ons, UPC-A, UPC-E.
- 2D: QR V1–V10 (Numeric, Alphanumeric, Byte, Kanji, ECI, Structured Append, FNC1), Data Matrix ECC 200 (all sizes incl. 144×144, rectangular, 6 modes), PDF417 (Byte/Text/Numeric, Macro, GS1, ECI), Aztec Compact 1–4L + Full 5–32L (Structured Append, FLG/ECI).
- QR convenience factories: vCard 3.0, WiFi (Joinware), URL, SMS,
email (
mailto:), geo location.
- BarChart, LineChart, PieChart, AreaChart, DonutChart, GroupedBarChart, StackedBarChart, MultiLineChart, ScatterChart.
- AcroForm widgets: text (single / multiline / password), checkbox, radio, combo, list, push / submit / reset buttons, signature.
- Per-field JavaScript actions (keystroke, validate, calculate, format).
- Markup annotations: Text, Highlight, Underline, StrikeOut, FreeText, Square, Circle, Line, Stamp, Ink, Polygon, PolyLine.
- Encryption: RC4-128, AES-128, AES-256 (V5 R5 + R6 / PDF 2.0).
- PAdES (
ETSI.CAdES.detached) or PKCS#7 detached signing with reason, location, signer name, certificate chain and RFC 3161 timestamps; signature stamps (text, images, QR) with certificate placeholders, several signature fields, invisible signatures. - Ready-made signers: PKCS#11 tokens and HSMs (php-pdf-pkcs11), AWS KMS, Google Cloud KMS and Azure Key Vault (php-pdf-cloud-kms), CryptoPro CSP on the server (php-pdf-cryptopro).
- PDF/A-1a, PDF/A-1b, PDF/A-2b, PDF/A-2u, PDF/A-3b with embedded sRGB ICC, validated with veraPDF in CI.
- PDF/X-1a, PDF/X-3, PDF/X-4 with /OutputIntent /S /GTS_PDFX.
- Tagged PDF / PDF/UA-ready structure tree.
- Read existing PDFs (
ReaderDocument) — classic and stream xref, object streams, corrupt-xref recovery, decryption (RC4 / AES-128 / AES-256). - Merge (
PdfMerger) — append and reorder whole or selected pages from multiple files; page annotations and bookmarks carried over with internal links and named destinations remapped. - Stamp overlays (watermarks, letterheads) and FPDI-style page import into a
freshly generated document via
PageImporter::intoDocument(). - See the reading & merging guide.
A complete usage walkthrough is in docs/en/USAGE.md.
- 📖 Usage guide — paragraphs, tables, charts, barcodes, forms, encryption, signing, PDF/A.
- ✍️ Digital signatures — PAdES and GOST signing,
stamps, signing outside the server (CryptoPro, HSM), existing PDFs and
several signers, certification, long-term validation, signature validation,
detached
.p7ssignatures. - 🔗 Reading & merging PDFs — read existing files, append/reorder pages, stamp overlays, handle encrypted input.
- ⚖️ Comparison vs mpdf / tcpdf / dompdf / FPDF — feature matrix, when to choose each.
- 📊 Benchmarks — reproducible wall-time, memory, and output-size measurements.
- ✅ Conformance — PDF/A validated with veraPDF, PDF/X checked with Ghostscript, renders diffed against goldens, and signatures verified with OpenSSL and pyHanko — on every push.
- 🔀 Migrating from mpdf — compat
facade (
WriteHTML/Outputkeep working) + full mapping table. - 🔀 Migrating from FPDI —
setSourceFile/importPage/useTemplatefacade; reads xref-stream and encrypted sources without a commercial parser.
Runnable scripts in examples/, outputs committed to
samples/ — every one is render-checked in CI:
| Run | Output | Shows |
|---|---|---|
php examples/01-html-to-pdf.php |
HTML/CSS subset → PDF | |
php examples/02-builder.php |
fluent builder, tables | |
php examples/03-barcodes.php |
QR, Code 128, EAN-13, DataMatrix | |
php examples/04-charts.php |
vector pie/bar/line charts | |
php examples/05-forms.php |
fillable AcroForm fields | |
php examples/06-signature.php |
PAdES digital signature with a visible stamp | |
php examples/07-pdfa.php |
PDF/A-2u (veraPDF-clean); needs scripts/fetch-fonts.sh |
|
php examples/08-merge.php |
append + reorder existing PDFs | |
php examples/09-stamp.php |
watermark/letterhead stamping |
The torture set exercises the hard paths (Arabic, CJK, rectangular DataMatrix, …) — see VIEWER-MATRIX.
| Package | What it adds |
|---|---|
| php-pdf (this package) | The core: HTML with CSS or a builder to PDF, read, merge, fill forms, sign and validate. |
| laravel-php-pdf | Laravel bridge: a Blade view straight to PDF, response()->pdf(), signing from config. |
| php-pdf-fonts-liberation | Liberation Sans, Serif and Mono, metric-compatible with Arial, Times New Roman and Courier New (OFL, kept out of the MIT core). |
| php-pdf-cryptopro | Signs with a key in CryptoPro CSP on the server: GOST R 34.10-2012, Russian qualified signatures. |
| php-pdf-pkcs11 | Signs with a key on an HSM, a smart card or a USB token, through PKCS#11. |
| php-pdf-cloud-kms | Signs with a key in AWS KMS, Google Cloud KMS or Azure Key Vault. |
Median of 5 isolated subprocess runs (environment and versions in the report). Full methodology and reproducer in docs/en/BENCHMARKS.md.
| Scenario | dskripchenko/php-pdf | mpdf | tcpdf | dompdf | FPDF |
|---|---|---|---|---|---|
| HTML → PDF article (~5 pages) | 15.2 ms | 61.9 ms | 38.0 ms | 48.1 ms | n/a |
| 100-page invoice (50 rows/page) | 632 ms | 2300 ms | 1342 ms | 9156 ms | 26.4 ms |
| Image grid (20 pages × 4 JPEGs) | 7.7 ms | 36.5 ms | 16.9 ms | 31.8 ms | 1.0 ms |
| Hello world (single page, one paragraph) | 5.0 ms | 29.4 ms | 15.0 ms | 11.7 ms | 0.9 ms |
FPDF wins on the simplest scenarios (no HTML, no wrapping, no table flow), but it cannot generate HTML→PDF and lacks UTF-8, charts, barcodes, forms, encryption, signing.
- PHP 8.2 or later.
- Required:
ext-mbstring,ext-zlib,ext-dom. - Optional:
ext-openssl(AES encryption and digital signatures). - No external binaries — pure PHP.
composer install
vendor/bin/phpunit2,480+ tests, ~120k assertions, run on PHP 8.2 / 8.3 / 8.4 / 8.5 in CI (see the tests workflow).
MIT — see LICENSE.
Copyright © 2026 Denis Skripchenko.