---
title: "Parse PDFs with Python: Step-by-step text extraction tutorial"
canonical_url: "https://www.nutrient.io/blog/extract-text-from-pdf-using-python/"
md_url: "https://www.nutrient.io/blog/extract-text-from-pdf-using-python.md"
last_updated: "2026-07-28T09:39:23.181Z"
description: "Learn to extract text from PDFs in Python using PyPDF for quick jobs and the Nutrient Processor API for OCR, structured output, and secure document parsing. Ideal for automation workflows and large-scale processing."
---

**TL;DR**

Parsing PDFs in Python is easy with the right tools. This tutorial walks you through extracting text from PDFs using [PyPDF](https://pypdf.readthedocs.io/en/latest/) for basic, selectable text, and the [Nutrient Processor API](https://www.nutrient.io/api/) for more advanced use cases like OCR, encrypted documents, and structured JSON output.

In this tutorial, you’ll learn how to parse PDF files in Python using:

- The open source [PyPDF](https://pypdf.readthedocs.io/en/latest/) library for quick and simple tasks.

- The [Nutrient Processor API](https://www.nutrient.io/api/) for advanced, reliable, and structured text extraction — including OCR and support for encrypted or scanned documents.

## What kind of text are you extracting?

Before you begin, it’s crucial to know what type of text you’re trying to extract:

- **Selectable (digital) text** — Text you can highlight in a PDF viewer. This is straightforward to parse.

- **Scanned (image-based) text** — Text stored as images, requiring optical character recognition (OCR).

This tutorial covers both — but it’ll start with digital PDFs and then show how to handle OCR using the Nutrient API. It will focus on extracting text that’s already selectable.

## Why Python is perfect for parsing PDFs

Python is beloved in the data world for a reason. When it comes to PDF parsing, Python offers:

- A mature ecosystem — Libraries like PyPDF make simple jobs easy, while APIs like Nutrient handle complex cases.

- Great integration — Python scripts fit smoothly into broader automation and ETL pipelines.

- Vibrant community — Endless tutorials, packages, and support channels are at your fingertips.

Read on to get started with your first extraction.

## Requirements

This tutorial will make use of Python version 3.12.3, but it should work with most 3.x Python versions. Create a new folder and a Python file to store all the code from this tutorial:

```bash

mkdir text_extract_pdf
cd text_extract_pdf
touch app.py

```

You’ll also need to install [PyPDF](https://pypdf.readthedocs.io/en/latest/). You’ll rely on this library to read a PDF file and extract data from it. It can be installed using PIP:

```bash

pip install pypdf

```

Use these two test PDFs:

- [GeoBase UML model](https://raw.githubusercontent.com/py-pdf/pypdf/main/resources/GeoBase_NHNC1_Data_Model_UML_EN.pdf)

- [Mozilla’s PDF.js sample](https://raw.githubusercontent.com/mozilla/pdf.js/ba2edeae/web/compressed.tracemonkey-pldi-09.pdf)

Just make sure to save the PDF file next to the `app.py` file and replace the file names in the rest of this tutorial appropriately.

## Method 1: Extract text from PDF using PyPDF

To extract text from a PDF in Python, install PyPDF, open the file with `PdfReader`, and call `.extract_text()` on each page. PyPDF is a pure Python library, so it doesn’t need any system dependencies. Here’s how to extract text from each page:

```python

# app.py

from pypdf import PdfReader

reader = PdfReader("compressed.tracemonkey-pldi-09.pdf")
for page in reader.pages:
    print(page.extract_text())

```

When you save and run the code, it’ll print all the text from the PDF file in the terminal. The code creates a [`PdfReader`](https://pypdf.readthedocs.io/en/latest/modules/PdfReader.html) object. Then it loops over all the pages in the PDF using the [`.pages`](https://pypdf.readthedocs.io/en/latest/modules/PdfReader.html#pypdf.PdfReader.pages) property and prints the text from each page using the [`.extract_text`](https://pypdf.readthedocs.io/en/latest/modules/PageObject.html#pypdf._page.PageObject.extract_text) method.

### Skipping headers and footers with PyPDF

PyPDF allows you to use visitor functions that get called with each operator or text fragment. The visitor function receives five arguments: the text, the current transformation matrix, the text matrix, the font dictionary, and the font size. You can make use of the text matrix to figure out the x/y coordinates of the text fragment and decide if you want to skip it or extract it.

In the following example, PyPDF will skip the header and footer of [this PDF document](https://raw.githubusercontent.com/py-pdf/pypdf/main/resources/GeoBase_NHNC1_Data_Model_UML_EN.pdf), as they fall outside of the acceptable y-coordinate range:

```python

from pypdf import PdfReader

reader = PdfReader("GeoBase_NHNC1_Data_Model_UML_EN.pdf")
page = reader.pages[3]

parts = []

def visitor_body(text, cm, tm, fontDict, fontSize):
    y = tm[5]
    if y > 50 and y < 720:
        parts.append(text)

page.extract_text(visitor_text=visitor_body)
print("".join(parts))

```

## How to extract text from encrypted PDFs in Python

The PDF files you’re working with may be encrypted. Luckily, you don’t have to look anywhere else for a solution, as PyPDF supports encryption and decryption of PDF files as well.

To work with encrypted documents, you’ll need to install the `cryptography` package:

```bash

pip install cryptography

```

Use the `.decrypt` method to decrypt a PDF file before extracting text from it:

```python

from pypdf import PdfReader

reader = PdfReader("encrypted-pdf.pdf")

if reader.is_encrypted:
    reader.decrypt("password")

# extract text from all pages

for page in reader.pages:
    print(page.extract_text())

```

## Method 2: Parse text with Nutrient Processor API (with OCR)

For more advanced use cases — like OCR, table detection, or layout-preserving JSON — use the [Nutrient Processor API](https://www.nutrient.io/api/).

### Step 1: Sign up and get your API key

Create a [free account](https://dashboard.nutrient.io/sign_up/?product=processor) at Nutrient Processor API. After verifying your email, copy your API key from the dashboard.

After you’ve verified your email, you’ll have access to your API key. Navigate to the **Overview** page to get started, or go to **API keys** to retrieve your key.![Image showing navigation to API keys on Nutrient API’s dashboard](@/assets/images/blog/2024/extract-text-from-pdf-using-python/pspdfkit-api-dashboard-keys.png)

### Step 2: Upload and extract text

To work with Nutrient Processor API, you’ll need to install the `requests` package:

```bash

pip install requests

```

After installing the package, you can create a Python script to perform text extraction using the API’s `/build` endpoint:

```python

import json
import requests

file = "./example.pdf"

url = "https://api.nutrient.io/build"

payload= {
  "instructions": json.dumps({
    "parts": [
      {
        "file": "file"
      }
    ],
    "output": {
        "type": "json-content",
        "plainText": True,
        "structuredText": True,
    }
})}

files=[
  ('file',('file.pdf',open(file,'rb'),'application/pdf')),
]
headers = {
  'Authorization': 'Bearer <API-KEY>'
}

response = requests.post(url, headers = headers, data = payload, files = files)

if response.status_code == 200:
  print(response.content)
else:
  print(
    f"Request to Nutrient API failed with status code {response.status_code}: '{response.text}'."
  )

```

Be sure to replace `<API-KEY>` in the code above with your key from the Nutrient API dashboard. Also ensure that an actual PDF file is present at the path specified by the `file` variable on line 4.

The JSON response includes both `plainText` and `structuredText`. The API will automatically:

- OCR scanned PDFs

- Preserve reading order and layout

- Normalize encoding issues

- Return structured JSON for downstream parsing

You can perform many operations using Nutrient Processor API, including text extraction, [Office conversion](https://www.nutrient.io/api/office-converter-api/), and [OCR](https://www.nutrient.io/api/pdf-ocr-api/). Learn more by reading our [documentation](https://www.nutrient.io/api/documentation/developer-guides/api-overview/).

## PyPDF vs. Nutrient Processor API: Which to use for text extraction

Use PyPDF for quick, budget-conscious extraction of selectable text in pure Python. Use the Nutrient Processor API when the job needs OCR for scanned pages, layout-preserving structured JSON, or enterprise security. Both extract text from PDFs, but they serve different needs.

### PyPDF

- **Open source** — PyPDF is an open source library, making it a cost-effective choice for developers working on projects with budget constraints.

- **Lightweight and easy to use** — PyPDF is simple to integrate into Python projects and works well for basic text extraction tasks.

- **Community-driven** — As an open source project, PyPDF benefits from community contributions and updates, but it might lack the advanced features of commercial tools.

### Nutrient Processor API

- **Advanced features** — Nutrient is a commercial API that offers advanced features like high-fidelity text extraction, handling of complex PDFs, and support for encrypted documents.

- **Security and compliance** — Nutrient provides SOC 2 Type 2-audited security, making it a suitable choice for enterprise applications where data security is a priority.

- **Comprehensive support** — With Nutrient, users benefit from professional support and regular updates, ensuring reliability and performance in production environments.

In summary, PyPDF is ideal for simpler, budget-conscious projects, while Nutrient is the go-to solution for enterprise-level applications requiring advanced capabilities and security.

## Conclusion

This tutorial covered the basics of extracting text from a PDF file using Python and PyPDF. It also showed how to extract text from an encrypted PDF file.

The second part of the tutorial introduced [Nutrient Processor API](https://www.nutrient.io/api/) as an alternative solution for extracting text from a PDF. Leveraging the power of Nutrient API, you can efficiently extract meaningful text from PDF files while ensuring high extraction speed and quality.

Need help choosing a library? Our [Python PDF library comparison](https://www.nutrient.io/blog/best-python-pdf-libraries/) benchmarks seven tools for text extraction, merging, OCR, and more.

## FAQ

#### Can I parse PDFs in Python without using OCR?

Yes! If your PDF contains digital (selectable) text, you can extract it using `PyPDF` without OCR. This works best for PDFs exported from Word, LaTeX, or similar tools.

#### What if my PDF is a scanned document or image?

You’ll need OCR to extract text from image-based PDFs. PyPDF doesn’t support this, but the Nutrient Processor API automatically applies OCR during processing.

#### Can I extract structured data like paragraphs or table-like sections?

Absolutely. The Nutrient Processor API returns both plain text and structured JSON with text order and hierarchy, making it ideal for NLP or analysis pipelines.

#### Is PyPDF enough for enterprise projects?

Not always. PyPDF is great for simple tasks, but for large-scale, secure, or OCR-heavy workflows, a robust API like Nutrient’s is better suited.

#### Is the Nutrient API free to try?

Yes. There’s a generous free tier for developers to test text extraction, OCR, and more — no credit card required.
---

## Related pages

- [The business case for accessibility: Five ways it drives enterprise value](/blog/5-ways-accessibility-drives-enterprise-value.md)
- [Accessibility Untangled Why It Matters Guide](/blog/accessibility-untangled-why-it-matters-guide.md)
- [Advanced Techniques For React Native Ui Components](/blog/advanced-techniques-for-react-native-ui-components.md)
- [`vector_store` holds your indexed documents (see the multimodal RAG post](/blog/agentic-rag.md)
- [Ai Document Automation Extraction To Action](/blog/ai-document-automation-extraction-to-action.md)
- [Ai Legal Assistant Document Authoring](/blog/ai-legal-assistant-document-authoring.md)
- [Angular File Viewer Pdf Image Office Files](/blog/angular-file-viewer-pdf-image-office-files.md)
- [Auto Tagging And Document Accessibility In Dotnet Sdk](/blog/auto-tagging-and-document-accessibility-in-dotnet-sdk.md)
- [Best Document Viewers](/blog/best-document-viewers.md)
- [The CEO’s AI playbook: Why decision architecture beats model selection](/blog/ceo-ai-playbook-decision-architecture.md)
- [1. Extract and chunk the PDF.](/blog/chat-with-pdf.md)
- [Complete Guide To Pdfjs](/blog/complete-guide-to-pdfjs.md)
- [Construction Document Data Extraction](/blog/construction-document-data-extraction.md)
- [Convert One Drive Files To Pdf In Sharepoint](/blog/convert-one-drive-files-to-pdf-in-sharepoint.md)
- [Create And Edit Pdfs In Flutter](/blog/create-and-edit-pdfs-in-flutter.md)
- [Create Pdfs With React](/blog/create-pdfs-with-react.md)
- [Creating A Document Scanner With Ocr In Python](/blog/creating-a-document-scanner-with-ocr-in-python.md)
- [Creating And Filling Pdf Forms Programmatically In Javascript](/blog/creating-and-filling-pdf-forms-programmatically-in-javascript.md)
- [The CTO’s AI playbook: Why accountability architecture beats orchestration](/blog/cto-ai-playbook-accountability-architecture.md)
- [Digital Signatures](/blog/digital-signatures.md)
- [Digital Workflow Automation](/blog/digital-workflow-automation.md)
- [Document Ai Vs Ocr](/blog/document-ai-vs-ocr.md)
- [Document Viewer](/blog/document-viewer.md)
- [Document Watermarking](/blog/document-watermarking.md)
- [Emerging threats: Your logging system may be an agentic threat vector](/blog/emerging-threats-your-logging-system.md)
- [Fillable Pdf](/blog/fillable-pdf.md)
- [How To Add Digital Signature To Pdf Using React](/blog/how-to-add-digital-signature-to-pdf-using-react.md)
- [How To Build A Dotnet Maui Pdf Viewer](/blog/how-to-build-a-dotnet-maui-pdf-viewer.md)
- [How To Build A Flutter Pdf Viewer](/blog/how-to-build-a-flutter-pdf-viewer.md)
- [or](/blog/how-to-build-a-javascript-pdf-viewer-with-pdfjs.md)
- [How To Build A Javascript Pdf Viewer](/blog/how-to-build-a-javascript-pdf-viewer.md)
- [or](/blog/how-to-build-a-nextjs-pdf-viewer.md)
- [How To Build A Powerpoint Viewer Using Javascript](/blog/how-to-build-a-powerpoint-viewer-using-javascript.md)
- [Using Yarn](/blog/how-to-build-a-react-excel-viewer.md)
- [How To Build A React Native Pdf Viewer](/blog/how-to-build-a-react-native-pdf-viewer.md)
- [How To Build A React Powerpoint Viewer](/blog/how-to-build-a-react-powerpoint-viewer.md)
- [How To Build A Reactjs File Viewer](/blog/how-to-build-a-reactjs-file-viewer.md)
- [or](/blog/how-to-build-a-reactjs-pdf-viewer-with-react-pdf.md)
- [or](/blog/how-to-build-a-reactjs-pdf-viewer.md)
- [How To Build A Reactjs Viewer With Pdfjs](/blog/how-to-build-a-reactjs-viewer-with-pdfjs.md)
- [How To Build A Vuejs Pdf Viewer With Pdfjs](/blog/how-to-build-a-vuejs-pdf-viewer-with-pdfjs.md)
- [How To Build A Vuejs Pdf Viewer](/blog/how-to-build-a-vuejs-pdf-viewer.md)
- [How To Build An Android Pdf Viewer](/blog/how-to-build-an-android-pdf-viewer.md)
- [How To Build An Angular Pdf Viewer With Ng2 Pdf Viewer](/blog/how-to-build-an-angular-pdf-viewer-with-ng2-pdf-viewer.md)
- [How To Build An Angular Pdf Viewer With Pdfjs](/blog/how-to-build-an-angular-pdf-viewer-with-pdfjs.md)
- [How To Convert Docx To Pdf Using Javascript](/blog/how-to-convert-docx-to-pdf-using-javascript.md)
- [How To Convert Docx To Pdf Using Python](/blog/how-to-convert-docx-to-pdf-using-python.md)
- [How To Convert Html To Pdf Using Html2pdf](/blog/how-to-convert-html-to-pdf-using-html2pdf.md)
- [or](/blog/how-to-convert-html-to-pdf-using-react.md)
- [or](/blog/how-to-convert-html-to-pdf-using-wkhtmltopdf-and-python.md)
- [How To Convert Word To Pdf In Nodejs](/blog/how-to-convert-word-to-pdf-in-nodejs.md)
- [or](/blog/how-to-create-a-react-js-signature-pad.md)
- [How To Create Pdfs With React To Pdf](/blog/how-to-create-pdfs-with-react-to-pdf.md)
- [How To Edit Pdfs Using Ios Pdf Library](/blog/how-to-edit-pdfs-using-ios-pdf-library.md)
- [How To Embed A Pdf Viewer In Your Website](/blog/how-to-embed-a-pdf-viewer-in-your-website.md)
- [How To Extract Tables From Pdf And Images](/blog/how-to-extract-tables-from-pdf-and-images.md)
- [How To Generate Pdf From Html With Nodejs](/blog/how-to-generate-pdf-from-html-with-nodejs.md)
- [base_url tells WeasyPrint where to resolve relative asset paths](/blog/how-to-generate-pdf-reports-from-html-in-python.md)
- [Open an image.](/blog/how-to-use-tesseract-ocr-in-python.md)
- [From an HTML string.](/blog/html-in-pdf-format.md)
- [Javascript Pdf Libraries](/blog/javascript-pdf-libraries.md)
- [Linearized Pdf](/blog/linearized-pdf.md)
- [Swift Package Manager](/blog/mobile-pdf-sdk.md)
- [`elements` come from your document parser — each has a type and content.](/blog/multimodal-rag.md)
- [Nutrient Vs Conga Composer](/blog/nutrient-vs-conga-composer.md)
- [Online Document Viewer](/blog/online-document-viewer.md)
- [Open Pdf In Your Web App](/blog/open-pdf-in-your-web-app.md)
- [Pdf Extraction Benchmark Opendataloader Bench](/blog/pdf-extraction-benchmark-opendataloader-bench.md)
- [Pdf Page Labels](/blog/pdf-page-labels.md)
- [Pdf Sdk Compliance Security Checklist](/blog/pdf-sdk-compliance-security-checklist.md)
- [Pdf Sdk Performance Benchmark](/blog/pdf-sdk-performance-benchmark.md)
- [Pdf Ua Compliance Guide](/blog/pdf-ua-compliance-guide.md)
- [Pdfjs Annotation Editor Layer](/blog/pdfjs-annotation-editor-layer.md)
- [Pdfjs Area Annotations Canvas Capture](/blog/pdfjs-area-annotations-canvas-capture.md)
- [Pdfjs Coordinate Systems Pdf To Screen](/blog/pdfjs-coordinate-systems-pdf-to-screen.md)
- [Pdfjs Document Outline Bookmarks Metadata](/blog/pdfjs-document-outline-bookmarks-metadata.md)
- [Pdfjs Eventbus Guide](/blog/pdfjs-eventbus-guide.md)
- [Pdfjs Limitations Commercial Upgrade](/blog/pdfjs-limitations-commercial-upgrade.md)
- [Pdfjs Native Annotation Layer Forms](/blog/pdfjs-native-annotation-layer-forms.md)
- [Pdfjs Navigation Zoom Rotation](/blog/pdfjs-navigation-zoom-rotation.md)
- [Pdfjs Pdf Page Manipulation Pdf Lib](/blog/pdfjs-pdf-page-manipulation-pdf-lib.md)
- [Pdfjs React Viewer Setup](/blog/pdfjs-react-viewer-setup.md)
- [Pdfjs Rendering Overlays React Portals](/blog/pdfjs-rendering-overlays-react-portals.md)
- [Pdfjs Server Side Text Extraction](/blog/pdfjs-server-side-text-extraction.md)
- [Pdfjs Sticky Note Annotations](/blog/pdfjs-sticky-note-annotations.md)
- [Pdfjs Text Highlight Annotations](/blog/pdfjs-text-highlight-annotations.md)
- [Pdfjs Text Search Pdffindcontroller](/blog/pdfjs-text-search-pdffindcontroller.md)
- [Pdfjs Thumbnail Sidebar](/blog/pdfjs-thumbnail-sidebar.md)
- [Process Flows](/blog/process-flows.md)
- [React Native Pdf Annotation](/blog/react-native-pdf-annotation.md)
- [or](/blog/sample-blog-updated.md)
- [Add DWS MCP Server to your Claude Code project.](/blog/teaching-llms-to-read-pdfs.md)
- [Open an image file.](/blog/tesseract-python-guide.md)
- [Top 5 Javascript Pdf Viewers](/blog/top-5-javascript-pdf-viewers.md)
- [Convert an HTML file to PDF.](/blog/top-ten-ways-to-convert-html-to-pdf.md)
- [Vector Pdf](/blog/vector-pdf.md)
- [Wcag2 Accessibility Requirements Documents](/blog/wcag2-accessibility-requirements-documents.md)
- [Web Sdk Is Now Headless](/blog/web-sdk-is-now-headless.md)
- [What Are Annotations](/blog/what-are-annotations.md)
- [What Is A Vpat](/blog/what-is-a-vpat.md)
- [What Is Pdf Ua](/blog/what-is-pdf-ua.md)
- [Why Pdfium Is A Trusted Platform For Pdf Rendering](/blog/why-pdfium-is-a-trusted-platform-for-pdf-rendering.md)
- [Why Your Ai Agent Hallucinates Pdf Table Data](/blog/why-your-ai-agent-hallucinates-pdf-table-data.md)

