All formats

pdfplumber

LanguagePython 3.8+
LicenseMIT
Repositorygithub.com/jsvine/pdfplumber
DocumentationREADME
Depends onpdfminer.six, pypdfium2 (page images), Pillow
Read / writeyes / no

pdfplumber gives you every character, line, rectangle and curve on a page with its coordinates, font and size, and builds words, text lines and tables from them. Its table finder uses ruling lines or text alignment and is configurable, which makes it the go-to library for extracting tables from reports, statements and invoices. page.to_image() draws what was detected on top of the rendered page, so you can tune settings visually.

It’s slower than PyMuPDF and works only on machine-generated PDFs (scanned pages need OCR first). It doesn’t modify PDFs.

Installation#

Shell
pip install pdfplumber

Basic usage: extract text from a PDF#

Python
import pdfplumber

with pdfplumber.open("in.pdf") as pdf:
    print(len(pdf.pages), "pages")
    for page in pdf.pages:
        print(f"--- page {page.page_number} ({page.width} x {page.height}) ---")
        print(page.extract_text())

page.extract_text(layout=True) keeps the visual layout with spaces, similar to pdftotext -layout.

How to extract tables from a PDF#

Python
import pdfplumber

with pdfplumber.open("report.pdf") as pdf:
    page = pdf.pages[0]
    for table in page.extract_tables():
        for row in table:
            print(row)  # list of cell strings, None for empty cells

For tables without ruling lines, base the detection on text alignment:

Python
table = page.extract_table({"vertical_strategy": "text", "horizontal_strategy": "text"})

How to get words and characters with positions#

Python
words = page.extract_words()
for w in words[:10]:
    print(w["text"], w["x0"], w["top"], w["x1"], w["bottom"])

ch = page.chars[0]
print(ch["text"], ch["fontname"], ch["size"])

Coordinates are in points from the top-left corner of the page (top, bottom), unlike PDF’s bottom-left origin.

How to extract text from part of a page#

Python
# (x0, top, x1, bottom): the top half of the page
top_half = page.crop((0, 0, page.width, page.height / 2))
print(top_half.extract_text())

for match in page.search("Total"):
    print(match["text"], match["x0"], match["top"])

How to debug extraction visually#

Python
im = page.to_image(resolution=150)
im.draw_rects(page.extract_words())  # outline every word
im.save("debug.png")

# show the table finder's lines and cells
page.to_image(resolution=150).debug_tablefinder().save("tables.png")

How to read metadata and open encrypted PDFs#

Python
with pdfplumber.open("secret.pdf", password="user") as pdf:
    print(pdf.metadata.get("Title"), pdf.metadata.get("Producer"))

Tips#