Turning HTML into a polished PDF, stamping and merging documents, or digitally signing contracts are everyday needs in PHP projects. The “best” library depends on your use case—HTML fidelity, performance, PDF/A compliance, digital signatures, RTL text, cost, and deployment constraints. This guide reviews the most-used options—dompdf, mPDF, TCPDF, FPDF, HTML2PDF, PDFlib, SetaPDF—and adds modern alternatives that use a real browser engine (wkhtmltopdf, Browsershot/Chrome headless) plus FPDI for importing/editing existing PDFs. You’ll also find clear recommendations by scenario, code snippets, and production checklists.
TL;DR — what to pick and when
- Standard invoices/reports from HTML:
mPDF or dompdf. mPDF is strong with long documents, tables, and RTL; dompdf wins on ease of use and a huge community. - Pixel-perfect layouts with advanced CSS (flex, some grid), webfonts, complex SVG:
wkhtmltopdf (with a PHP wrapper) or Browsershot (Chrome headless). These render like a real browser. Requires installing external binaries. - Draw-from-code, high performance, no HTML:
TCPDF (open source) or PDFlib (commercial) for speed and fine-grained control. - Digital signatures, PDF/A, forms, redaction, splitting/merging at scale:
SetaPDF (commercial, modular) or TCPDF for basic signing. - Import pages from existing PDFs and stamp/number/watermark:
FPDI (with FPDF/TCPDF/mPDF).
CSS Grid/Flex support is partial or absent in PHP HTML renderers. For pixel fidelity, use a browser engine (wkhtmltopdf/Chrome headless).
Expanded comparison table
Versions and minimum PHP requirements vary; check each library’s
composer.json
for your target version.
“HTML support” means how well it turns modern HTML/CSS into accurate layout.
Library | Open Source | HTML-based | OOP | Install via Composer | Docs | Key Dependencies | License | HTML/CSS Support | RTL / Complex scripts | PDF/A / Signing | Images / SVG | Typical Use |
---|---|---|---|---|---|---|---|---|---|---|---|---|
dompdf | Yes | Yes | Yes | Yes | Good | PHP 7/8, ext-dom , ext-mbstring , php-font-lib , php-svg-lib | MIT | CSS 2.1 + parts of CSS3; HTML5 partial | Decent | No native PDF/A / no signing | SVG basic | Easy start, popular for invoices/reports |
mPDF | Yes | Yes | Yes | Yes | Good | PHP 7/8, ext-mbstring , ext-gd | GPL | CSS 2.1 + partial HTML5; strong tables | Very good | PDF/A-1b/2b profiles; basic signing | Images + partial SVG | Long docs, RTL, enterprise invoicing |
TCPDF | Yes | Partial (HTML light) | Yes | Yes | Fair | PHP 7/8 | LGPL | Basic HTML (limited CSS) | Good | Digital signatures, barcodes, QR | Images + SVG | High speed drawing, precise control |
FPDF | Yes | No | Yes | No (manual) | Fair | Very light, no extensions | LGPL | N/A | – | No (extensions needed) | JPG/PNG | Minimal PDFs coded by hand |
HTML2PDF (spipu) | Yes | Yes | Yes | Yes | Good | PHP ≥ 5.6, ext-gd , ext-mbstring (uses TCPDF) | LGPL | Parser + TCPDF backend | Partial | Depends on TCPDF | Images | Simple pipeline; less active than mPDF/dompdf |
PDFlib | No | No | Yes | No | Excellent | PDFlib extension/SDK | Commercial | Draw API (no HTML) | – | Advanced features incl. signing | High | Fastest & feature-rich, but paid |
SetaPDF (Setasign) | No | No | Yes | Yes | Excellent | Composer modules | Commercial | No HTML rendering | – | PDF/A, signing, forms, redaction | High | Best-in-class PDF manipulation suite |
wkhtmltopdf (PHP wrappers) | Bin. external | Yes (WebKit) | – | Yes (wrapper) | Good | wkhtmltopdf binary | LGPL (bin), wrappers MIT | Near-browser fidelity | Yes | Depends | Excellent | Pixel-perfect print of web pages |
Browsershot (Chrome) | Wrapper | Yes (Chromium) | – | Yes | Good | Node.js + Chrome/Chromium | MIT | Full modern CSS (like Chrome) | Yes | Depends | Excellent | Highest fidelity; requires Node/Chrome |
FPDI | Core is OSS | No | Yes | Yes | Good | Needs FPDF/TCPDF/mPDF | MIT (+ add-ons) | N/A | – | No (core) | – | Import/compose existing PDFs |
Strengths and trade-offs by approach
A) Pure PHP HTML→PDF (dompdf, mPDF, HTML2PDF)
- Pros: easy deployment (no external binaries), good for invoices/reports, friendly with frameworks (Laravel/Symfony), predictable performance.
- Cons: incomplete support for modern CSS (grid/flex), some SVG/webfont quirks, edge cases with complex responsive layouts.
Pick mPDF when you need strong table handling, RTL, and basic PDF/A profiles. Pick dompdf for simplest onboarding and a huge community.
B) Real browser engines (wkhtmltopdf, Browsershot/Chrome headless)
- Pros: highest layout fidelity (what you see in a browser is what you get), excellent webfont/SVG support, advanced CSS.
- Cons: you must install binaries (wkhtmltopdf or Chrome), consider memory/timeouts, and harden execution for security.
Great for catalogs, brochures, marketing layouts, and any “pixel-perfect” design.
C) Code-driven drawing (TCPDF, FPDF, PDFlib)
- Pros: speed, deterministic output, millimetric control, no HTML conversion; supports barcodes, bookmarks, signatures.
- Cons: more development time for layout, less flexible for last-minute design changes.
TCPDF is the open-source workhorse; PDFlib is the fastest/most comprehensive commercial toolkit.
D) Manipulation, signing, and assembly (SetaPDF, FPDI)
- SetaPDF covers enterprise-grade needs: PDF/A, advanced digital signatures, form fields, redaction, repair, split/merge.
- FPDI is perfect for importing existing PDFs (official templates) and stamping on top with FPDF/TCPDF/mPDF.
Concrete recommendations by scenario
- Invoices, purchase orders, administrative PDFs (logos, tables, totals):
mPDF (tables/RTL/PDF-A) or dompdf (simplicity). If design fidelity is critical, wkhtmltopdf. - Long narrative reports (pagination, TOC, headers/footers):
mPDF; TCPDF if you don’t need complex HTML/CSS. - Compliance: PDF/A archiving, digital signatures, forms:
SetaPDF (best coverage) or TCPDF for basic signatures; PDFlib if performance/commercial support is a must. - Stamping official templates (import existing PDF, add text/seals/page numbers):
FPDI + FPDF/TCPDF/mPDF. - Pixel-perfect catalogs/marketing layouts mirroring the website:
Browsershot (Chrome) or wkhtmltopdf.
Minimal usage examples
dompdf (simple HTML→PDF):
use Dompdf\Dompdf;
require 'vendor/autoload.php';
$html = '<h1>Invoice #2025-001</h1><p>Total: €1.245,50</p>';
$dompdf = new Dompdf([
'isRemoteEnabled' => true,
'defaultFont' => 'DejaVu Sans',
]);
$dompdf->loadHtml($html, 'UTF-8');
$dompdf->setPaper('A4', 'portrait');
$dompdf->render();
$dompdf->stream('invoice-2025-001.pdf', ['Attachment' => true]);
Code language: PHP (php)
mPDF (tables, RTL, PDF/A profile):
$mpdf = new \Mpdf\Mpdf(['mode' => 'utf-8', 'format' => 'A4']);
$mpdf->PDFA = true; // enable PDF/A mode
$mpdf->PDFAauto = true;
$mpdf->WriteHTML('<style>table{border-collapse:collapse}td,th{border:1px solid #ccc;padding:6px}</style>');
$mpdf->WriteHTML('<table><tr><th>Item</th><th>Amount</th></tr><tr><td>Service</td><td>€1.245,50</td></tr></table>');
$mpdf->Output('report.pdf', 'I');
Code language: HTML, XML (xml)
TCPDF (draw from code):
$pdf = new TCPDF();
$pdf->AddPage();
$pdf->SetFont('dejavusans','',12);
$pdf->Cell(0,10,'Monthly Report',0,1);
$pdf->Output('report.pdf','I');
Code language: PHP (php)
wkhtmltopdf (PHP wrapper):
use mikehaertl\wkhtmlto\Pdf;
$pdf = new Pdf('<h1>Catalog</h1><p>Rendered by WebKit</p>');
$pdf->binary = '/usr/local/bin/wkhtmltopdf';
$pdf->setOptions(['enable-local-file-access' => true]);
if (!$pdf->send('catalog.pdf')) {
error_log($pdf->getError());
}
Code language: PHP (php)
FPDI (import an existing PDF and stamp text):
use setasign\Fpdi\Fpdi;
$pdf = new FPDI();
$pageCount = $pdf->setSourceFile('template.pdf');
for ($i = 1; $i <= $pageCount; $i++) {
$tplIdx = $pdf->importPage($i);
$pdf->AddPage();
$pdf->useTemplate($tplIdx);
$pdf->SetFont('Helvetica','',10);
$pdf->Text(20, 280, 'Stamped: '.date('Y-m-d'));
}
$pdf->Output('stamped.pdf', 'I');
Code language: PHP (php)
Original checklist (expanded)
Library | Open Source | HTML-based | OOP | Composer | Docs | Dependencies |
---|---|---|---|---|---|---|
dompdf | Yes | Yes | Yes | Yes | Good | PHP 7/8; ext-dom , ext-mbstring , php-font-lib , php-svg-lib |
FPDF | Yes | No | Yes | No | Fair | None (very light) |
HTML2PDF | Yes | Yes | Yes | Yes | Good | PHP ≥ 5.6; ext-gd , ext-mbstring (TCPDF backend) |
mPDF | Yes | Yes | Yes | Yes | Good | ext-mbstring , ext-gd ; PHP 7/8 |
TCPDF | Yes | No (HTML lite) | Yes | Yes | Fair | PHP 7/8 |
PDFlib | No | No | Yes | No | Excellent | PDFlib SDK (commercial) |
SetaPDF | No | No | Yes | Yes | Excellent | Composer modules (commercial) |
Recommended additions:
Library | Open Source | HTML-based | OOP | Composer | Docs | Dependencies |
---|---|---|---|---|---|---|
wkhtmltopdf (wrapper) | Wrapper OSS | Yes (WebKit) | – | Yes | Good | wkhtmltopdf binary |
Browsershot (Spatie) | Yes | Yes (Chrome) | – | Yes | Good | Node.js + Chrome/Chromium |
FPDI | Core OSS | No | Yes | Yes | Good | Works with FPDF/TCPDF/mPDF |
Production best practices
- Fonts & Unicode: ship DejaVu/Noto; subset fonts to shrink files.
- Images: optimize; use JPG for photos, PNG/SVG for graphics; cap at 300 dpi for print.
- Pagination: test long tables and multipage content; tune CSS (
page-break-*
). - Resources & timeouts: set sensible
memory_limit
and time limits; HTML rendering can be heavy. - Deterministic builds: embed fonts/CSS (no remote CDN) for legal/archival documents.
- Visual regression tests: keep “golden” PDFs and compare in CI to catch renderer version drift.
- Security: never render untrusted HTML without sanitization; sandbox external binaries.
Conclusion
- For reliable HTML→PDF with strong tables and RTL, mPDF is the most balanced generalist.
- For simplicity and community, dompdf is an excellent default.
- For pixel-perfect results, go with wkhtmltopdf or Browsershot (accepting the binary/Node requirement).
- For enterprise-grade manipulation (PDF/A, signing, forms, redaction), choose SetaPDF (or PDFlib if you want raw performance and can license it).
- For template stamping and assembling existing PDFs, FPDI is the right tool.
- For absolute control and speed without HTML, TCPDF or PDFlib (draw-API) are hard to beat.
The “best” library is the one that minimizes your maintenance cost for the job at hand. Balance fidelity, performance, compliance features, and operational constraints (binaries, hosting, CI/CD) before committing.