Mixedbread parsing
Parse documents, extract structured content, and run OCR using the Mixedbread Parsing API. Use when parsing PDFs, Word documents, PowerPoint slides, or images, extracting tables or form fields, running OCR on scanned documents, converting documents to markdown or HTML, or extracting structured chunks with element-level bounding boxes and confidence scores.From its SKILL.md
npx -y skills add mixedbread-ai/skills --skill mixedbread-parsingAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
3 things to look at
- reads credentialsReads from 1 credential source: `MXBAI_API_KEY`.
- 7 stars7 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
- runs commandsInstructs the agent to run 3 commands, including `pip install mixedbread` and 2 more.
SKILL.md
7.9 KB, ~1.8k tokens by cl100k_base, as published. Nobody here has run it
Mixedbread Parsing
Parse documents, extract structured content, and run OCR using the Parsing API. Supports PDFs, Word documents, PowerPoint presentations, and images.
Docs: https://www.mixedbread.com/docs/parsing/overview.md Agent-readable docs: https://www.mixedbread.com/docs/llms.txt Latest docs search: https://www.mixedbread.com/question?q=parsing§ion=docs
Setup
pip install mixedbread # Python
npm install @mixedbread/sdk # TypeScript
export MXBAI_API_KEY=your_api_key
Quick Start
Python:
from mixedbread import Mixedbread
mxbai = Mixedbread()
# Upload and parse a document (waits for completion)
job = mxbai.parsing.jobs.upload_and_poll(
file=open("report.pdf", "rb"),
return_format="markdown",
)
for chunk in job.result.chunks:
print(chunk.content)
TypeScript:
import Mixedbread from '@mixedbread/sdk';
import fs from 'fs';
const mxbai = new Mixedbread();
const job = await mxbai.parsing.jobs.uploadAndPoll(
fs.createReadStream('report.pdf'),
{ return_format: 'markdown' },
);
for (const chunk of job.result.chunks) {
console.log(chunk.content);
}
Decision Tree
- Which convenience method?
- File on disk →
upload_and_poll()(uploads + creates job + polls) - File already uploaded via Files API →
create_and_poll()(creates job + polls) - Need async control →
upload()orcreate()thenpoll()separately
- File on disk →
- Which parsing mode? (default is
high_quality)- Born-digital PDF (selectable text) → pass
mode="fast"explicitly. Fastest, lowest cost. Extracts text, structure, and layout. - Scanned document, image, or complex layout →
high_qualitymode (the default). Uses OCR. Extracts text with confidence scores and per-element bounding boxes, handles rotated/skewed pages, multi-column layouts.
- Born-digital PDF (selectable text) → pass
- Which return format? →
return_format:markdown(default),html, orplain - Need specific elements only? → Set
element_typesto reduce processing time
Supported File Types
PDF (.pdf), Word (.doc, .docx, .dotx, .docm, .dotm, .odt, .rtf), Slides (.ppt, .pptx, .ppsx, .ppam, .pptm, .potm, .ppsm, .odp), Images (.jpeg, .png, .webp, .avif).
Element types: text, title, section-header, header, footer, page-number, list-item, figure, table, form, footnote. (Legacy values picture, caption, formula, page-header, and page-footer are accepted but normalized to figure/text/header/footer.)
Each extracted element carries type, content, page, confidence (0–1), and bbox — the bounding box [x1, y1, x2, y2] in page pixel coordinates. Use bboxes to map OCR output back to its location on the page (e.g. evidence highlighting).
Chunking: chunking_strategy defaults to page (currently the only strategy) — one chunk per page.
Workflows
Extract Tables from Documents
Filter for table elements to pull structured data from reports.
Python:
job = mxbai.parsing.jobs.upload_and_poll(
file=open("financial-report.pdf", "rb"),
element_types=["table"],
return_format="html",
mode="high_quality",
)
for chunk in job.result.chunks:
for element in chunk.elements:
if element.type == "table":
print(f"Page {element.page}, confidence {element.confidence:.2f}, bbox {element.bbox}")
print(element.content)
TypeScript:
const job = await mxbai.parsing.jobs.uploadAndPoll(
fs.createReadStream('financial-report.pdf'),
{ element_types: ['table'], return_format: 'html', mode: 'high_quality' },
);
for (const chunk of job.result.chunks) {
for (const element of chunk.elements) {
if (element.type === 'table') {
console.log(`Page ${element.page}, confidence ${element.confidence.toFixed(2)}, bbox ${element.bbox}`);
console.log(element.content);
}
}
}
Batch Parse Multiple Files
Upload multiple files asynchronously, then poll all jobs:
Python:
import os
jobs = []
for filename in os.listdir("./documents"):
if filename.endswith(".pdf"):
job = mxbai.parsing.jobs.upload(
file=open(f"./documents/{filename}", "rb"),
return_format="markdown",
)
jobs.append(job)
# Poll all jobs
for job in jobs:
completed = mxbai.parsing.jobs.poll(job_id=job.id)
print(f"{completed.filename}: {len(completed.result.chunks)} chunks")
TypeScript:
import { readdirSync, createReadStream } from 'fs';
import path from 'path';
const files = readdirSync('./documents').filter(f => f.endsWith('.pdf'));
const jobs = await Promise.all(
files.map(f => mxbai.parsing.jobs.upload(
createReadStream(path.join('./documents', f)),
{ return_format: 'markdown' },
)),
);
// Poll all jobs
for (const job of jobs) {
const completed = await mxbai.parsing.jobs.poll(job.id);
console.log(`${completed.filename}: ${completed.result.chunks.length} chunks`);
}
Rules
CRITICAL
- Don't double-parse. Store uploads auto-parse documents. Files uploaded with
parsing_strategy: "high_quality"automatically get OCR text (images), summaries (images), and transcriptions (audio & video) extracted. These are available as fields on search result chunks. There is no benefit to also running the Parsing API on the same file. Use the Parsing API only for standalone document extraction outside of stores. - Use
upload_and_poll()/create_and_poll()instead of manual polling loops. These methods handle backoff automatically. Manualwhileloops withretrieve()are fragile and waste API calls.
HIGH
- Specify
element_typeswhen you only need certain elements. Requesting all types increases processing time and response size. If you only need tables, setelement_typestotableonly. - Use
fastmode for born-digital PDFs. Thehigh_qualitymode adds OCR overhead that provides no benefit when text is already selectable. - Check
confidencescores on OCR output. Low-confidence elements (< 0.5) may contain errors. Filter or flag them.
MEDIUM
- Check
job.errorbefore retrying failed jobs. Common causes: unsupported file type, corrupt file, file too large. Blindly retrying wastes quota. - Use
content_to_embedfor embedding pipelines. Each chunk provides bothcontent(full text) andcontent_to_embed(optimized for embedding). Use the latter when feeding into vector stores outside Mixedbread. - Verify file format before parsing. Only PDF, Word, PowerPoint, and images are supported. Convert other formats first.
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
Job stuck in pending | Queue is busy | Use poll() with a longer poll_timeout_ms. Check job status with retrieve(). |
Job status failed | Unsupported file type, corrupt file, or file too large | Check job.error for details. Verify file format is supported. |
| Empty chunks in result | File has no extractable content (blank pages) | Verify the file has content. Try high_quality mode for scanned documents. |
| Low confidence scores | Scanned or low-resolution source | Use high_quality mode for better OCR accuracy. |
| Missing tables or figures | Element types not requested | Set element_types to include table and figure explicitly. |
upload_and_poll() timeout | Very large document or slow processing | Increase poll_timeout_ms, or use upload() + poll() separately for more control. |
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.
Gives 0 of the 12 instructions most pdf office docs skills give in ~1.8k tokens
Counted across 569 of the 585 authors here whose files we hold, read 2026-09-06
- Ensure every slide fits inside one viewportin 20 of 569, across 11 files
- Check for product marketing context firstin 15 of 569, across 5 files
- Ask for the minimum neededin 15 of 569, across 5 files
- Set the API key environment variablein 15 of 569, across 10 files
- Support keyboard and touch navigationin 14 of 569, across 5 files
- Match the buyer stagein 13 of 569, across 3 files
- Split overflowing content into multiple slidesin 12 of 569, across 3 files
- Set page size explicitly for consistent resultsin 12 of 569, across 5 files
- Convert documents to markdown using pandocin 12 of 569, across 6 files
- Read STYLE_PRESETS.md before generatingin 12 of 569, across 7 files
- Send multipart POST requests to the APIin 12 of 569, across 7 files
- Use smart quotes for new contentin 11 of 569, across 4 files
Said here and by no other author read
- Use upload_and_poll instead of manual loops
- Specify element_types for specific elements
- Use fast mode for born-digital PDFs
- Check confidence scores on OCR output
- Check job.error before retrying failed jobs
- Use content_to_embed for embedding pipelines
Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once. Length counted with cl100k_base; the agent that loads this file may tokenize it differently.