Read text, metadata, page sizes and images out of PDF files from PHP, without installing anything
on the server: this package ships the Xpdf command-line tools
(pdftotext, pdfinfo, pdftopng, pdfimages and five more) as pre-compiled binaries for Linux
and macOS, with a fluent PHP wrapper class per tool.
Xpdf version: 4.06
Maintained by Restruct. If this package saves you time, you can support ongoing maintenance.
PHP cannot read PDF content on its own. The usual route is to install xpdf or poppler on every
server and development machine, build a shell_exec() command line by hand, and parse the tool's
text output yourself: which version is installed differs per machine, a missing binary only shows
up at runtime, and a damaged PDF easily parses as "0 pages" instead of an error.
This package bundles one known xpdf version with the code, finds the right binary for the platform
itself, runs it through symfony/process with a timeout, and returns parsed results.
use Restruct\Xpdf\PdfToText;
use Restruct\Xpdf\PdfInfo;
use Restruct\Xpdf\PdfToPng;
use Restruct\Xpdf\PdfImages;
// Extract text (UTF-8, layout preserved)
$text = PdfToText::extract('/path/to/file.pdf');
// Page count
$pages = PdfInfo::pageCount('/path/to/file.pdf');
// Full document info
$info = PdfInfo::create('/path/to/file.pdf');
echo $info->getTitle();
echo $info->getPageCount();
$dims = $info->getPageDimensions();
echo $dims->standard; // 'A4'
// Render pages to PNG
$pngs = PdfToPng::render('/path/to/file.pdf', '/tmp/output', dpi: 240);
// Extract images
$images = PdfImages::extractAll('/path/to/file.pdf', '/tmp/img');
// List images without extracting
$listing = PdfImages::list('/path/to/file.pdf');use Restruct\Xpdf\PdfToText;
// Quick extraction
$text = PdfToText::extract('input.pdf');
// Fluent API with full control
$text = PdfToText::create('input.pdf')
->encoding('UTF-8')
->layout()
->pages(1, 5)
->noPageBreak()
->noDiag() // skip watermarks
->getText();
// Table mode for tabular data
$text = PdfToText::create('input.pdf')
->table()
->encoding('UTF-8')
->getText();
// Save to file
PdfToText::create('input.pdf')
->encoding('UTF-8')
->toFile('output.txt');The layout modes (layout(), simple(), simple2(), table(), linePrinter(), raw()) exclude
each other: setting one clears the others. getText() returns an empty string when pdftotext fails,
toFile() returns false.
Replaces howtomakeaturn/pdfinfo with improved page dimension detection.
use Restruct\Xpdf\PdfInfo;
$info = PdfInfo::create('input.pdf');
// Basic metadata
$info->getTitle();
$info->getAuthor();
$info->getPageCount();
$info->getPdfVersion();
$info->getCreationDate();
// Page dimensions with paper size detection
$dims = $info->getPageDimensions();
$dims->width; // 595 (points)
$dims->height; // 842 (points)
$dims->standard; // 'A4'
$dims->orientation; // 'portrait'
$dims->rotation; // 0
$dims->nearestDIN; // 'A4' or 'A3'
// Rotation of the page, in degrees
$info->getPageRotation();
// All fields as array
$all = $info->getAll();
// Or in one call
$all = PdfInfo::info('input.pdf');If pdfinfo fails (damaged, unreadable or user-password-protected file, timeout), every parsed
getter throws a RuntimeException with the exit code and pdfinfo's error output, instead of
returning 0 pages (from 1.0.2). A failed run is not cached, so each getter call runs pdfinfo again.
run() still returns the raw XpdfResult without throwing. (A PDF with only an owner password
opens fine and does not throw.)
Empty fields (e.g. a document without a title) return null. When pdfinfo prints a label twice,
the first value wins.
standard is the A-size label pdfinfo prints itself when it prints one (A0 to A6), otherwise the
nearest entry in the built-in table of ISO A/B/C, ANSI and a few other sizes (Letter among them),
within 2 points in either orientation. null means no standard size matched. width and height
are rounded to whole points; nearestDIN is A4 for pages up to roughly A4 or Letter size and
A3 for anything larger.
use Restruct\Xpdf\PdfToPng;
// Render all pages
$files = PdfToPng::render('input.pdf', '/tmp/page', dpi: 240);
// ['/tmp/page-000001.png', '/tmp/page-000002.png', ...]
// Render single page
$file = PdfToPng::renderPage('input.pdf', 1, '/tmp/thumb', dpi: 72);
// Full control
$files = PdfToPng::create('input.pdf')
->resolution(300)
->pages(1, 10)
->gray()
->convert('/tmp/output');The default resolution of render() and renderPage() is 150 dpi. On failure, convert() and
render() return an empty array and renderPage() returns null.
use Restruct\Xpdf\PdfImages;
// Extract all images (JPEG where possible)
$files = PdfImages::extractAll('input.pdf', '/tmp/img');
// Extract unique images only
$files = PdfImages::extractUnique('input.pdf', '/tmp/img');
// List images without extracting
$list = PdfImages::list('input.pdf');
foreach ($list as $img) {
echo "{$img['page']}: {$img['width']}x{$img['height']} {$img['color']} {$img['enc']}\n";
}
// Full control
$files = PdfImages::create('input.pdf')
->pages(1, 5)
->jpeg()
->unique()
->extract('/tmp/img');For the tools without a wrapper class (pdffonts, pdftohtml, pdftoppm, pdftops,
pdfdetach), or any option a wrapper does not expose:
use Restruct\Xpdf\Xpdf;
// Check availability
Xpdf::isAvailable();
Xpdf::availableTools(); // ['pdftotext', 'pdfinfo', ...]
// Run any tool directly
$result = Xpdf::run('pdftotext', ['-layout', '-enc', 'UTF-8', 'input.pdf', '-']);
echo $result->output;
echo $result->isSuccessful();run() throws a RuntimeException when the tool's binary is not available. Otherwise it returns
an XpdfResult with output, errorOutput and exitCode (-1 on a timeout), and never throws on
a failed run.
| Branch | Package version | Xpdf | PHP |
|---|---|---|---|
main |
1.x |
4.06 | 8.1+ |
composer.json is the source of truth for exact constraints. This is a plain PHP package; it does
not depend on any framework.
- PHP 8.1 or higher and
symfony/process^6 or ^7. - Bundled binaries are x86_64 only: Linux x86_64, and macOS x86_64 or Apple Silicon via Rosetta 2.
On other platforms (e.g. Linux ARM64) install xpdf yourself and point
XPDF_BIN_DIRat it. - The Linux binaries are dynamically linked: they need
libfontconfig.so.1(all tools) and, for the rendering tools such aspdftopng,libzandlibbz2. Most distributions and CI images have these; a minimal container image may not.
composer require restruct/xpdf-staticOn first use, the package includes its bootstrap.php, which detects the platform and defines the
XPDF_BIN_DIR constant, taking the first of:
XPDF_BIN_DIRconstant (if already defined)XPDF_BIN_DIRenvironment variable (when it is an existing directory)- macOS: bundled
x64/mac/binaries - Linux: bundled
x64/linux/binaries
On any other platform nothing is defined, Xpdf::isAvailable() returns false and run() throws.
Every tool runs with a timeout of 30 seconds by default (Xpdf::setDefaultTimeout() changes it).
PdfToPng defaults to 120 seconds and PdfImages extraction to 60. The run(), getText(),
toFile(), convert(), extract() and listImages() methods take a $timeout argument in seconds.
All 9 xpdf tools are bundled: pdftotext, pdfinfo, pdffonts, pdfimages, pdftohtml,
pdftopng, pdftoppm, pdftops, pdfdetach. Their options are in the man pages in xpdf-doc/
and at https://www.xpdfreader.com/.
composer install
vendor/bin/phpunitTests that run the real pdfinfo are skipped when it is not available.
See CHANGELOG.md.
- Wrapper code (
bootstrap.php,src/): MIT (Copyright Restruct web & apps). - Bundled xpdf binaries (
x64/): unmodified xpdf-tools 4.06, Copyright Glyph & Cog, LLC, licensed under the GNU General Public License version 2 or 3. They are not covered by the MIT licence. The upstream README, man pages and GPL texts that must accompany them are inxpdf-doc/; source is available from https://www.xpdfreader.com/download.html.
See LICENSE for the full terms.