pdfplumber
Plumb a PDF for character-level text, tables, and layout data in Python — with built-in visual debugging tools.
Repository Health
Technical Analysis
pdfplumber gives Python developers granular access to the raw contents of a PDF: every character, line, rectangle, curve, image, and annotation is exposed as a plain dictionary with exact positioning, font, and color attributes. Built on top of pdfminer.six’s parsing engine, it adds a much friendlier object model — pdfplumber.open(path) returns a PDF with a list of Page objects, each offering .crop(), .filter(), .within_bbox(), and rich text/table extraction methods.
Its table-extraction engine, adapted from published research on PDF table detection, reconstructs tables from a page’s actual vector lines (or from the alignment of words when no lines are drawn), then lets you inspect exactly which lines and intersections it used via .to_image() and .debug_tablefinder(). This tight feedback loop — extract, visualize, adjust settings, repeat — is what distinguishes pdfplumber from libraries that only return extracted text or tables with no way to see why extraction failed. It works best on machine-generated PDFs (not scanned/OCR’d documents) and ships a pdfplumber CLI alongside the library for quick CSV/JSON/text dumps.
What You Get
- Direct access to every PDF object (
.chars,.lines,.rects,.curves,.images,.annots,.hyperlinks) as plain dicts with exact coordinates, fonts, and colors - A configurable table-detection engine (
.find_tables(),.extract_table()) driven by graphical lines or word alignment, with dozens of tunable snap/join/intersection tolerances - Visual debugging via
.to_image()and.debug_tablefinder(), which render the page with detected lines, intersections, and tables overlaid for immediate feedback - Page-level transforms —
.crop(),.within_bbox(),.outside_bbox(),.filter()— that return derived pages retaining only the objects you care about - Text extraction with layout preservation (
.extract_text(layout=True)), word-level bounding boxes (.extract_words()), and regex search over positioned text (.search()) - A
pdfplumbercommand-line tool that dumps a PDF’s objects to CSV, JSON, or plain text without writing any code
Common Use Cases
- Extracting tabular data from government or corporate reports (e.g. WARN notices, background-check PDFs) into structured rows for analysis
- Building data pipelines that pull text and figures out of machine-generated invoices, statements, or forms
- Debugging why an automated table-extraction pass failed, by rendering the page with detected lines/cells highlighted
- Cropping a PDF to a specific region (e.g. a form field or table) before running text or table extraction on just that area
- Reading AcroForm field values from fillable PDF forms via pdfplumber’s pdfminer wrappers
Under The Hood
Architecture
pdfplumber layers a friendly object model on top of pdfminer.six’s low-level parser. A shared Container base class (container.py) implements lazy, cached properties — PDF (pdf.py) wraps a pdfminer.pdfdocument.PDFDocument/PDFParser pair and exposes .pages as a list of Page instances (page.py, the largest and most central module), each of which interprets the page’s content stream into .chars/.lines/.rects/.curves/.images dictionaries. Derived views — CroppedPage, FilteredPage — subclass Page so that .crop()/.filter() return objects with the identical interface, letting downstream code (text extraction, table-finding) stay agnostic of whether it’s working with a full page or a sliced one. Feature modules build on top of this shared object model rather than touching pdfminer directly: table.py implements a TableFinder that turns edges into intersections into cells into tables purely from the object lists Page already exposes, display.py wraps Pillow to rasterize a page and draw debug overlays, and structure.py independently walks the PDF’s marked-content structure tree. This separation means table detection, visual debugging, and structure parsing can each evolve without touching the parsing layer.
Tech Stack
Pure Python (3.10–3.14), with pdfminer.six doing the heavy lifting of PDF parsing and layout analysis, Pillow handling raster image generation for visual debugging and image object metadata, and pypdfium2 used for rendering support. Packaging is classic setuptools (setup.py + setup.cfg, no pyproject.toml), with a console-script entry point (cli.py, built on argparse) registered as the pdfplumber command. No web framework, database, or async runtime is involved — it’s a focused, dependency-light parsing library.
Code Quality
The project runs a strict CI lint gate — black --check, isort --check-only, flake8, and mypy --strict --implicit-reexport all block merges, and the package ships a py.typed marker for downstream type-checking. Tests run under pytest with pytest-cov (coverage uploaded to Codecov) across a comprehensive tests/ directory covering table extraction, structure parsing, character deduplication, layout analysis, and PDF repair, backed by a tests/pdfs and tests/comparisons fixture library of real-world problem PDFs used as regression cases. This combination of strict typing, formatting, linting, and fixture-driven regression testing is a strong quality signal for a library that has to handle enormously varied real-world PDF structures.
API Design
The public API favors chainable, low-boilerplate calls — pdfplumber.open(path).pages[0].extract_table() — while still exposing the full object model underneath for anyone who needs it. Method names read as verbs on the object they act on (.crop(), .filter(), .extract_text(), .extract_tables()), and the visual-debugging tools (.to_image(), .debug_tablefinder()) turn an otherwise opaque extraction failure into something a developer can literally see, which is unusual among PDF libraries that only expose extracted output with no way to inspect why extraction went wrong. The trade-off is a large surface of tuning parameters for table extraction (a dozen-plus table_settings keys) that require reading documentation to use well.
Used by 4 apps in this directory
ERPNext
ERP · Invoicing Finance
100% free, open-source ERP unifying accounting, manufacturing, inventory, CRM, HR, and POS in a single self-hostable platform.
OpenViking
Databases · AI Development
An open-source context database that gives AI agents a unified filesystem for memory, resources, and skills with hierarchical tiered retrieval.
Second Me
Productivity · AI Assistants
Train a locally hosted AI twin on your own memories—then connect it to the world through a decentralized identity network.
Skyvern
AI Agents · Automation
Skyvern (YC S2023) automates browser-based workflows by pairing LLMs with computer vision, letting agents click, fill, and extract data on sites they've never seen, without brittle XPath selectors that break on every layout change.