
Extracting Tables
- 1 installs
- 26 repo stars
- Updated July 27, 2026
- kreuzberg-dev/plugins
Extracts tabular data from PDFs, spreadsheets, and images using layout-aware detection, outputting Markdown tables or structured JSON cells.
About
Covers Kreuzberg's layout-aware table extraction from PDFs, spreadsheets, and images with selectable table models and Markdown or JSON cell output. A developer uses it to pull financial statements, invoices, or scientific tables into structured data.
- RT-DETR layout detection plus selectable table models (tatr, slanet variants)
- Markdown tables for LLMs or structured cells[][] JSON for exact access
Extracting Tables by the numbers
- 1 all-time installs (skills.sh)
- Ranked #565 of 688 Office & Documents skills by installs in the Skillselion catalog
- Data as of Aug 4, 2026 (Skillselion catalog sync)
npx skills add https://github.com/kreuzberg-dev/plugins --skill extracting-tablesAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 1 |
|---|---|
| repo stars | ★ 26 |
| Last updated | July 27, 2026 |
| Repository | kreuzberg-dev/plugins ↗ |
What it does
Extracts tabular data from PDFs, spreadsheets, and images using layout-aware detection, outputting Markdown tables or structured JSON cells.
Files
Extracting tables
Use this when the user wants structured tabular data — financial statements, scientific tables, invoices, spreadsheet-style PDFs. Kreuzberg detects tables via a layout model (RT-DETR v2) and reconstructs cell structure with a configurable table model.
Basic usage
# Markdown tables embedded in the content stream
kreuzberg extract report.pdf --layout --content-format markdown
# Structured JSON output, tables appear under result.tables
kreuzberg extract report.pdf --layout --format json--layout turns on layout-aware extraction; without it, tables fall back to plain text reflow and you lose cell boundaries.
Output shapes
Two surfaces, picked via --format (CLI shape) and --content-format (content rendering):
- Markdown tables in `content` —
--content-format markdown. Tables
appear inline as | col | col | blocks. Good for LLM ingestion.
- Structured `tables` array —
--format json. Each entry has
cells[][] (rows × cols), markdown (pre-rendered), page_index, bbox. Use this when downstream code needs exact cell access.
Both are populated at once when --layout is on. The tables array is always structured; the content stream switches representation.
kreuzberg extract financials.pdf --layout --format json \
| jq '.tables[] | {page: .page_index, rows: (.cells | length)}'Table models
--layout-table-model picks the reconstruction backend:
| Model | Best for | Notes |
|---|---|---|
tatr | dense complex tables (academic, financial) | Default. Heaviest, highest accuracy. |
slanet_auto | dispatches per-table to wired/wireless | Good when table styles are mixed. |
slanet_wired | tables with visible borders | Faster than tatr. |
slanet_wireless | tables without borders (whitespace-separated) | For invoices, simple grids. |
slanet_plus | hybrid wired / wireless | Lighter than slanet_auto. |
disabled | layout detection only, no table structure | Use to skip table model cost. |
kreuzberg extract bank-statement.pdf \
--layout --layout-table-model tatr --content-format markdownDrop --layout-confidence when the layout model misses tables (default threshold ~0.5):
kreuzberg extract noisy-scan.pdf --layout --layout-confidence 0.3Spreadsheets
.xlsx, .ods, .csv, .tsv are extracted by dedicated parsers — no layout model needed. Each sheet becomes a markdown table (or structured table) automatically:
kreuzberg extract workbook.xlsx --content-format markdown
kreuzberg extract data.csv --format jsonPass --no-cache=true only when iterating on the same file with different configs.
Config file alternative
# `output_format` in config files equals `--content-format` on the CLI.
output_format = "markdown"
[layout_detection]
enabled = true
confidence_threshold = 0.5
table_model = "tatr"Then:
kreuzberg extract report.pdf --format jsonProgrammatic access
From Python, structured tables live on result.tables:
from kreuzberg import extract_file_sync, ExtractionConfig, LayoutDetectionConfig
config = ExtractionConfig(
layout_detection=LayoutDetectionConfig(enabled=True, table_model="tatr"),
output_format="markdown",
)
result = extract_file_sync("report.pdf", config=config)
for table in result.tables:
print(table.markdown) # rendered markdown
print(table.cells[0][0]) # cell accessNode.js mirrors this (extractFile, result.tables, camelCase fields). See references/python-api.md and references/nodejs-api.md in the sibling kreuzberg skill for full type signatures.
Known limitations
- Merged cells — reconstructed as repeated values across the spanned
region; the merge is not preserved as metadata in v0.1.
- Rotated tables — enable
--ocr-auto-rotate truefor image-based
PDFs before extraction.
- Nested tables — flattened. Detection succeeds; structural nesting is
lost.
- Multi-page tables — each page yields a separate
tables[]entry.
Stitch by matching column headers if needed.
- ONNX Runtime required — layout and table models are unavailable in
WASM builds and on the Android x86_64 emulator; native targets ship full support.
Common failure modes
- Empty `tables` with `--layout` on — confidence threshold too high or
table model mismatched. Drop --layout-confidence to 0.3, try --layout-table-model tatr.
- Markdown tables look ragged — switch
--layout-table-modelto
slanet_wired for bordered grids or slanet_wireless for invoices.
- Slow extraction —
tatris heavy. Useslanet_autoor
slanet_plus as a default; reach for tatr only when accuracy matters.
See references/cli-reference.md for the full layout flag set and references/advanced-features.md for the layout pipeline internals.