Xberg Document Extraction
Xberg is a document intelligence library with a Rust core and bindings for Python, TypeScript/Node.js, Ruby, PHP, Go, Java, C#, Elixir, WebAssembly, Dart, Kotlin Android, Swift, Zig, and C. It extracts text, tables, metadata, and images from 107 formats across 140 unique file extensions and accepts 53 compatibility MIME aliases, including PDF, Office documents, images, HTML, email, archives, and academic formats.
Use this skill when writing code that:
- Extracts text or metadata from documents
- Performs OCR on scanned documents or images
- Batch-processes multiple files
- Configures extraction options (output format, chunking, OCR, language detection)
- Implements custom plugins (post-processors, validators, OCR backends)
If the xberg MCP server is registered in this session, prefer its tools over shelling out to the CLI — they expose the same extraction surface with structured arguments and results.
Installation
Python
pip install xberg
Node.js
npm install @xberg-io/xberg
Rust
cargo add xberg
# Cargo.toml
[dependencies]
xberg = { version = "1.1.0", features = ["full"] }
tokio = { version = "1", features = ["full"] }
# feature flags: pdf, ocr, chunking, embeddings, language-detection, keywords, api, mcp
# (or "formats" / "full" aggregates); tokio-runtime is on by default
CLI
brew install xberg-io/tap/xberg
# or run without a persistent install (the CLI proxy package self-installs the binary):
npx @xberg-io/xberg-cli --help
uvx --from xberg-cli xberg --help
# or download a prebuilt binary from the latest GitHub release:
# https://github.com/xberg-io/xberg/releases/latest
# or build from source:
cargo install xberg-cli
Quick Start
The library entry points are extract(input, config) and extract_batch(inputs, config). Both return an ExtractionResult envelope — the extracted document(s) live in result.results, and per-document data (content, tables, metadata, …) is on each result.results[i]. Python and Node are async-only.
Python
import asyncio
from xberg import ExtractInput, extract, ExtractionConfig
async def main() -> None:
result = await extract(ExtractInput(uri="document.pdf"), ExtractionConfig())
doc = result.results[0]
print(doc.content) # extracted text
print(doc.metadata) # document metadata
print(doc.tables) # extracted tables
asyncio.run(main())
Node.js
import { extract } from "@xberg-io/xberg";
const output = await extract({ kind: "uri", uri: "document.pdf" });
const doc = output.results[0];
console.log(doc.content);
console.log(doc.metadata);
console.log(doc.tables);
Rust
use xberg::{extract, ExtractInput, ExtractionConfig};
#[tokio::main]
async fn main() -> xberg::Result<()> {
let output = extract(ExtractInput::from_uri("document.pdf"), &ExtractionConfig::default()).await?;
println!("{}", output.results[0].content);
Ok(())
}
CLI
xberg extract document.pdf
xberg extract document.pdf --format json
xberg extract document.pdf --content-format markdown
Configuration
All languages use the same configuration structure with language-appropriate naming conventions.
Python (snake_case)
from xberg import (
ExtractInput, extract,
ExtractionConfig, OcrConfig, TesseractConfig, PdfConfig, ChunkingConfig, OutputFormat,
)
config = ExtractionConfig(
ocr=OcrConfig(
backend="tesseract",
language=["eng"],
tesseract_config=TesseractConfig(psm=6, enable_table_detection=True),
),
pdf_options=PdfConfig(passwords=["secret123"]),
chunking=ChunkingConfig(max_characters=1000, overlap=200),
output_format=OutputFormat("markdown"),
)
result = await extract(ExtractInput(uri="document.pdf"), config)
Node.js (camelCase)
import { extract, type ExtractionConfig } from "@xberg-io/xberg";
const config: ExtractionConfig = {
ocr: { backend: "tesseract", language: ["eng"] },
pdfOptions: { passwords: ["secret123"] },
chunking: { maxCharacters: 1000, overlap: 200 },
outputFormat: "markdown",
};
const output = await extract({ kind: "uri", uri: "document.pdf" }, config);
Rust (snake_case)
use xberg::{extract, ExtractInput, ExtractionConfig, OcrConfig, ChunkingConfig, OutputFormat};
let config = ExtractionConfig {
ocr: Some(OcrConfig {
backend: "tesseract".into(),
language: vec!["eng".to_string()],
..Default::default()
}),
chunking: Some(ChunkingConfig {
max_characters: 1000,
overlap: 200,
..Default::default()
}),
output_format: OutputFormat::Markdown,
..Default::default()
};
let output = extract(ExtractInput::from_uri("document.pdf"), &config).await?;
Config File (TOML)
output_format = "markdown"
[ocr]
backend = "tesseract"
language = "eng"
[chunking]
max_characters = 1000
overlap = 200
[pdf_options]
passwords = ["secret123"]
# CLI: auto-discovers xberg.toml in current/parent directories
xberg extract doc.pdf
# or explicit:
xberg extract doc.pdf --config xberg.toml
xberg extract doc.pdf --config-json '{"ocr":{"backend":"tesseract","language":"deu"}}'
Batch Processing
extract_batch takes a list of ExtractInputs and returns one envelope whose results array holds a document per input (in input order); per-input failures are reported in result.errors.
Python
from xberg import ExtractInput, extract_batch, ExtractionConfig
inputs = [
ExtractInput(uri="doc1.pdf"),
ExtractInput(uri="doc2.docx"),
ExtractInput(uri="doc3.xlsx"),
]
output = await extract_batch(inputs, ExtractionConfig())
for doc in output.results:
print(f"{len(doc.content)} chars extracted")
Node.js
import { extractBatch } from "@xberg-io/xberg";
const output = await extractBatch([
{ kind: "uri", uri: "doc1.pdf" },
{ kind: "uri", uri: "doc2.docx" },
]);
for (const doc of output.results) {
console.log(`${doc.content.length} chars`);
}
Rust
use xberg::{extract_batch, ExtractInput, ExtractionConfig};
let config = ExtractionConfig::default();
let inputs = vec![ExtractInput::from_uri("doc1.pdf"), ExtractInput::from_uri("doc2.docx")];
let output = extract_batch(inputs, &config).await?;
CLI
xberg batch *.pdf --format json
xberg batch docs/*.docx --content-format markdown
OCR
OCR runs automatically for images and scanned PDFs. Tesseract is the default backend (native binding, no external install required).
Backends
Select with OcrConfig.backend:
- tesseract (default): built-in native binding. All Tesseract languages supported.
- paddleocr (
"paddleocr" / "paddle-ocr"): ONNX-based PaddleOCR.
- vlm: Vision-Language-Model OCR (configure via
OcrConfig.vlm_config).
Custom backends can be registered in Python/Node via register_ocr_backend (see Advanced Features).
Language Codes
config = ExtractionConfig(ocr=OcrConfig(language=["eng"])) # English
config = ExtractionConfig(ocr=OcrConfig(language=["eng", "deu"])) # Multiple
# The single-string shorthand ("eng+deu") is only accepted in config files / --config-json,
# not in the OcrConfig constructor (Python takes a list, Node takes an array).
Force OCR
config = ExtractionConfig(force_ocr=True) # OCR even if text is extractable
Result Envelope and Document Fields
extract / extract_batch return an ExtractionResult envelope: results (list of documents), errors (per-input failures), and summary (counts). Per-document fields live on each document in results — bind doc = result.results[0] (Python/Node) or &output.results[0] (Rust) first.
| Field |
Python (doc.) |
Node.js (doc.) |
Rust (document.) |
Description |
| Text content |
content |
content |
content |
Extracted text (str/String) |
| MIME type |
mime_type |
mimeType |
mime_type |
Input document MIME type |
| Metadata |
metadata |
metadata |
metadata |
Document metadata (flat mapping) |
| Tables |
tables |
tables |
tables |
Extracted tables with cells + markdown |
| Languages |
detected_languages |
detectedLanguages |
detected_languages |
Detected languages (if enabled) |
| Chunks |
chunks |
chunks |
chunks |
Text chunks (if chunking enabled) |
| Images |
images |
images |
images |
Extracted images (if enabled) |
| Elements |
elements |
elements |
elements |
Semantic elements (if element_based format) |
| Pages |
pages |
pages |
pages |
Per-page content (if page extraction enabled) |
| Keywords |
extracted_keywords |
extractedKeywords |
extracted_keywords |
Extracted keywords (if enabled) |
Error Handling
Python
extract / extract_batch raise a plain RuntimeError on failure — the typed XbergError subclasses are not raised by these entry points, so catch RuntimeError. Per-input failures during extract_batch are reported non-fatally in result.errors.
from xberg import ExtractInput, extract, ExtractionConfig
try:
result = await extract(ExtractInput(uri="file.pdf"), ExtractionConfig())
for err in result.errors:
print(f"Per-input error: {err}")
except RuntimeError as e:
print(f"Extraction failed: {e}")
Node.js
The Node binding throws plain Error objects (it does not export typed error subclasses). Catch with instanceof Error, and inspect output.errors for non-fatal per-input failures.
import { extract } from "@xberg-io/xberg";
try {
const output = await extract({ kind: "uri", uri: "file.pdf" });
if (output.errors.length > 0) {
console.error("Per-input errors:", output.errors);
}
} catch (e) {
if (e instanceof Error) {
console.error(`Extraction failed: ${e.message}`);
}
}
Rust
use xberg::{extract, ExtractInput, ExtractionConfig, XbergError};
let config = ExtractionConfig::default();
match extract(ExtractInput::from_uri("file.pdf"), &config).await {
Ok(output) => println!("{}", output.results[0].content),
Err(XbergError::Parsing { message, .. }) => eprintln!("Parse error: {message}"),
Err(XbergError::Ocr { message, .. }) => eprintln!("OCR error: {message}"),
Err(XbergError::UnsupportedFormat(mime)) => eprintln!("Unsupported: {mime}"),
Err(e) => eprintln!("Error: {e}"),
}
Common Pitfalls
- Result is an envelope:
extract / extract_batch return ExtractionResult with results, errors, and summary. Per-document fields (content, tables, chunks, …) are on result.results[i], NOT on the top-level return.
- Async-only: Python and Node have no sync variants — always
await extract(...). Rust extract is async; use #[tokio::main] or an async context.
- Build the input: pass an
ExtractInput, not a bare path. Use ExtractInput(uri=...) / ExtractInput::from_uri(...) (Python/Rust) or { kind: "uri", uri: "..." } (Node); for bytes use kind="bytes" with bytes/mime_type.
- Python ChunkingConfig fields: construct with
max_characters and overlap (defaults 1000 / 200); these are also the readable attributes. When passing config as a dict/JSON, the max_chars / max_overlap aliases are also accepted. Node uses maxCharacters / overlap; Rust struct fields are max_characters / overlap.
- Python errors:
extract / extract_batch raise a plain RuntimeError on failure, not typed XbergError subclasses — catch RuntimeError. Node throws plain Error (no typed error subclasses).
- Rust extract signature:
extract(input, &config) — the config is a reference. Use &ExtractionConfig::default() for defaults.
- CLI --format vs --content-format:
--format controls CLI output (text, json, or toon). --content-format controls content rendering (plain, markdown, djot, html, json, or doctags).
- Config file field names: Use snake_case in TOML/YAML/JSON config files —
[chunking] fields are max_characters and overlap; other fields use names like output_format, pdf_options.
Supported Formats (Summary)
| Category |
Extensions |
| PDF |
.pdf |
| Word |
.docx, .docm, .doc, .dotx, .dotm, .dot, .odt, .pages, .wpd, .wp, .wp5, .wp6, .hwp, .hwpx |
| Spreadsheets |
.xlsx, .xlsm, .xlsb, .xls, .xla, .xlam, .xltm, .xltx, .xlt, .ods, .numbers |
| Presentations |
.pptx, .pptm, .ppt, .pps, .ppsx, .potx, .potm, .pot, .odp, .key |
| eBooks |
.epub, .fb2 |
| Images |
.png, .jpg, .jpeg, .gif, .webp, .bmp, .tiff, .tif, .jp2, .jpg2, .j2c, .j2k, .jpc, .jbig2, .jb2, .pnm, .pbm, .pgm, .ppm, .heic, .heics, .heif, .heifs, .hif, .avif, .avcs, .svg |
| Markup |
.html, .htm, .xhtml, .xht, .xml, .kml |
| Data |
.json, .geojson, .jsonl, .ndjson, .yaml, .yml, .toml, .csv, .tsv, .dbf, .sqlite, .sqlite3, .db, .gpkg, .gpkx |
| Text |
.txt, .adoc, .asciidoc, .vtt, .md, .markdown, .commonmark, .qmd, .rmd, .mdx, .djot, .dj, .doctags, .rst, .org, .rtf |
| Email |
.eml, .msg, .pst |
| Archives |
.zip, .tar, .tgz, .gz, .7z |
| Audio/Video |
.mp3, .mpga, .m4a, .wav, .webm, .mp4, .mpg4, .mp4v, .m4v, .mpeg, .mpg, .mpe, .m1v, .m2v |
| Academic |
.bib, .ris, .nbib, .enw, .tex, .latex, .typ, .typst, .jats, .nxml, .ipynb, .docbook, .dbk, .docbook4, .docbook5, .opml |
CSL JSON is supported through an explicit MIME type but does not have a registered file extension.
See references/supported-formats.md for the complete format reference with MIME types.
Additional Resources
Detailed reference files for specific topics:
- Python API Reference — All functions, config classes, plugin protocols, exact signatures
- Node.js API Reference — All functions, TypeScript interfaces, worker pool APIs
- Rust API Reference — All functions with feature gates, structs, Cargo.toml examples
- CLI Reference — All commands, flags, config precedence, exit codes
- Configuration Reference — TOML/YAML/JSON formats, auto-discovery, env vars, full schema
- Supported Formats — Format families, extensions, capabilities, and authoritative discovery commands
- Advanced Features — Plugins, embeddings, MCP server, API server, security limits
- Other Language Bindings — Go, Ruby, Java, C#, PHP, Elixir, WASM, Dart, Kotlin Android, Swift, Zig, C, and Docker
Related skills
Task-focused sibling skills go deeper than this overview:
- extracting-with-ocr — OCR backends, language packs, force-OCR, tuning.
- extracting-tables — layout-aware table detection and table models.
- chunking — chunk size/overlap, markdown/yaml/semantic chunkers, the
chunk command.
- extracting-keywords — YAKE/RAKE keywords, language detection, the
embed command.
- batch-extraction — the
batch command, --file-configs, parallelism, error recovery.
- picking-a-format — choosing
--format / --content-format per consumer.
Full documentation: https://docs.xberg.io
GitHub: https://github.com/xberg-io/xberg
1---2name: xberg3description: Extract text, tables, metadata, and images from 107 document formats (PDF, Office, images, HTML, email, archives, academic) using Xberg. Use when writing code that calls Xberg APIs in Python, Node.js/TypeScript, Rust, or CLI. Covers installation, extraction (sync/async), configuration (OCR, chunking, output format), batch processing, error handling, and plugins.4license: Elastic-2.05---6
7<!--
8AI-RULEZ :: GENERATED FILE — DO NOT EDIT
9Content-Hash: blake3:a350cdaa08f8e82becd82ed51d10fc81771a4cf74c1b619e65b424101f0a612c
10Source-Hash: blake3:b4d7bed4b4d3a6a30408bf787c69ff09c73a68092ee161ecf2a72f11338b8435
11Schema-Version: v1
12-->
13
14# Xberg Document Extraction
15
16Xberg is a document intelligence library with a Rust core and bindings for Python, TypeScript/Node.js, Ruby, PHP, Go, Java, C#, Elixir, WebAssembly, Dart, Kotlin Android, Swift, Zig, and C. It extracts text, tables, metadata, and images from 107 formats across 140 unique file extensions and accepts 53 compatibility MIME aliases, including PDF, Office documents, images, HTML, email, archives, and academic formats.
17
18Use this skill when writing code that:
19
20- Extracts text or metadata from documents
21- Performs OCR on scanned documents or images
22- Batch-processes multiple files
23- Configures extraction options (output format, chunking, OCR, language detection)
24- Implements custom plugins (post-processors, validators, OCR backends)
25
26> If the `xberg` MCP server is registered in this session, prefer its tools over shelling out to the CLI — they expose the same extraction surface with structured arguments and results.
27
28## Installation
29
30### Python
31
32```bash
33pip install xberg
34```
35
36### Node.js
37
38```bash
39npm install @xberg-io/xberg
40```
41
42### Rust
43
44```bash
45cargo add xberg
46```
47
48```toml
49# Cargo.toml
50[dependencies]
51xberg = { version = "1.1.0", features = ["full"] }
52tokio = { version = "1", features = ["full"] }
53# feature flags: pdf, ocr, chunking, embeddings, language-detection, keywords, api, mcp
54# (or "formats" / "full" aggregates); tokio-runtime is on by default
55```
56
57### CLI
58
59```bash
60brew install xberg-io/tap/xberg
61# or run without a persistent install (the CLI proxy package self-installs the binary):
62npx @xberg-io/xberg-cli --help
63uvx --from xberg-cli xberg --help
64# or download a prebuilt binary from the latest GitHub release:
65# https://github.com/xberg-io/xberg/releases/latest
66# or build from source:
67cargo install xberg-cli
68```
69
70## Quick Start
71
72The library entry points are `extract(input, config)` and `extract_batch(inputs, config)`. Both return an `ExtractionResult` **envelope** — the extracted document(s) live in `result.results`, and per-document data (`content`, `tables`, `metadata`, …) is on each `result.results[i]`. Python and Node are async-only.
73
74### Python
75
76```python
77import asyncio
78from xberg import ExtractInput, extract, ExtractionConfig
79
80async def main() -> None:
81 result = await extract(ExtractInput(uri="document.pdf"), ExtractionConfig())
82 doc = result.results[0]
83 print(doc.content) # extracted text
84 print(doc.metadata) # document metadata
85 print(doc.tables) # extracted tables
86
87asyncio.run(main())
88```
89
90### Node.js
91
92```typescript
93import { extract } from "@xberg-io/xberg";
94
95const output = await extract({ kind: "uri", uri: "document.pdf" });
96const doc = output.results[0];
97console.log(doc.content);
98console.log(doc.metadata);
99console.log(doc.tables);
100```
101
102### Rust
103
104```rust
105use xberg::{extract, ExtractInput, ExtractionConfig};
106
107#[tokio::main]
108async fn main() -> xberg::Result<()> {
109 let output = extract(ExtractInput::from_uri("document.pdf"), &ExtractionConfig::default()).await?;
110 println!("{}", output.results[0].content);
111 Ok(())
112}
113```
114
115### CLI
116
117```bash
118xberg extract document.pdf
119xberg extract document.pdf --format json
120xberg extract document.pdf --content-format markdown
121```
122
123## Configuration
124
125All languages use the same configuration structure with language-appropriate naming conventions.
126
127### Python (snake_case)
128
129```python
130from xberg import (
131 ExtractInput, extract,
132 ExtractionConfig, OcrConfig, TesseractConfig, PdfConfig, ChunkingConfig, OutputFormat,
133)
134
135config = ExtractionConfig(
136 ocr=OcrConfig(
137 backend="tesseract",
138 language=["eng"],
139 tesseract_config=TesseractConfig(psm=6, enable_table_detection=True),
140 ),
141 pdf_options=PdfConfig(passwords=["secret123"]),
142 chunking=ChunkingConfig(max_characters=1000, overlap=200),
143 output_format=OutputFormat("markdown"),
144)
145
146result = await extract(ExtractInput(uri="document.pdf"), config)
147```
148
149### Node.js (camelCase)
150
151```typescript
152import { extract, type ExtractionConfig } from "@xberg-io/xberg";
153
154const config: ExtractionConfig = {
155 ocr: { backend: "tesseract", language: ["eng"] },
156 pdfOptions: { passwords: ["secret123"] },
157 chunking: { maxCharacters: 1000, overlap: 200 },
158 outputFormat: "markdown",
159};
160
161const output = await extract({ kind: "uri", uri: "document.pdf" }, config);
162```
163
164### Rust (snake_case)
165
166```rust
167use xberg::{extract, ExtractInput, ExtractionConfig, OcrConfig, ChunkingConfig, OutputFormat};
168
169let config = ExtractionConfig {
170 ocr: Some(OcrConfig {
171 backend: "tesseract".into(),
172 language: vec!["eng".to_string()],
173 ..Default::default()
174 }),
175 chunking: Some(ChunkingConfig {
176 max_characters: 1000,
177 overlap: 200,
178 ..Default::default()
179 }),
180 output_format: OutputFormat::Markdown,
181 ..Default::default()
182};
183
184let output = extract(ExtractInput::from_uri("document.pdf"), &config).await?;
185```
186
187### Config File (TOML)
188
189```toml
190output_format = "markdown"
191
192[ocr]
193backend = "tesseract"
194language = "eng"
195
196[chunking]
197max_characters = 1000
198overlap = 200
199
200[pdf_options]
201passwords = ["secret123"]
202```
203
204```bash
205# CLI: auto-discovers xberg.toml in current/parent directories
206xberg extract doc.pdf
207# or explicit:
208xberg extract doc.pdf --config xberg.toml
209xberg extract doc.pdf --config-json '{"ocr":{"backend":"tesseract","language":"deu"}}'
210```
211
212## Batch Processing
213
214`extract_batch` takes a list of `ExtractInput`s and returns one envelope whose `results` array holds a document per input (in input order); per-input failures are reported in `result.errors`.
215
216### Python
217
218```python
219from xberg import ExtractInput, extract_batch, ExtractionConfig
220
221inputs = [
222 ExtractInput(uri="doc1.pdf"),
223 ExtractInput(uri="doc2.docx"),
224 ExtractInput(uri="doc3.xlsx"),
225]
226output = await extract_batch(inputs, ExtractionConfig())
227
228for doc in output.results:
229 print(f"{len(doc.content)} chars extracted")
230```
231
232### Node.js
233
234```typescript
235import { extractBatch } from "@xberg-io/xberg";
236
237const output = await extractBatch([
238 { kind: "uri", uri: "doc1.pdf" },
239 { kind: "uri", uri: "doc2.docx" },
240]);
241for (const doc of output.results) {
242 console.log(`${doc.content.length} chars`);
243}
244```
245
246### Rust
247
248```rust
249use xberg::{extract_batch, ExtractInput, ExtractionConfig};
250
251let config = ExtractionConfig::default();
252let inputs = vec![ExtractInput::from_uri("doc1.pdf"), ExtractInput::from_uri("doc2.docx")];
253let output = extract_batch(inputs, &config).await?;
254```
255
256### CLI
257
258```bash
259xberg batch *.pdf --format json
260xberg batch docs/*.docx --content-format markdown
261```
262
263## OCR
264
265OCR runs automatically for images and scanned PDFs. Tesseract is the default backend (native binding, no external install required).
266
267### Backends
268
269Select with `OcrConfig.backend`:
270
271- **tesseract** (default): built-in native binding. All Tesseract languages supported.
272- **paddleocr** (`"paddleocr"` / `"paddle-ocr"`): ONNX-based PaddleOCR.
273- **vlm**: Vision-Language-Model OCR (configure via `OcrConfig.vlm_config`).
274
275Custom backends can be registered in Python/Node via `register_ocr_backend` (see [Advanced Features](references/advanced-features.md)).
276
277### Language Codes
278
279```python
280config = ExtractionConfig(ocr=OcrConfig(language=["eng"])) # English
281config = ExtractionConfig(ocr=OcrConfig(language=["eng", "deu"])) # Multiple
282# The single-string shorthand ("eng+deu") is only accepted in config files / --config-json,
283# not in the OcrConfig constructor (Python takes a list, Node takes an array).
284```
285
286### Force OCR
287
288```python
289config = ExtractionConfig(force_ocr=True) # OCR even if text is extractable
290```
291
292## Result Envelope and Document Fields
293
294`extract` / `extract_batch` return an `ExtractionResult` envelope: `results` (list of documents), `errors` (per-input failures), and `summary` (counts). Per-document fields live on each document in `results` — bind `doc = result.results[0]` (Python/Node) or `&output.results[0]` (Rust) first.
295
296| Field | Python (`doc.`) | Node.js (`doc.`) | Rust (`document.`) | Description |
297| ------------ | ---------------------- | --------------------- | ----------------------- | --------------------------------------------- |
298| Text content | `content` | `content` | `content` | Extracted text (str/String) |
299| MIME type | `mime_type` | `mimeType` | `mime_type` | Input document MIME type |
300| Metadata | `metadata` | `metadata` | `metadata` | Document metadata (flat mapping) |
301| Tables | `tables` | `tables` | `tables` | Extracted tables with cells + markdown |
302| Languages | `detected_languages` | `detectedLanguages` | `detected_languages` | Detected languages (if enabled) |
303| Chunks | `chunks` | `chunks` | `chunks` | Text chunks (if chunking enabled) |
304| Images | `images` | `images` | `images` | Extracted images (if enabled) |
305| Elements | `elements` | `elements` | `elements` | Semantic elements (if element_based format) |
306| Pages | `pages` | `pages` | `pages` | Per-page content (if page extraction enabled) |
307| Keywords | `extracted_keywords` | `extractedKeywords` | `extracted_keywords` | Extracted keywords (if enabled) |
308
309## Error Handling
310
311### Python
312
313`extract` / `extract_batch` raise a plain `RuntimeError` on failure — the typed `XbergError` subclasses are not raised by these entry points, so catch `RuntimeError`. Per-input failures during `extract_batch` are reported non-fatally in `result.errors`.
314
315```python
316from xberg import ExtractInput, extract, ExtractionConfig
317
318try:
319 result = await extract(ExtractInput(uri="file.pdf"), ExtractionConfig())
320 for err in result.errors:
321 print(f"Per-input error: {err}")
322except RuntimeError as e:
323 print(f"Extraction failed: {e}")
324```
325
326### Node.js
327
328The Node binding throws plain `Error` objects (it does not export typed error subclasses). Catch with `instanceof Error`, and inspect `output.errors` for non-fatal per-input failures.
329
330```typescript
331import { extract } from "@xberg-io/xberg";
332
333try {
334 const output = await extract({ kind: "uri", uri: "file.pdf" });
335 if (output.errors.length > 0) {
336 console.error("Per-input errors:", output.errors);
337 }
338} catch (e) {
339 if (e instanceof Error) {
340 console.error(`Extraction failed: ${e.message}`);
341 }
342}
343```
344
345### Rust
346
347```rust
348use xberg::{extract, ExtractInput, ExtractionConfig, XbergError};
349
350let config = ExtractionConfig::default();
351match extract(ExtractInput::from_uri("file.pdf"), &config).await {
352 Ok(output) => println!("{}", output.results[0].content),
353 Err(XbergError::Parsing { message, .. }) => eprintln!("Parse error: {message}"),
354 Err(XbergError::Ocr { message, .. }) => eprintln!("OCR error: {message}"),
355 Err(XbergError::UnsupportedFormat(mime)) => eprintln!("Unsupported: {mime}"),
356 Err(e) => eprintln!("Error: {e}"),
357}
358```
359
360## Common Pitfalls
361
3621. **Result is an envelope**: `extract` / `extract_batch` return `ExtractionResult` with `results`, `errors`, and `summary`. Per-document fields (`content`, `tables`, `chunks`, …) are on `result.results[i]`, NOT on the top-level return.
3632. **Async-only**: Python and Node have no sync variants — always `await extract(...)`. Rust `extract` is async; use `#[tokio::main]` or an async context.
3643. **Build the input**: pass an `ExtractInput`, not a bare path. Use `ExtractInput(uri=...)` / `ExtractInput::from_uri(...)` (Python/Rust) or `{ kind: "uri", uri: "..." }` (Node); for bytes use `kind="bytes"` with `bytes`/`mime_type`.
3654. **Python ChunkingConfig fields**: construct with `max_characters` and `overlap` (defaults 1000 / 200); these are also the readable attributes. When passing config as a dict/JSON, the `max_chars` / `max_overlap` aliases are also accepted. Node uses `maxCharacters` / `overlap`; Rust struct fields are `max_characters` / `overlap`.
3665. **Python errors**: `extract` / `extract_batch` raise a plain `RuntimeError` on failure, not typed `XbergError` subclasses — catch `RuntimeError`. Node throws plain `Error` (no typed error subclasses).
3676. **Rust extract signature**: `extract(input, &config)` — the config is a reference. Use `&ExtractionConfig::default()` for defaults.
3687. **CLI --format vs --content-format**: `--format` controls CLI output (`text`, `json`, or `toon`). `--content-format` controls content rendering (`plain`, `markdown`, `djot`, `html`, `json`, or `doctags`).
3698. **Config file field names**: Use snake_case in TOML/YAML/JSON config files — `[chunking]` fields are `max_characters` and `overlap`; other fields use names like `output_format`, `pdf_options`.
370
371## Supported Formats (Summary)
372
373| Category | Extensions |
374| ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
375| **PDF** | `.pdf` |
376| **Word** | `.docx`, `.docm`, `.doc`, `.dotx`, `.dotm`, `.dot`, `.odt`, `.pages`, `.wpd`, `.wp`, `.wp5`, `.wp6`, `.hwp`, `.hwpx` |
377| **Spreadsheets** | `.xlsx`, `.xlsm`, `.xlsb`, `.xls`, `.xla`, `.xlam`, `.xltm`, `.xltx`, `.xlt`, `.ods`, `.numbers` |
378| **Presentations** | `.pptx`, `.pptm`, `.ppt`, `.pps`, `.ppsx`, `.potx`, `.potm`, `.pot`, `.odp`, `.key` |
379| **eBooks** | `.epub`, `.fb2` |
380| **Images** | `.png`, `.jpg`, `.jpeg`, `.gif`, `.webp`, `.bmp`, `.tiff`, `.tif`, `.jp2`, `.jpg2`, `.j2c`, `.j2k`, `.jpc`, `.jbig2`, `.jb2`, `.pnm`, `.pbm`, `.pgm`, `.ppm`, `.heic`, `.heics`, `.heif`, `.heifs`, `.hif`, `.avif`, `.avcs`, `.svg` |
381| **Markup** | `.html`, `.htm`, `.xhtml`, `.xht`, `.xml`, `.kml` |
382| **Data** | `.json`, `.geojson`, `.jsonl`, `.ndjson`, `.yaml`, `.yml`, `.toml`, `.csv`, `.tsv`, `.dbf`, `.sqlite`, `.sqlite3`, `.db`, `.gpkg`, `.gpkx` |
383| **Text** | `.txt`, `.adoc`, `.asciidoc`, `.vtt`, `.md`, `.markdown`, `.commonmark`, `.qmd`, `.rmd`, `.mdx`, `.djot`, `.dj`, `.doctags`, `.rst`, `.org`, `.rtf` |
384| **Email** | `.eml`, `.msg`, `.pst` |
385| **Archives** | `.zip`, `.tar`, `.tgz`, `.gz`, `.7z` |
386| **Audio/Video** | `.mp3`, `.mpga`, `.m4a`, `.wav`, `.webm`, `.mp4`, `.mpg4`, `.mp4v`, `.m4v`, `.mpeg`, `.mpg`, `.mpe`, `.m1v`, `.m2v` |
387| **Academic** | `.bib`, `.ris`, `.nbib`, `.enw`, `.tex`, `.latex`, `.typ`, `.typst`, `.jats`, `.nxml`, `.ipynb`, `.docbook`, `.dbk`, `.docbook4`, `.docbook5`, `.opml` |
388
389CSL JSON is supported through an explicit MIME type but does not have a registered file extension.
390
391See [references/supported-formats.md](references/supported-formats.md) for the complete format reference with MIME types.
392
393## Additional Resources
394
395Detailed reference files for specific topics:
396
397- **[Python API Reference](references/python-api.md)** — All functions, config classes, plugin protocols, exact signatures
398- **[Node.js API Reference](references/nodejs-api.md)** — All functions, TypeScript interfaces, worker pool APIs
399- **[Rust API Reference](references/rust-api.md)** — All functions with feature gates, structs, Cargo.toml examples
400- **[CLI Reference](references/cli-reference.md)** — All commands, flags, config precedence, exit codes
401- **[Configuration Reference](references/configuration.md)** — TOML/YAML/JSON formats, auto-discovery, env vars, full schema
402- **[Supported Formats](references/supported-formats.md)** — Format families, extensions, capabilities, and authoritative discovery commands
403- **[Advanced Features](references/advanced-features.md)** — Plugins, embeddings, MCP server, API server, security limits
404- **[Other Language Bindings](references/other-bindings.md)** — Go, Ruby, Java, C#, PHP, Elixir, WASM, Dart, Kotlin Android, Swift, Zig, C, and Docker
405
406## Related skills
407
408Task-focused sibling skills go deeper than this overview:
409
410- **extracting-with-ocr** — OCR backends, language packs, force-OCR, tuning.
411- **extracting-tables** — layout-aware table detection and table models.
412- **chunking** — chunk size/overlap, markdown/yaml/semantic chunkers, the `chunk` command.
413- **extracting-keywords** — YAKE/RAKE keywords, language detection, the `embed` command.
414- **batch-extraction** — the `batch` command, `--file-configs`, parallelism, error recovery.
415- **picking-a-format** — choosing `--format` / `--content-format` per consumer.
416
417Full documentation: <https://docs.xberg.io>
418GitHub: <https://github.com/xberg-io/xberg>