pikepdf
| Language | Python 3.11+ (C++ extension) |
|---|---|
| License | MPL-2.0 |
| Repository | github.com/pikepdf/pikepdf |
| Documentation | pikepdf.readthedocs.io |
| Depends on | QPDF (bundled in the wheels), lxml, Pillow, packaging |
| Read / write | yes / yes: pages, objects, metadata (Info and XMP), encryption, attachments, outlines, repair; no text extraction or rendering |
pikepdf wraps the QPDF C++ library: it opens a PDF as a tree of Python objects (pikepdf.Dictionary, Array, Name, Stream) that you can read and change directly, and writes the result with QPDF’s writer. That makes it reliable for structural work on real-world files: merging, splitting, reordering and rotating pages, encrypting with AES-256 and decrypting, editing XMP metadata, managing attachments, linearizing and compressing. Opening and saving a damaged file with pikepdf often repairs it. OCRmyPDF uses it.
pikepdf doesn’t extract text or render pages; combine it with pdfminer.six, pdfplumber or pypdfium2 for that.
Installation#
Shell
pip install pikepdf
Basic usage: merge PDF files#
Python
from pikepdf import Pdf
out = Pdf.new()
for path in ["a.pdf", "b.pdf"]:
src = Pdf.open(path)
out.pages.extend(src.pages)
out.save("merged.pdf")
Keep the source Pdf objects open until save(): pages copied from them are read lazily.
How to split a PDF into pages#
Python
from pikepdf import Pdf
with Pdf.open("in.pdf") as pdf:
for n, page in enumerate(pdf.pages):
dst = Pdf.new()
dst.pages.append(page)
dst.save(f"page-{n + 1}.pdf")
How to rotate and delete pages#
Python
from pikepdf import Pdf
with Pdf.open("in.pdf") as pdf:
for page in pdf.pages:
page.rotate(90, relative=True)
del pdf.pages[-1] # remove the last page
pdf.save("out.pdf")
How to encrypt and decrypt a PDF#
Python
import pikepdf
from pikepdf import Pdf
with Pdf.open("in.pdf") as pdf:
pdf.save("encrypted.pdf", encryption=pikepdf.Encryption(
owner="owner", user="user", R=6, # R=6 is AES-256
allow=pikepdf.Permissions(extract=False)))
with Pdf.open("encrypted.pdf", password="owner") as pdf:
pdf.save("decrypted.pdf") # saved without encryption by default
How to read and edit PDF metadata#
Python
from pikepdf import Pdf
with Pdf.open("in.pdf", allow_overwriting_input=True) as pdf:
print(pdf.pdf_version, len(pdf.pages), pdf.is_encrypted)
print(pdf.docinfo.get("/Title"), pdf.docinfo.get("/Producer"))
with pdf.open_metadata() as meta: # XMP; also updates the Info dictionary
meta["dc:title"] = "New title"
pdf.save("in.pdf")
How to inspect PDF objects#
Python
from pikepdf import Pdf
with Pdf.open("in.pdf") as pdf:
page = pdf.pages[0]
print(page.mediabox) # [0, 0, 595.27, 841.89]
print(page.obj.keys()) # raw page dictionary keys
print(pdf.Root.keys()) # the catalog
print(pdf.trailer.get("/ID"))
for name, image in page.get_images().items():
print(name, image.Width, image.Height, image.get("/Filter"))
Tips#
pdf.save(path, object_stream_mode=pikepdf.ObjectStreamMode.generate, compress_streams=True)produces smaller files;linearize=Truemakes fast-web-view files.pdf.check_pdf_syntax()returns a list of structural problems found by QPDF.pikepdf.PdfImage(image).extract_to(fileprefix="img")saves an embedded image in its native format.