How to Extract Text From a PDF in PHP

Jul 11, 2026 7 min read

Extract text from a PDF in PHP: read the text layer with smalot/pdfparser, or OCR a scanned PDF with an API. Code for both, plus how to handle them in one script.

// Try it now

PDF, JPG, PNG, BMP, HEIC, TIFF

Upload a document to extract

Last updated July 2026.

To extract text from a PDF in PHP, first check whether the PDF has a real text layer. If it does, a library like smalot/pdfparser reads the text directly with no OCR in a few lines. If the PDF is a scan or a photo of a page, the text is really an image, so you send it to an OCR API such as DocuOCR, which recognizes the characters and returns the text plus named fields and tables as JSON. One PHP code path can handle both cases by trying the text layer first and falling back to OCR when it comes back empty.

PDF is not one format so much as a container, and that is why "read the text from a PDF" has two very different answers in PHP. A PDF exported from Word or a web page carries the characters as actual text you can pull out instantly. A PDF that came off a scanner or a phone camera carries a picture of the page, and no amount of string parsing will find words inside a JPEG. The trick is knowing which one you have and having a plan for each. Below is how to do both in PHP, and how to tell them apart in code.

How do I extract text from a PDF in PHP?

For a PDF with a genuine text layer, the fastest route is smalot/pdfparser, a pure-PHP library you install with Composer. It reads the embedded text with no external binary and no cloud call:

use Smalot\PdfParser\Parser;

$parser = new Parser();
$pdf = $parser->parseFile('statement.pdf');
echo $pdf->getText();

That is the whole job for a digital PDF. You can also loop over $pdf->getPages() to keep text per page. Because it runs in-process, it is fast and free, which makes it the right first tool for invoices, reports and statements that were generated as PDFs rather than scanned. The problem starts when getText() returns an empty string or a jumble of spacing, which is your signal that the page is an image and needs OCR.

Why does my PDF text extraction return empty or garbled text?

Almost always because the PDF is a scan. A scanned or photographed page is stored as an image inside the PDF, so there is no text layer for a parser to read, and getText() returns nothing or a few stray characters. Garbled output has a different cause: some PDFs embed fonts with non-standard character maps, so the bytes are there but do not map back to readable letters. In both cases the fix is optical character recognition, which looks at the pixels and works out the characters, exactly what a text parser cannot do.

How do I OCR a scanned PDF in PHP?

You send the file to an OCR service and read the result back. The cleanest way in PHP is a REST OCR API, because PHP has cURL built in and Guzzle in most projects, so there is no engine to install. With DocuOCR you POST the PDF, start extraction, then read structured JSON:

use GuzzleHttp\Client;

$client = new Client(['base_uri' => 'https://docuocr.com/api/documents/']);
$headers = ['Authorization' => 'Bearer YOUR_API_KEY'];

$up = $client->post('upload', [
    'headers'   => $headers,
    'multipart' => [['name' => 'file', 'contents' => fopen('scan.pdf', 'r')]],
]);
$fileId = json_decode($up->getBody(), true)['file_id'];

$job = $client->post('extract', ['headers' => $headers, 'json' => ['file_id' => $fileId]]);
$hash = json_decode($job->getBody(), true)['extraction_hash'];

do {
    sleep(2);
    $res = json_decode($client->get("extraction/{$hash}", ['headers' => $headers])->getBody(), true);
} while ($res['status'] !== 'completed');

echo $res['text'];

The same three calls work in plain PHP with curl_init, and in Laravel they are three Http::withToken()->post() calls in a controller or a queued job. The full request and response shape is in the OCR API for PHP reference, which also shows how to get named fields and tables instead of a flat text blob.

Which PHP library is best for reading PDFs?

It depends on the PDF. For text-layer PDFs, smalot/pdfparser is the common choice for reading and getting page text; pdftotext through the poppler-utils binary is faster on large batches if you can install it on the server. For rendering or manipulating PDFs you would reach for a different tool, but for reading text those two cover most needs. What none of the pure-PHP libraries do is OCR: they cannot read a scanned page, so the moment your input includes scans you pair a text parser with an OCR API and pick between them at runtime.

How do I handle both digital and scanned PDFs in one PHP script?

Try the text layer first and fall back to OCR when it is empty. This one branch handles a mixed pile of PDFs without you sorting them by hand:

$text = (new Parser())->parseFile($path)->getText();

if (strlen(trim($text)) < 20) {
    // No usable text layer: it is a scan, send it to the OCR API
    $text = ocrViaApi($path);   // the Guzzle flow above
}

The threshold is a judgment call, but a page with fewer than a couple dozen characters of extractable text is almost always a scan. This pattern keeps the free, instant path for digital PDFs and only spends an API call on the pages that actually need OCR, which keeps cost down when most of your documents already carry text.

How do I extract fields and tables from a PDF in PHP, not just text?

Raw text is rarely the goal. What most PHP apps actually want is the invoice total, the dates, or the rows of a table as usable values, not a wall of characters you then parse with regular expressions. A document extraction API returns those directly: DocuOCR gives back named fields and table rows as JSON, so $res['fields'] and $res['tables'] drop straight into an Eloquent model or a database. That removes the brittle string-parsing layer teams otherwise maintain. If your PDFs are bank statements and all you need is the transactions inside your accounting software, a dedicated PDF bank statement to QuickBooks converter does that single job without any code at all, which is worth knowing before you build a parser you did not need.

How do I OCR many PDFs in PHP at scale?

Push the work onto a queue rather than one blocking loop. In Laravel, dispatch a job per document so workers process them in parallel and you stay under the API rate limit; in plain PHP, a worker pool or a simple queue table does the same. Wrap each API call in a try or catch block, add exponential backoff on HTTP 429 responses, and honor any Retry-After header. For large volumes, register a webhook so results are pushed to your app as each document finishes instead of polling for every one. That keeps thousands of pages moving without one slow scan holding up the rest.

The short version

Reading a PDF in PHP is really two jobs. Use smalot/pdfparser for digital PDFs with a text layer, detect the empty result that means a scan, and fall back to an OCR API for those. When you need fields and tables instead of raw text, let the API return structured JSON so you skip the regex layer entirely. To wire it up in your own stack, the PHP OCR API guide has the full code, and the document OCR API reference covers the request and response in detail.

Extract your documents with DocuOCR

Upload a document and get clean, structured data in seconds. No template setup required.

Start free

← Back to all articles