mPDF vs Dompdf vs TCPDF
Written for mPDF 8.2 on PHP 8.1+. Updated 5 November 2026.
Three open-source libraries cover most PDF generation in PHP: mPDF, Dompdf and TCPDF. All three are installed with Composer, need no external programs, and run on ordinary shared hosting. They differ in how they think about a document. Dompdf is a small browser-style layout engine for HTML and CSS. TCPDF is a drawing API with an HTML import bolted on. mPDF sits in between: HTML and CSS in, with print features such as running headers, page numbering and barcodes built into the markup.
The short answer
- Pick mPDF if your documents are HTML templates that need print features: headers and footers with page numbers, tables that run over many pages, non-Latin languages (Arabic, Hebrew, Hindi, Chinese, Thai), or barcodes and QR codes.
- Pick Dompdf if you want the most “it just looks like my web page” behaviour for simple, Latin-script documents, and you like a small, permissively licensed (LGPL) dependency.
- Pick TCPDF if you are placing things at exact coordinates rather than flowing HTML, or need its specialist features: certificate-based digital signatures, PDF/A, or a very wide range of barcodes.
- Pick none of them if your layout depends on flexbox, CSS grid or modern web fonts behaving exactly as in Chrome. Use headless Chrome instead (see the end of this guide).
Side by side
| mPDF | Dompdf | TCPDF | |
|---|---|---|---|
| Composer package | mpdf/mpdf |
dompdf/dompdf |
tecnickcom/tcpdf |
| Licence | GPL 2.0 | LGPL 2.1 | LGPL 3.0 |
| How you build pages | HTML and CSS | HTML and CSS | PHP drawing calls, plus writeHTML() |
| CSS support | Most of CSS 2.1, some CSS3; no flexbox or grid | Most of CSS 2.1, some CSS3; no flexbox or grid | A small subset, mostly inline styles |
| Right-to-left and complex scripts | Good, with automatic font selection by language | Limited: no proper shaping for Arabic or Indic scripts | Good for RTL; shaping depends on the font and script |
| Headers, footers, page numbers | In the markup (<htmlpageheader>, {PAGENO}, {nbpg}) |
Through PHP canvas calls or fixed-position elements | Through PHP methods (Header(), Footer()) |
| Tables over several pages | Repeats <thead> and keeps rows together |
Repeats <thead>; very long tables are slow |
Basic, via writeHTML() |
| Barcodes and QR codes | <barcode> tag |
Not built in (use an image) | Many 1D and 2D types built in |
| Password protection | Yes | Yes (basic) | Yes |
| Digital signatures (certificates) | No | No | Yes |
| Typical problem | Memory use on huge documents | Speed and memory on long tables | Verbose code for HTML-style layouts |
“CSS support” here means what the layout engine understands when printing. None of the three runs JavaScript.
The same invoice in each
The test document is a short invoice: a heading, a table and a total, with UTF-8 text.
$html = '<h1>Invoice 1042</h1>
<table width="100%" border="1" cellpadding="6">
<thead><tr><th>Item</th><th align="right">Price</th></tr></thead>
<tr><td>Café consulting (2 h)</td><td align="right">€180.00</td></tr>
<tr><td><b>Total</b></td><td align="right"><b>€180.00</b></td></tr>
</table>';
mPDF
$mpdf = new \Mpdf\Mpdf(['format' => 'A4', 'tempDir' => sys_get_temp_dir() . '/mpdf']);
$mpdf->SetHTMLFooter('<div style="text-align:right">Page {PAGENO} of {nbpg}</div>');
$mpdf->WriteHTML($html);
$mpdf->Output('invoice-1042.pdf', \Mpdf\Output\Destination::INLINE);
The footer and page numbers are a single line of HTML. Fonts that cover the euro sign and accented letters are included, and switching to Arabic or Chinese text mostly needs 'autoScriptToLang' => true, 'autoLangToFont' => true in the config. See Fonts and languages and Headers, footers and page numbers.
Dompdf
use Dompdf\Dompdf;
$dompdf = new Dompdf();
$dompdf->loadHtml('<meta charset="utf-8">' . $html);
$dompdf->setPaper('A4', 'portrait');
$dompdf->render();
$font = $dompdf->getFontMetrics()->getFont('DejaVu Sans');
$dompdf->getCanvas()->page_text(500, 810, 'Page {PAGE_NUM} of {PAGE_COUNT}', $font, 9);
$dompdf->stream('invoice-1042.pdf', ['Attachment' => false]);
Page numbers are drawn in PHP after rendering, at coordinates in points. Dompdf’s default fonts only cover Western characters; for anything else, use DejaVu Sans (bundled) or load a font with @font-face. Loading images or stylesheets from URLs is off by default for security, and is turned on with the isRemoteEnabled option.
TCPDF
$pdf = new TCPDF('P', 'mm', 'A4', true, 'UTF-8');
$pdf->setPrintHeader(false);
$pdf->AddPage();
$pdf->SetFont('dejavusans', '', 11);
$pdf->writeHTML($html);
$pdf->Output('invoice-1042.pdf', 'I');
This works for a simple table, but writeHTML() understands far less CSS than the other two, so styled templates usually need rewriting. Custom headers and footers mean extending the TCPDF class and overriding Header() and Footer(). TCPDF’s strength shows when you skip HTML and draw with Cell(), MultiCell() and absolute positions, as on labels, tickets and forms that must line up with pre-printed paper.
Things that decide it
Your licence. mPDF is GPL 2.0. Using it inside a web application you run yourself is common and generally fine, but if you distribute software that includes it, the GPL’s conditions apply to that distribution. Dompdf (LGPL 2.1) and TCPDF (LGPL 3.0) are more permissive about being bundled. If this matters to your business, ask whoever handles licensing; this guide isn’t legal advice.
Languages. For Arabic, Hebrew, Persian, Hindi, Bengali, Thai or CJK text, mPDF is the safest of the three, because it chooses fonts by language and handles right-to-left layout in HTML. Dompdf will display many scripts with the right font, but joined and reordered scripts such as Arabic and Devanagari don’t come out correctly.
Long documents. All three hold the whole document in memory. For reports of hundreds of pages, generate in a queue job rather than during a web request, and see Performance and memory for mPDF’s settings for big tables.
Maintenance. mPDF and Dompdf both have active repositories and regular releases. TCPDF still gets fixes, but its author’s new work goes into a separate, rewritten library, tc-lib-pdf. Check each project’s page for the current state: mPDF, Dompdf and TCPDF on GitHub.
When none of them fits: headless Chrome
If your designers build documents with flexbox, grid, modern CSS and web fonts, a PHP layout engine will always be a step behind. The alternative is to have a real browser print the page: headless Chrome or Chromium, driven from PHP by a wrapper such as Browsershot (which uses Puppeteer) or by calling a service such as Gotenberg. The output matches Chrome’s Print → Save as PDF exactly. The costs are a much heavier install, slower generation and a server process to look after. The older wkhtmltopdf tool, which once filled this role, is no longer maintained and should not be used for new projects.
You can preview how a browser lays out your HTML as pages with our HTML to PDF tool, which uses your browser’s print engine. Templates from the examples gallery are written to work both there and in mPDF.
Next steps
- Install mPDF with Composer and make your first PDF.
- Supported CSS: what mPDF’s layout engine understands.
- Invoice example: a complete, styled template.