Pull position-aware text out of a PDF in Rust, Python, or Node.js, turn it into retrieval-ready chunks (Preview), and use the balanced tier (Preview) for table-aware extraction. Structured extraction is Preview.
Install the SDK for Rust, Python, or Node.js. The install lines carry no version. The balanced tier (Preview) needs models installed once with the pdfluent CLI from the 1.1.0 release archives.
# Rust
cargo add pdfluent@1.1.0
# Python
pip install pdfluent==1.1.0
# Node.js
npm install @pdfluent/node
# Models for the balanced tier (CLI from the 1.1.0 release archives)
pdfluent models install layout tablesA retrieval-augmented generation (RAG) pipeline needs more than a blob of text: knowing which page a passage came from, and roughly how it was laid out, makes later chunking and citation much easier. PDFluent's structured extraction returns Markdown, blocks, words with boxes, and chunks. Structured extraction is Preview: output quality is still improving and the API may change in a minor release.
use pdfluent::{ExtractOptions, PdfDocument, Quality};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let doc = PdfDocument::open("report.pdf")?;
let markdown = doc.extract_markdown(&ExtractOptions::default())?;
let blocks = doc.extract_blocks(&ExtractOptions::default())?;
println!("{} blocks", blocks.len());
// balanced: needs the ort-layout/ort-tables features and installed models
let tables = doc.extract_markdown(&ExtractOptions::default().with_quality(Quality::Balanced))?;
println!("{markdown}\n{tables}");
Ok(())
}PdfDocument::open takes a path. extract_markdown returns Markdown (Preview); extract_blocks returns a Vec<Block> (Preview). The default options use the fast tier, which runs the engine alone with no models.
use pdfluent::{ExtractOptions, PdfDocument, Quality};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let doc = PdfDocument::open("report.pdf")?;
let markdown = doc.extract_markdown(&ExtractOptions::default())?;
let blocks = doc.extract_blocks(&ExtractOptions::default())?;
println!("{} blocks", blocks.len());
Ok(())
}Document is a context manager. extract_markdown returns Markdown (Preview); extract_words returns words with boxes (Preview); iter_chunks yields chunks with a .text attribute (Preview). Structured extraction is Preview.
from pdfluent import Document
from pdfluent.chunks import iter_chunks
with Document("report.pdf") as doc:
md = doc.extract_markdown() # fast tier, no models
words = doc.extract_words()
for chunk in iter_chunks(doc, mode="markdown"):
print(chunk.text)PdfDocument.open takes a buffer. extractMarkdown returns Markdown (Preview); iterChunks yields chunks with a .text attribute (Preview). Structured extraction is Preview.
const fs = require("node:fs");
const { PdfDocument, iterChunks } = require("@pdfluent/node");
const doc = PdfDocument.open(fs.readFileSync("report.pdf"));
const md = doc.extractMarkdown();
for (const chunk of iterChunks(doc, { mode: "markdown" })) {
console.log(chunk.text);
}Embedding models and vector stores work best on bounded chunks, not whole-page or whole-document strings. PDFluent provides iter_chunks for Python and iterChunks for Node.js, which yield chunks with a .text attribute. Structured extraction is Preview: output quality is still improving and the API may change in a minor release.
from pdfluent import Document
from pdfluent.chunks import iter_chunks
with Document("report.pdf") as doc:
md = doc.extract_markdown() # fast tier, no models
for chunk in iter_chunks(doc, mode="markdown"):
print(chunk.text)iter_chunks takes a Document and a mode ("blocks" or "markdown") and yields chunks with a .text attribute. Structured extraction is Preview.
from pdfluent import Document
from pdfluent.chunks import iter_chunks
with Document("report.pdf") as doc:
for chunk in iter_chunks(doc, mode="markdown"):
print(chunk.text)iterChunks is exported from @pdfluent/node. It takes a document and an options object with mode: "markdown" and yields chunks with a .text attribute. Structured extraction is Preview.
const fs = require("node:fs");
const { PdfDocument, iterChunks } = require("@pdfluent/node");
const doc = PdfDocument.open(fs.readFileSync("report.pdf"));
for (const chunk of iterChunks(doc, { mode: "markdown" })) {
console.log(chunk.text);
}The fast tier returns Markdown, blocks, words with boxes, and chunks. The balanced tier (Preview) adds a layout model and a table-structure model for better table and structure detection. Structured extraction, including the balanced tier, is Preview: output quality is still improving and the API may change in a minor release.
use pdfluent::{ExtractOptions, PdfDocument, Quality};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let doc = PdfDocument::open("report.pdf")?;
let markdown = doc.extract_markdown(&ExtractOptions::default())?;
let blocks = doc.extract_blocks(&ExtractOptions::default())?;
println!("{} blocks", blocks.len());
// balanced: needs the ort-layout/ort-tables features and installed models
let tables = doc.extract_markdown(&ExtractOptions::default().with_quality(Quality::Balanced))?;
println!("{markdown}\n{tables}");
Ok(())
}Pass quality="balanced" to extract_markdown. It needs installed models. Balanced (Preview) is Markdown only: extract_markdown reads it, extract_blocks refuses it. Structured extraction is Preview.
from pdfluent import Document
with Document("report.pdf") as doc:
md_tables = doc.extract_markdown(quality="balanced") # needs installed modelsPass { quality: "balanced" } to extractMarkdown. It needs installed models. Balanced (Preview) is Markdown only: extractMarkdown reads it, extractBlocks refuses it. Structured extraction is Preview.
const fs = require("node:fs");
const { PdfDocument, iterChunks } = require("@pdfluent/node");
const doc = PdfDocument.open(fs.readFileSync("report.pdf"));
const mdTables = doc.extractMarkdown({ quality: "balanced" });