What 1.1.0 adds
PDFluent SDK 1.1.0 ships structured extraction on every channel: Markdown, blocks, words with boxes, and chunks for retrieval pipelines. Blocks cover paragraphs, headings with level, list items, table cells with grid position, and running heads, each with page and box. If you turn PDFs into Markdown or chunks for search and retrieval, these are the entry points you would use. The release also adds an optional balanced extraction quality that runs a layout model and a table-structure model locally, and image extraction on the plain document API. A compat layer follows part of the PyMuPDF API (coverage is partial and behaviour can differ in places; it is an independent implementation, not PyMuPDF), and the release ships a full command-line interface.
Structured extraction ships as Preview. Output quality is still improving and the API may change in a minor release. Plain-text extraction is not Preview.
Install and run it
pip install pdfluent==1.1.0You install the models with the pdfluent command-line tool. Download the archive for your platform from the 1.1.0 release page, put pdfluent on your PATH, and run:
pdfluent models install layout tablesfrom pdfluent import Document
with Document("report.pdf") as doc:
print(doc.extract_markdown(quality="balanced"))If the models are not installed, the call fails with MODEL_NOT_AVAILABLE, naming the install command and the path it looked in.
Two quality tiers
fast is the default. It is the engine alone, pure Rust, no models, and it runs everywhere including WebAssembly.
balanced is Preview and opt-in. The layout model regions each page (headings, lists, tables, page furniture) and the table-structure model structures tables. Both models run locally through ONNX Runtime 1.23.2 [B49, 2026-10-10]; the SDK loads the ONNX Runtime library at run time and never links it. The tier is Markdown only: extract_markdown reads it, extract_blocks refuses it. It is native only, never WebAssembly, and runs on glibc Linux, macOS and Windows, not on musl Linux, where loading returns a typed ModelError. In Rust it needs the cargo features ort-layout and ort-tables, both off by default; we build the Python wheel, the Node addon and the CLI archives with them.
The models are a separate, explicit download so extraction does not reach the network on its own. The CLI from the release archives fetches them once with pdfluent models install layout tables; pdfluent models status shows what is installed and whether the pins verify. The installer checks every file against size and SHA-256 pins compiled into the binary, so installs are reproducible and nothing downloads automatically at run time. PDFLUENT_MODELS_BASE points the installer at a mirror or a local directory, and the installer enforces the pins the same way.
The package models-v1 holds three components: heron_ep03.onnx, the layout model, trained by PDFluent as a fine-tune of IBM's docling-layout-heron-101 (Apache-2.0) on the DocLayNet training split (CDLA-Permissive-1.0), licensed under the SDK terms with Apache-2.0 attribution to IBM's base model; tatr-v1.1-all.onnx, Microsoft Table Transformer v1.1-all as an unmodified ONNX export under MIT; and the ONNX Runtime 1.23.2 libraries under MIT [B49, 2026-10-10]. Third-party files ship as-is under their own licences; the full text is in MODELS-NOTICE.txt in the release [B48].
Table results
| Dataset | Sample | Metric | vs Docling | vs pymupdf4llm | Claim |
|---|---|---|---|---|---|
| FinTabNet | 120 pages, 67 documents | TEDS | +0.150 [+0.119; +0.183] | +0.132 [+0.106; +0.158] | [A38, 2026-10-14] |
| PubTables-1M | 120 pages, 55 documents | TEDS | +0.087 [+0.055; +0.128] | +0.081 [+0.046; +0.127] | [A39, 2026-10-14] |
In balanced mode with the table model, PDFluent scored higher than both Docling and pymupdf4llm on FinTabNet (financial reports) and PubTables-1M (scientific articles) [A38, A39, 2026-10-14].1 On ParseBench tables (100 pages from 32 documents, ParseBench's own scorer on each tool's Markdown), it is ahead of pymupdf4llm on both metrics: table record match +0.314 [+0.181; +0.452], GriTS +0.186 [+0.101; +0.275] [A40, 2026-10-14].1
Dataset sources: FinTabNet (IBM, CDLA-Permissive-1.0), PubTables-1M (CDLA-Permissive-2.0 annotations over CC0/CC BY articles), ParseBench (LlamaIndex, Apache-2.0 card over third-party documents).
1 Mode: quality=balanced with the table-structure model. We measured our side on 2026-10-14 on a 1.1.0 pre-release build with the same extraction code, and Docling 2.126.0 and pymupdf4llm 1.28.2 on 2026-10-08 on the identical pages. The pages come from each dataset's development (tuning) split, which we used while building the table work, so our side is an upper bound, not an independent held-out test. Each number is ours minus theirs, with a 95% interval from a paired per-document bootstrap. The table-structure model we ship is Microsoft's Table Transformer v1.1-all, which Microsoft trained on PubTables-1M and FinTabNet.c. We have not checked whether our sample pages fall inside its training data, so the FinTabNet and PubTables-1M results may favour us for that reason too. Table structure only, on these three samples. Reproducible with pdfluent-bench (coming).
What else is new
- —Rust:
extract_markdown,extract_blocks(Preview),extract_words,extract_text_pages(), image extraction onPdfDocument,keep_ligatures(bool), and newExtractOptionsfields includingquality,progress,code,actual_textand OCR options. - —Python:
Document.extract_markdown,extract_blocks,extract_words, image extraction,quality=,model_dir=,table_model_dir=, aprogresscallback,ocr_function=,pdfluent.chunks.iter_chunks, and a compat layer. - —Node:
extractMarkdown,extractBlocks,extractWords, image extraction,iterChunks,quality,modelDir,tableModelDir, and one sharedPdfluentErroracross CJS, ESM and compat exports. - —WebAssembly:
encryptPdf/decryptPdf(AES-256, on bytes),PdfDoc.addWatermark(options),extractImages(bytes)returning{ images, skipped }, andsignPdf(bytes, p12, password, options?). Nobalancedtier. - —Java:
extractMarkdown/extractBlocksand image extraction onPdfluentDocument. Java 1.1.0 is available from the PDFluent Maven repository (maven.pdfluent.com); Maven Central carries 1.0.0, and 1.1.x follows there later. - —.NET: structured extraction and image extraction, plus AcroForm read/write, annotations, images, merge and PDF/A validation on
PdfDocument. - —C API:
extract_markdown/extract_blocks, image extraction, form field write and read-back, document serialisation.pdf_version()now returns the crate version. - —CLI:
extract,merge,split,pages,compress,protect/unprotect,watermark,convert,redact,sign,validate --pdfa, global--json,-q/-v,-for stdin/stdout,--raster quality|speed,--wordsand--format words. - —In pdfluent 1.1.0, OCR is reachable from Python only: it is opt-in, off by default, and runs through a system tesseract binary on PATH (or PDFLUENT_TESSERACT), or through your own function passed as ocr_function=. From plain Rust, the pdfluent 1.1.0 crate does not reach tesseract (its ocr-tesseract feature is empty). The lower-level pdf-engine crate has optional OCR backends behind feature flags (ocr and ocr-cloud), but the pdfluent 1.1.0 facade does not expose them. Node.js on Linux (glibc): the
@pdfluent/nodeaddons need at most GLIBC_2.17, so glibc 2.17 or newer runs them. This does not apply to the pdfluent CLI, whose linux-gnu binaries need glibc 2.18 or newer. [B50, 2026-10-16]
What to check when upgrading
- —CLI exit codes changed: 0 ok, 1 usage, 2 input error, 3 processing error. Before they were 2 usage, 3 missing file, 4 malformed PDF, 5 policy opt-in, 6/7/70 stub/IO/unknown. The
--jsonenvelope names the exact failure. - —
Blockis#[non_exhaustive]and gainedconfidenceandgrid, so struct literals stop compiling. UseBlock::new(kind, page, bbox, text, index)and set fields on the result. - —The extractor joins words by default:
Safety rulesinstead ofS a f e t y, and18.90instead of split decimals. Spans merge to one per word or run, so block and span counts in JSON output drop. - —
PdfDocument::outlines()returns pageNonefor an outline entry with no destination; 1.0.0 returnedSome(0)through a page-1 fallback. Code that treatedSome(0)as "first page" for such entries needs to handleNone. - —Plain-text extraction can be slightly slower on some documents: the extractor now places combining marks such as
c⃝and≠after the glyph they mark, which adds a small per-glyph cost. Follow-up work on this is planned after 1.1.0. - —
pdf-syntaxandpdf-interpretmove to 0.6.0; crates pinned to 0.5.x must move.
The Docling comparison has the full method and sources. For extraction, see the structured extraction guide and the output formats guide; for Office files, the Office to Markdown guide. The Python API is covered by the PyMuPDF-style Python API guide and the Python docs, with full details in the changelog.
Report problems or ask questions in GitHub Discussions. The full release notes are on the v1.1.0 release page.