Data Ingestion Recipe Parsing Workflows

pdfplumber vs PyMuPDF for Recipe Extraction

This page helps a food-tech developer choose between the two libraries most used to pull structured recipes and menus out of PDFs. It is a decision companion to PDF recipe extraction pipelines; read that for the extraction-and-validation architecture, then use this to pick the parser that fits your documents — a choice that determines both accuracy on tabular menus and throughput on large batches.

Both extract text with positional coordinates. pdfplumber models the page as words and ruled tables and excels at grid-structured menus; PyMuPDF (the fitz module) is faster and exposes layout blocks, favoring bulk throughput and mixed-layout documents.

Prerequisites and Data Contract

  • Python 3.11+, pdfplumber 0.11+, PyMuPDF 1.24+.
  • Digitally-generated PDFs (not scans — scanned menus need OCR, a separate path).
  • The output contract is identical: a list of (text, x0, top, x1, bottom, page) word boxes, or extracted table rows, that the downstream Pydantic validation layer parses into recipe records.
  • Note the licensing difference: pdfplumber is MIT; PyMuPDF is AGPL/commercial — a real constraint for closed-source products.
pdfplumber versus PyMuPDF for recipe extraction A comparison of two PDF extraction libraries. pdfplumber models the page as words and ruled tables, giving high accuracy on grid-structured menus at moderate speed, under a permissive MIT license, and is best when table fidelity matters. PyMuPDF exposes layout blocks and characters with high throughput, is best for large mixed-layout batches, but carries an AGPL or commercial license that constrains closed-source use. pdfplumber PyMuPDF (fitz) • words + ruled-table model • high fidelity on grid menus • moderate throughput • MIT license • best when tables matter • layout blocks + characters • very high throughput • strong on mixed layouts • AGPL / commercial license • best for large batches

Step-by-Step Implementation

Step 1 — Extract a menu table with pdfplumber

pdfplumber detects ruled tables directly, which is decisive for a priced menu grid.

import pdfplumber


def extract_tables_pdfplumber(path: str) -> list[list[list[str]]]:
    tables: list[list[list[str]]] = []
    with pdfplumber.open(path) as pdf:
        for page in pdf.pages:
            for table in page.extract_tables():
                tables.append(table)     # list of rows, each a list of cells
    return tables

Step 2 — Extract word boxes with PyMuPDF for speed

When throughput dominates and layout is irregular, PyMuPDF streams word boxes fast.

import fitz   # PyMuPDF


def extract_words_pymupdf(path: str) -> list[tuple]:
    words: list[tuple] = []
    with fitz.open(path) as doc:
        for page_num, page in enumerate(doc):
            for x0, y0, x1, y1, text, *_ in page.get_text("words"):
                words.append((text, x0, y0, x1, y1, page_num))
    return words

Step 3 — Choose by document shape and license

Pick pdfplumber when menus are ruled tables and per-cell fidelity drives cost accuracy, and when a permissive license matters for a closed product. Pick PyMuPDF when you are processing large volumes of mixed-layout documents where raw speed wins and the AGPL/commercial terms are acceptable. A common production pattern is pdfplumber for the tabular menu path and PyMuPDF as a fast pre-scan to classify pages — but only if the license fits. Whichever you choose, the extracted boxes feed the same validation layer described in parsing PDF menus with PyPDF2 and regex.

Verification and Validation

  • Same document, compare cell recall. Run both on a representative menu and count correctly-extracted price cells. pdfplumber usually wins on ruled grids; if it does not, your PDF may lack table rules and both need coordinate clustering.
  • Throughput bench. Time both over a batch of 500 PDFs. If PyMuPDF is many times faster and accuracy is comparable, throughput is your deciding axis.
  • License audit. Confirm the chosen library’s license is compatible with your distribution model before it reaches production; AGPL obligations are easy to overlook.
  • Coordinate agreement. Both report positions; overlay extracted boxes on a page image and confirm they align with the visible text.

Gotchas and Edge Cases

  • Scanned PDFs. Neither library does OCR. A scanned menu returns no extractable text; detect an empty extraction and route to an OCR path rather than shipping empty recipes.
  • Missing table rules. pdfplumber’s table detection depends on ruled lines; a borderless menu needs explicit table_settings using text alignment, or it returns nothing.
  • Multi-column reading order. PyMuPDF word order can interleave columns. Sort by (page, column-band, top) before parsing, or a two-column menu scrambles items and prices.
  • Encoding artifacts. Ligatures and fraction glyphs (½) can extract as multiple characters or the wrong codepoint; normalize Unicode before regex parsing so 1½ cup does not break quantity extraction.

For library specifics, see the official pdfplumber documentation and PyMuPDF documentation.