Table of contents

Many PHP applications end up needing to produce a PDF. An invoice, a shipping label, a course certificate, a signed contract, a monthly report. It is one of those unglamorous requirements that turns up on project after project, and it is rarely as simple as it first sounds.
I know, because I have been writing the code that does it for twenty-five years.
If you have generated a PDF from PHP at any point in the last two decades, there is a good chance some of my code was involved. TCPDF, the library I started in 2002, has been installed more than 109 million times through Composer alone, and it is a dependency of a long list of applications you already know. I have even found documents generated by TCPDF sitting on NASA’s own data-centre websites. More on that below.
That library has now reached the end of its road, and it has a successor: tc-lib-pdf. This is the story of how we got from there to here, and why the new library deserves your attention.
The problem that started it all
In 2001 I was building AIOCP, the “All In One Control Panel,” a PHP and MySQL web content management system (CMS) with e-commerce features. (AIOCP is still on SourceForge if you want to see where this began.) Like every e-commerce system, it had to produce invoices, and invoices meant PDFs.
The natural first choice was FPDF , Olivier Plathey’s elegant pure-PHP PDF class, first released in 2001. It was free, dependency-free, and a pleasure to use, so I adopted it immediately.
It did not take long to hit its limits. AIOCP was multilingual, and I needed proper UTF-8 Unicode support, including right-to-left languages and the bidirectional algorithm. I also wanted to lay out invoices from HTML rather than positioning every line by hand. FPDF, by design, offered none of that. The distance between what FPDF gave me and what real documents demanded is exactly what pushed me to build something more.
From FPDF to TCPDF
In 2002 I started extending FPDF into what became TCPDF, at first as code embedded directly inside AIOCP. I added real Unicode and right-to-left (RTL) support, HTML rendering, barcodes, encryption, and a great deal more. I released TCPDF as a standalone library on January 6, 2005, by which point it had already grown well beyond its FPDF starting point. Over the years that followed it was almost entirely rewritten.
Pulling it out of AIOCP and shipping it on its own changed everything. TCPDF spread far beyond the CMS it was born in, into a who’s-who of PHP software: learning platforms, customer relationship management (CRM) and enterprise resource planning (ERP) systems, billing systems, e-commerce engines, analytics tools. To this day you will find it as a dependency of projects such as Moodle, PrestaShop, SugarCRM and SuiteCRM, Dolibarr, WHMCS, vTiger, Matomo, EC-CUBE, and CiviCRM, among many others. On Packagist alone it is required by more than 500 packages .
I will not put a number on how many PDFs TCPDF has generated, because no reliable number exists. What I can tell you is that the reach is real and checkable, right up to some surprising places. Documents produced by TCPDF sit on the websites of United States federal agencies. NASA’s Langley Atmospheric Science Data Center publishes technical guides made with it, complete with figures and photographs, and the U.S. Geological Survey (USGS) generates its Water Resources Research annual reports with it too. You do not have to take my word for any of this. Open NASA’s guide to using AirMISR data or a USGS annual report and read the PDF producer metadata. It says TCPDF. I take no small amount of pride in that.
The weight of success
Success has a cost, and for TCPDF the cost was its architecture.
TCPDF grew into a single, enormous PHP file with more than twenty years of features layered on top of one another. It predated namespaces, predated Composer, and carried patterns from the PHP 4 era. Every new capability made the monolith harder to maintain, harder to test in isolation, and harder to keep secure. The deprecated package today carries several published security advisories , which is what you would expect from a large body of legacy code that the whole industry depends on.
I did not want the next twenty years to look like the last twenty. So I rebuilt it from the ground up.
tc-lib-pdf: the modern successor
tc-lib-pdf is the modern evolution of TCPDF. Instead of one giant file, it is a family of focused, independently versioned Composer packages, each with its own tests and a single clear responsibility, coordinated by the main tc-lib-pdf package:
tc-lib-pdf-fontfor font parsing, subsetting, and generationtc-lib-pdf-imagefor image embedding (JPEG, PNG, SVG, ICC)tc-lib-pdf-graphfor vector graphics, gradients, and transformstc-lib-pdf-pagefor the page model, boxes, and layouttc-lib-pdf-encryptfor encryption and signaturestc-lib-pdf-parserfor reading and importing existing PDFstc-lib-barcode,tc-lib-color,tc-lib-unicode, andtc-lib-filefor the rest
It is pure PHP, requires PHP 8.2 or later, is strictly typed, and is Composer-first from the ground up. The modularity earns its keep: each package can be tested, versioned, and reused on its own, which is what makes the whole thing maintainable over the long run. The monolith became a toolkit.
Generating a document looks like this:
<?php
require __DIR__ . '/vendor/autoload.php';
\define('K_PATH_FONTS', \realpath(__DIR__ . '/vendor/tecnickcom/tc-lib-pdf-font/target/fonts'));
$pdf = new \Com\Tecnick\Pdf\Tcpdf();
$bfont = $pdf->font->insert($pdf->pon, 'helvetica', '', 12);
$page = $pdf->addPage();
$pdf->page->addContent($bfont['out']);
$pdf->addHTMLCell(
html: '<h1>Hello, PDF!</h1><p>Generated with tc-lib-pdf.</p>',
posx: 15,
posy: 20,
width: 180,
);
$pdf->renderPDF($pdf->getOutPDFString());
What sets it apart
I am not going to line tc-lib-pdf up against every other PHP PDF library and claim it wins on every count. The pitch is narrower than that: very few libraries combine all of the following in a single pure-PHP package, and I am not aware of any that combine all of them and are still actively developed.
Standards compliance, the serious kind. tc-lib-pdf produces PDF/A (levels 1, 2, and 3, including a, b, and u conformance), PDF/X (1a, 3, 4, and 5) for print exchange, and PDF/UA (1 and 2) for accessibility. These are the formats archives, print houses, and public-sector procurement actually require.
Real HTML and CSS, with a real cascade. This is where tc-lib-pdf goes well beyond what legacy TCPDF could do. It ships a genuine CSS engine with a real cascade: selector specificity, !important handling, inheritance and shorthand propagation, class, id, and attribute selectors with combinators, @media rules, and reusable global stylesheets you register once with setGlobalCSS(). Tables support colspan and rowspan, nested tables, and header rows that replay with identical column geometry across page breaks. HTML forms map to real interactive PDF form fields. Content paginates, hyphenates in justified text, and even flows around no-write regions.
Print and prepress output. Many PHP tools emit RGB, screen-targeted PDFs that a commercial printer cannot use as-is. tc-lib-pdf speaks the language of print: cyan, magenta, yellow, and key (CMYK) and spot colours, International Color Consortium (ICC) colour profiles, overprint control, crop marks and registration bars, and full page-box control (Media, Crop, Bleed, Trim, Art) with genuine bleed and trim boxes.
Cryptographic signing that goes the distance. Detached Cryptographic Message Syntax (CMS, the PKCS#7 standard) digital signatures, RFC 3161 trusted timestamps from any compliant authority, and Long-Term Validation that embeds Online Certificate Status Protocol (OCSP) and Certificate Revocation List (CRL) revocation evidence directly in the document. This is the part most PHP libraries do not even attempt.
The fundamentals, done right. Native UTF-8 and RTL with the bidirectional algorithm, 1D and 2D barcodes, Factur-X and ZUGFeRD electronic invoicing through PDF/A-3, importing pages from existing PDFs, and security hardening such as Server-Side Request Forgery (SSRF) guards and host and path allowlists for remote assets.
There is a runnable examples gallery that demonstrates all of this. It is the fastest way to see what fits your use case.
Migrating: two paths, one recommendation
If you run TCPDF today, there are two ways forward, and both deserve a straight account.
The path I recommend: adopt tc-lib-pdf directly. It is not a drop-in replacement. It uses a different namespace, a more strongly typed API, and Composer-first font generation. In exchange you get the full capability set above and a codebase that will keep evolving. For new projects, and for any migration you are willing to invest in, this is the right destination.
The last resort: TCPDF 7 as a bridge. The latest release of the old tecnickcom/tcpdf package is no longer a PDF engine at all. As of version 7 it is a compatibility facade: it requires tc-lib-pdf underneath and maps the familiar TCPDF API onto it. There is a certain symmetry here. The library I once extracted from AIOCP is now itself powered by its own successor.
Be clear-eyed about what this is, though. It is not a pure drop-in. Parts of the API have changed, font management in particular, so even the facade needs some adaptation of your existing code. And it exposes only the old API surface, so the modern capabilities and the type safety stay out of reach, while the package itself remains deprecated and in maintenance-only mode. Reach for it only to keep legacy code alive while you plan the move. The bridge buys you time; the destination is still the direct API.
Keeping shared infrastructure alive
Here is the uncomfortable truth about a dependency that an industry runs on without thinking about it: it has been maintained, for twenty-five years, mostly by one person.
tc-lib-pdf is free and open source under the GNU Lesser General Public License (LGPL), and it will stay that way. But if your company ships products that rely on TCPDF or tc-lib-pdf, sponsoring its maintenance is closer to insurance on a dependency you already ship than to a donation. It is what keeps this shared infrastructure secure, current, and maintained. If that is you, please consider becoming a sponsor .
Getting started
If you are starting something new, or you are ready to move off the old engine:
composer require tecnickcom/tc-lib-pdf
Then:
- Explore the repository and the examples .
- Read the documentation at tcpdf.org .
- Try the quick start above and generate your first document.
- If it helps you, star the project. If your business depends on it, sponsor it .
Twenty-five years ago I needed to print an invoice. That small problem grew into one of the most widely used PHP libraries in the world, and now into a modern toolkit built to last. I am glad you are here for the next chapter.