Skip to content

Migrate from pypdf to PDF Oxide

A complete guide to switching from pypdf to PDF Oxide, covering every API you use today and how to replace it.

Why Switch from pypdf?

There are four compelling reasons to migrate:

  1. 15x faster — PDF Oxide averages 0.8ms per page vs pypdf’s 12.1ms. Processing a 500-page document drops from 6 seconds to 0.4 seconds.
  2. 100% reliability — PDF Oxide passes 100% of the PDF test suite. pypdf fails on 1.6% of files (98.4% pass rate), meaning roughly 1 in 60 documents will produce broken output.
  3. Built-in Markdown and HTML — pypdf can only extract plain text. PDF Oxide converts pages to Markdown (with tables and structure preserved) and HTML, which is critical for LLM and RAG pipelines.
  4. OCR and rendering included — pypdf has no OCR or page rendering capabilities. PDF Oxide includes PaddleOCR for scanned documents and can render pages to images, all without external dependencies.

Step 1: Install

pip install pdf_oxide
pip uninstall pypdf  # optional

Step 2: Replace Imports

# Before
from pypdf import PdfReader, PdfWriter, PdfMerger

# After
from pdf_oxide import PdfDocument, Pdf

Step 3: API Mapping

Task pypdf PDF Oxide
Open PDF PdfReader("file.pdf") PdfDocument("file.pdf")
Page count len(reader.pages) doc.page_count()
Extract text reader.pages[0].extract_text() doc.extract_text(0)
Extract images reader.pages[0].images doc.extract_images(0)
Form fields reader.get_fields() doc.get_form_fields()
Metadata reader.metadata doc.xmp_metadata()
Encrypted PDF reader.decrypt("pw") PdfDocument("f.pdf", password="pw")
Merge PDFs PdfMerger() + .append() Pdf.merge(["a.pdf", "b.pdf"]) or doc.merge_from("b.pdf")
Split pages PdfWriter() + .add_page() doc.extract_pages([0, 1, 2, 3, 4], "out.pdf")
To Markdown Not available doc.to_markdown(0)
Render Not available doc.render_page(0)
OCR Not available doc.extract_text_ocr(0)

Step 4: Common Pattern Changes

Text Extraction

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

# PDF Oxide
from pdf_oxide import PdfDocument
doc = PdfDocument("report.pdf")
for i in range(doc.page_count()):
    print(doc.extract_text(i))

Merge PDFs

pypdf requires creating a merger object and appending files one by one. PDF Oxide does it in a single call:

# pypdf
from pypdf import PdfMerger
merger = PdfMerger()
merger.append("doc1.pdf")
merger.append("doc2.pdf")
merger.write("merged.pdf")

# PDF Oxide — static merge
from pdf_oxide import Pdf
pdf = Pdf.merge(["doc1.pdf", "doc2.pdf"])
pdf.save("merged.pdf")

You can also use the instance method doc.merge_from("other.pdf") to append pages to an existing document.

Split / Extract Pages

# pypdf — manual page-by-page copying
from pypdf import PdfReader, PdfWriter
reader = PdfReader("report.pdf")
writer = PdfWriter()
for page in reader.pages[0:5]:
    writer.add_page(page)
writer.write("first_5_pages.pdf")

# PDF Oxide — one call
from pdf_oxide import PdfDocument
doc = PdfDocument("report.pdf")
doc.extract_pages([0, 1, 2, 3, 4], "first_5_pages.pdf")

Encrypted PDFs

# pypdf — two-step open + decrypt
from pypdf import PdfReader
reader = PdfReader("encrypted.pdf")
reader.decrypt("password")
text = reader.pages[0].extract_text()

# PDF Oxide — one step
from pdf_oxide import PdfDocument
doc = PdfDocument("encrypted.pdf", password="password")
text = doc.extract_text(0)

Markdown Conversion (New Capability)

pypdf has no Markdown support. PDF Oxide makes it easy to feed PDFs into LLM pipelines:

from pdf_oxide import PdfDocument

doc = PdfDocument("report.pdf")
for i in range(doc.page_count()):
    md = doc.to_markdown(i)
    print(md)

Image Extraction

# pypdf
from pypdf import PdfReader
reader = PdfReader("report.pdf")
for image in reader.pages[0].images:
    with open(image.name, "wb") as f:
        f.write(image.data)

# PDF Oxide
from pdf_oxide import PdfDocument
doc = PdfDocument("report.pdf")
for i, img in enumerate(doc.extract_image_bytes(0)):
    with open(f"img_{i}.{img['format']}", "wb") as f:
        f.write(img["data"])

Step 5: Testing Your Migration

Run your existing test files through both libraries and compare output:

from pdf_oxide import PdfDocument

doc = PdfDocument("your-test-file.pdf")

# Verify text extraction
text = doc.extract_text(0)
print(text[:500])

# Verify page count
print(f"Pages: {doc.page_count()}")

# Verify form fields (if applicable)
fields = doc.get_form_fields()
for f in fields:
    print(f"{f.name}: {f.value}")

Other Migration Guides