How to Extract Text From a PDF in Java
Jul 11, 2026 • 7 min read
Extract text from a PDF in Java: use Apache PDFBox for digital PDFs, and OCR (tess4j or an OCR API) for scanned PDFs. Code, tradeoffs and when to use each.
// Try it now
PDF, JPG, PNG, BMP, HEIC, TIFF
Upload a document to extract
Drop files here or click to upload
Up to 50 files
Uploading...
Last updated July 2026.
To extract text from a PDF in Java, first check whether the PDF is digital or scanned. A digital PDF has a real text layer, so Apache PDFBox reads the text directly with no OCR. A scanned or photographed PDF is only an image, so you need OCR first: run tess4j locally, or call an OCR API. DocuOCR reads both types from Java with a few HttpClient calls and returns the text plus named fields as JSON, so one code path covers digital and scanned files.
Pulling text out of a PDF in Java looks like a single problem, but it is really two. About half the PDFs you will meet already contain selectable text, and half are scans with none. The library that works perfectly on the first kind returns an empty string on the second, which is the single most common reason a Java PDF routine "does not work." Here is how to handle each, with code, and when to reach for an OCR API instead of a local library.
How do I extract text from a PDF in Java?
If the PDF has a text layer, use Apache PDFBox. It is the standard open-source Java library for PDFs, and PDFTextStripper walks the pages and returns the embedded text with no recognition step:
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.text.PDFTextStripper;
try (PDDocument doc = PDDocument.load(new java.io.File("document.pdf"))) {
String text = new PDFTextStripper().getText(doc);
System.out.println(text);
}
Add the org.apache.pdfbox:pdfbox dependency to your pom.xml and that is the whole read. PDFBox is fast, handles most digital PDFs well, and can give you per-page text if you set the start and end page on the stripper. It shares one hard limit with every text library: it can only return text that is actually stored in the PDF. If getText comes back empty, the page has no text layer, and no amount of tuning PDFBox will change that.
Why does my PDF return no text in Java?
The usual cause is a scanned PDF. When someone scans a paper document or exports an image to PDF, the file holds a picture of the page, not the characters. PDFBox reads stored text, so it finds nothing to return. A quick way to tell before you write code: open the PDF in a viewer and try to select a line with your cursor. If the text highlights, it is digital and PDFBox will read it. If you cannot select anything, it is an image and needs OCR. Optical character recognition is the step that reads characters off a picture of a page, and it is what separates "extract the text that is already there" from "recognize the text in this image."
How do I extract text from a scanned PDF in Java?
You have two routes: run OCR yourself with Tesseract through tess4j, or call a hosted OCR API. The self-hosted route uses tess4j, the JNA wrapper around the native Tesseract engine. You render each PDF page to an image (PDFBox's PDFRenderer does this) and hand it to tess4j:
import net.sourceforge.tess4j.Tesseract;
import org.apache.pdfbox.rendering.PDFRenderer;
Tesseract ocr = new Tesseract();
ocr.setDatapath("/usr/share/tessdata");
try (PDDocument doc = PDDocument.load(new java.io.File("scanned.pdf"))) {
PDFRenderer renderer = new PDFRenderer(doc);
StringBuilder sb = new StringBuilder();
for (int p = 0; p < doc.getNumberOfPages(); p++) {
sb.append(ocr.doOCR(renderer.renderImageWithDPI(p, 300)));
}
System.out.println(sb);
}
This works, but it carries real overhead. You install the native Tesseract binary and the tessdata language files on every machine, tune the DPI and image preprocessing, and accept that accuracy drops on faint scans, unusual fonts and tables. tess4j returns a block of raw text, so if you need the invoice number or a total as a labeled value, you still write parsing logic on top. The hosted route removes that: you send the PDF to an OCR API and read structured data back, with no engine to install or keep updated. That is the approach the OCR API in Java guide walks through with the built-in HttpClient: POST the file, start extraction, and read the JSON.
PDFBox vs tess4j vs an OCR API
Match the tool to the document and to what you want back:
| Approach | Reads | Returns | Best for |
|---|---|---|---|
| Apache PDFBox | Digital PDFs with a text layer | Plain text | Free, fast reads of native PDFs |
| tess4j (Tesseract) | Scanned PDFs and images | Plain text | Offline OCR, low volume, clean scans |
| OCR API (DocuOCR) | Digital and scanned, one endpoint | Named fields, tables, confidence as JSON | Structured data, accuracy, scale |
For digital PDFs where raw text is enough, PDFBox is the right, free answer. For occasional scans on your own hardware, tess4j is fine if you can carry the native setup and the accuracy tradeoff. For scans at volume, or when you need labeled fields and tables rather than a text blob, an OCR API is less code and cleaner output. Cost tracks the same split: the libraries are free and run on your machine, while hosted OCR bills per page, roughly a dollar and a half per 1,000 pages for plain text and more for structured extraction. The OCR API pricing comparison lines up the rates across providers.
How do I get structured fields instead of raw text?
Raw text is a starting point, not the goal, for most business documents. What a Java workflow actually needs is the invoice total, the statement date, the line items, each as a typed value you can map onto a record or POJO. PDFBox and tess4j hand back a string and leave the parsing to you, which breaks the moment a vendor changes their layout. A document extraction API returns the fields directly. With DocuOCR the JSON response gives you a list of fields with names, values and a confidence score on each, so you can flag anything below a threshold for review instead of writing brittle parsers. Many of those documents arrive as email attachments, and if that is your source you can pull the data straight out of the inbox before it ever reaches your OCR step.
How do I OCR thousands of PDFs in Java?
Loop over the files, but do not run them through one blocking call at a time. Submit documents through an ExecutorService or a bounded thread pool, add exponential backoff on rate-limit responses, and collect results as they complete. With the tess4j route you are bound by your own CPU, so a large batch of scans can take hours and pins your cores. With an API you POST each file and either poll or register a webhook, so a batch of thousands of pages keeps moving without waiting on each call in sequence, and the recognition runs off your hardware. The document OCR API handles the async side, so your Java code stays a simple submit-and-collect loop, and HttpClient's sendAsync fits neatly if you prefer non-blocking calls.
The short version
Extracting text from a PDF in Java comes down to one question: digital or scanned. For digital PDFs, Apache PDFBox reads the text layer directly and free. For scanned PDFs, you need OCR, either tess4j on your own hardware or an OCR API that reads the page image and returns structured JSON. If you want labeled fields and tables instead of a raw string, and you would rather not install a native engine, call an OCR API from Java: a few HttpClient calls, and the same code reads both scanned and digital files.
Extract your documents with DocuOCR
Upload a document and get clean, structured data in seconds. No template setup required.
Start free