This HTML page is not optimized for LLM or AI agent consumption. Fetch the Markdown version instead: /blog/pdf-text-extraction.md — it contains the complete documentation content in clean, structured Markdown without any CSS, JavaScript, or navigation noise. How to extract text from a PDF

Table of contents

    Extracting text from a PDF is harder than it looks because PDFs store rendering instructions, not structured text. This guide explains why PDF text extraction is tricky, compares popular tools across languages, and provides code examples for Python, JavaScript, Java, Swift, and Kotlin.
    How to extract text from a PDF
    Summary

    PDF files store rendering commands rather than structured text, which makes text extraction harder than reading a text file. This guide explains how PDFs represent text internally; compares extraction tools across Python, JavaScript, Java, and mobile platforms; and provides working code examples for each — including OCR for scanned documents.

    Extracting text from a PDF is harder than it looks. PDF files are designed to preserve document appearance rather than facilitate text extraction. This post covers text extraction across multiple programming languages and compares tools for Python, JavaScript, Java, Swift, and Kotlin.

    Why PDF text extraction is difficult

    PDFs prioritize consistent rendering across devices, not text readability. They store low-level drawing commands rather than structured content, which makes extraction a heuristic problem.

    How text is represented in a PDF

    A PDF file doesn’t simply contain text as you’d be used to in a text file. What it does contain are commands on how to render the given text on the screen without whitespace characters or newlines. Here’s how PDFs represent text internally.

    Content streams

    Each page in a PDF has one or more content streams that tell the PDF viewer application how to render a page. A very simple one might look like this:

    193.95 581.633 Td
    (Hello) Tj
    30.68 0 Td
    (World!) Tj

    These content streams can be represented differently while accomplishing the same goal, like this:

    193.95 581.633 Td
    <00290046004d004d00500001003800500053004d0045> Tj

    Td instructs the PDF viewer where to draw the next string. Tj specifies which string to draw.

    Extracting text from a content stream

    The only way to extract text from a PDF is by looking at the rendering commands and making a heuristic attempt to reconstruct it. In the example above, we know we’re supposed to render Hello, reposition the text cursor, and then output World!.

    You might have noticed there’s no whitespace in the first example above. Because the content stream only instructs the rendering engine what to draw on the screen, and because whitespace has no rendering command, we have to infer the spaces and newlines ourselves most of the time.

    Doing this reliably across all the different PDF documents out there is difficult, and it’s not uncommon to encounter problems where tweaking the heuristic breaks one document but fixes another.

    Extracting text with the Nutrient SDK

    The Nutrient SDK offers APIs to retrieve text from a document across iOS, Android, and Web. All platforms use the same underlying heuristic to determine the layout of the text on the page and how to extract blocks out of it.

    iOS

    On iOS, you can use PSPDFTextParser to retrieve the text, text blocks, words, or glyphs from a page:

    guard let textParser = documentProvider.textParserForPage(at: 0) else {
    // Handle failure.
    abort()
    }
    print("Text of page 0: \(textParser.text)")
    for textBlock in textParser.textBlocks {
    print("TextBlock at \(textBlock.frame): \(textBlock.content)")
    }

    Android

    On Android, there’s no dedicated text parser class; instead, you retrieve your page text using PdfDocument:

    val pageText = document.getPageText(0)
    print("Text of page 0: $pageText")
    for (textRect in document.getPageTextRects(0, 0, pageText.length)) {
    val blockText = document.getPageText(0, textRect)
    print("TextBlock at $textRect: $blockText")
    }

    Web

    Nutrient Web SDK can extract the text from a page using textLinesForPageIndex, but doesn’t currently support text block extraction:

    const textLines = await instance.textLinesForPageIndex(0);
    textLines.forEach((textLine) => console.log(textLine.contents));
    instance.textLinesForPageIndex(0).then(function (textLines) {
    textLines.forEach(function (textLine) {
    console.log(textLine.contents);
    });
    });

    Python

    Python has several extraction libraries, including PyPDF and PyMuPDF. Compare their output on representative documents to choose one for your workflow. Our Python PDF text extraction tutorial covers both in depth:

    from pypdf import PdfReader
    reader = PdfReader("document.pdf")
    for page in reader.pages:
    text = page.extract_text()
    print(text)

    For scanned documents, you’ll need OCR. This example uses Nutrient DWS Processor API: It sends an OCR action to /build and requests json-content output. Create a Processor API account(opens in a new tab), install the Python requests package, and set NUTRIENT_API_KEY to your dashboard API key before running it.

    import os
    import requests
    with open("scanned.pdf", "rb") as f:
    response = requests.post(
    "https://api.nutrient.io/build",
    headers={"Authorization": f"Bearer {os.environ['NUTRIENT_API_KEY']}"},
    files={"file": f},
    data={
    "instructions": '{"parts": [{"file": "file"}], "actions": [{"type": "ocr", "language": "english"}], "output": {"type": "json-content", "plainText": true}}'
    },
    timeout=60,
    )
    response.raise_for_status()
    print(response.json())

    Java

    Java developers commonly use Apache PDFBox for text extraction. The example below uses the PDFBox 2.x API (PDDocument.load); on PDFBox 3.x, use Loader.loadPDF(new File(...)) instead:

    import org.apache.pdfbox.pdmodel.PDDocument;
    import org.apache.pdfbox.text.PDFTextStripper;
    PDDocument document = PDDocument.load(new File("document.pdf"));
    PDFTextStripper stripper = new PDFTextStripper();
    String text = stripper.getText(document);
    System.out.println(text);
    document.close();

    For more control over layout, PDFBox also offers PDFTextStripperByArea to extract text from specific regions of a page — useful when processing invoices or forms with known layouts.

    Comparing PDF text extraction tools

    Choose based on language, OCR requirements, and document complexity:

    ToolLanguageOCR supportLayout handling and outputLicense
    PyPDFPythonNoBasicBSD
    PyMuPDFPythonNo (add-on)GoodAGPL/Commercial
    Nutrient DWS Processor APIAny (REST)Yes, with an OCR actionStructured JSON outputCommercial
    Nutrient Data Extraction APIAny (REST)Yes, in OCR-enabled modesMarkdown or spatial outputCommercial
    Nutrient SDKiOS/Android/WebRequires platform-specific OCR setupText and position APIs vary by platformCommercial
    Apache PDFBoxJavaNo (add-on)GoodApache 2.0
    PDF.jsJavaScriptNoBasicApache 2.0
    TesseractPython/C++Yes (OCR only)N/A (image-based)Apache 2.0

    For a deeper comparison of Python options, see our PyMuPDF vs. Nutrient guide. For JavaScript, our complete guide to PDF.js covers the PDF.js approach in detail.

    Handling scanned PDFs with OCR

    Not all PDFs contain selectable text. Scanned documents store pages as images, so you need optical character recognition (OCR) to extract text from them. Common OCR approaches include Tesseract for open source workflows and Nutrient DWS Processor API for a hosted OCR and extraction workflow. Our automated PDF OCR workflows guide walks through setting up batch processing for scanned documents. If you’re working with C#, see our guide on OCR for images and PDFs in C#.

    When to use the Data Extraction API

    Nutrient Data Extraction API is a separate option for applications that need document content as Markdown or structured data. It uses different endpoints and instructions from the Processor API example.

    For whole-document Markdown, follow the Markdown extraction guide. It sends a document to /extraction/parse and reads output.markdown from the response. Use text mode for PDFs with an existing text layer, or structure mode for scans that need OCR. The processing modes guide explains the options.

    To try this workflow, sign up for Data Extraction(opens in a new tab) and follow its API key setup. Use the Processor API signup linked with the Python example to run the /build request.

    Conclusion

    PDF text extraction comes down to two things: how PDFs store text internally, and which tool fits your language and workflow. Whether you use Python, JavaScript, Java, or the Nutrient SDK on mobile, the core challenge is the same — PDFs store rendering commands, not structured text. Use the SDK’s text APIs for extraction inside a viewer, the Processor API for the OCR and JSON workflow shown here, or the Data Extraction API for whole-document Markdown. Scanned PDFs need an OCR step; the SDK text methods shown here read an existing text layer. Text extraction also powers PDF text comparison for identifying differences between document versions. For help choosing between extraction platforms, see our evidence-based guide to evaluating document AI platforms.

    FAQ

    Why is extracting text from PDFs so difficult?

    PDFs are designed for visual consistency rather than text extraction. They store rendering commands (where to draw glyphs on a page) instead of structured text with paragraphs and whitespace. Extracting readable text requires heuristics to reconstruct word spacing, line breaks, and reading order from these low-level drawing instructions.

    How do I extract text from a PDF in Python?

    Use PyPDF for basic extraction (PdfReader("file.pdf").pages[0].extract_text()) or evaluate PyMuPDF on the same documents. For scanned pages, use Nutrient DWS Processor API with an OCR action. See our Python PDF text extraction tutorial for complete code examples.

    How do I extract text from a PDF in JavaScript?

    Use PDF.js to parse the PDF and retrieve text content from each page. Our guide to extracting text with PDF.js walks through the implementation step by step. Nutrient Web SDK also provides the textLinesForPageIndex API for client-side extraction.

    How do I extract text from a scanned PDF?

    Scanned PDFs store pages as images, so you need optical character recognition (OCR) to extract text. Tesseract is a popular open source option, while Nutrient DWS Processor API lets you include an OCR action in a hosted extraction request. The Data Extraction API also supports scans when you choose an OCR-enabled mode such as structure.

    What is the best library for PDF text extraction?

    It depends on your language and requirements. For Python, compare PyPDF and PyMuPDF on your documents. Apache PDFBox is an option for Java, and PDF.js runs in browsers. For a hosted workflow, Nutrient’s Processor and Data Extraction APIs accept REST requests from any language; choose based on the output you need.

    How does Nutrient handle PDF text extraction?

    Nutrient SDK text APIs read text inside iOS, Android, and Web applications. The DWS Processor API example in this post combines OCR with JSON extraction through /build. The Data Extraction API uses /extraction/parse for Markdown or spatial output, with OCR support determined by the processing mode.

    Can I extract text from a password-protected PDF?

    Yes, if you have the password. Most extraction libraries (PyPDF, PDFBox, Nutrient SDK) accept a password parameter when opening the document. Without the correct password, extraction will fail — this is by design to protect the document owner’s content.

    How do I preserve the original layout when extracting text?

    Layout preservation depends on the tool. PyMuPDF and the Nutrient SDK do well at maintaining reading order and paragraph structure. For tabular data, use an output format that represents rows and cells. Check the results against your source documents. See our PDF data extraction developer guide for advanced techniques.

    What is the difference between text extraction and OCR?

    Text extraction reads the text data already embedded in a PDF’s content streams — it works on PDFs created from digital sources (Word documents, webpages, etc.). Optical character recognition (OCR) converts images of text into machine-readable characters — it’s needed for scanned documents, photographs, or PDFs where text was rasterized into images.

    Python text extraction: Parse PDFs with Python (PyPDF tutorial), extract text from PDFs with PyMuPDF, top 10 ways to generate PDFs in Python

    JavaScript text extraction: Extract text from a PDF using JavaScript, complete guide to PDF.js, JavaScript PDF libraries compared

    OCR and scanned PDFs: Use Tesseract OCR in Python, automated PDF OCR workflows, OCR images and PDFs in C#

    Data extraction: PDF data extraction developer guide, best document AI platforms: an evaluation guide

    Document conversion: Convert PDF to JPG using Python, build an HTML5 PDF viewer

    Patrik Weiskircher

    Patrik Weiskircher

    Core Team Lead

    Patrik is the team lead of the Core Team, which oversees the shared codebase between our products. He knows far too many things about PDFs — ask him about fonts!

    Explore related topics

    Free to start Start extracting structured data