anydoc: Convert Office Docs to Clean Markdown at Sub-5ms Speeds
anydoc
| What it is | A Rust library that turns 14 office/ebook formats into clean GitHub-Flavored Markdown |
| Platform | macOS, Linux, Windows (CLI, Python, Node.js, browser via WASM) |
| Price | Free, open source (MIT) |
| Link | github.com/firecrawl/anydoc |
Every document pipeline ends the same way: whatever format goes in, you want clean Markdown out. I’ve stitched together pandoc scripts, LibreOffice headless calls, and Python soup scrapers to get there, and each one broke on some format or other. anydoc from Firecrawl is the closest I’ve found to a single tool that just does the whole job.
It converts Word (.doc/.docx/.docm), PowerPoint, Excel, OpenDocument, RTF, EPUB, CSV, and PDF into one consistent GitHub-Flavored Markdown output. Pure Rust, no ML models, no cloud calls. Median conversion is under 5 milliseconds per document.
One output for every format. Every parser funnels into a shared document model and a single Markdown serializer, so tables, escaping, heading anchors, and footnotes behave identically whether the input is a 2003 .doc or a fresh .pptx. I converted a docx with a table, blockquote, and nested list and got back clean GFM with the table intact, no hand-fixing needed.
It is genuinely fast. The project benchmarks against six other converters on 100 real documents across 14 formats: 4.4ms median versus LibreOffice at 1129ms, pandoc at 102ms, markitdown at 135ms. That is not a marginal win, it is two to three orders of magnitude. For batch jobs on thousands of files the difference is hours.
Format detection reads the bytes, not the filename. It checks the PDF header, RTF open group, OLE stream names, and ZIP mimetype, so a mislabeled file still converts correctly. The one exception: CSV has no in-content marker, so you pass the format name explicitly or rely on the extension.
Bindings everywhere, and they stay out of the way. CLI via
npx @firecrawl/anydoc, Python viapip install firecrawl-anydoc, plus Node.js and WebAssembly for the browser. The demo page runs the whole library as WASM so files never leave your machine. Node runs on the libuv thread pool, Python releases the GIL, so neither blocks your app.The honest limitations. Scanned PDFs need OCR, which anydoc does not do; you would feed those to Firecrawl’s hosted Parse instead. And the PDF path is the weakest: my test PDF came out with bold/italic runs glued together (this is aboldtest), because it routes through pdf-inspector rather than the shared document model. Office formats are the strong suit, text PDFs work but are rougher.
It ships as an agent skill.
npx skills add firecrawl/anydocand your coding agent can read any document it runs into. That is the detail that makes this more than a library: it is designed for the LLM-pipeline use case end to end.
Worth your time if: you build RAG pipelines, batch-convert mixed office files, or want your coding agent to read docs without a cloud API call.
Install & first run
The fastest path is the CLI. First run downloads the prebuilt binary, later runs are near-instant:
npx @firecrawl/anydoc report.docx # Markdown to stdout
npx @firecrawl/anydoc slides.pptx -o slides.md # or to a fileCSV needs the format named, since the bytes carry no marker:
npx @firecrawl/anydoc - --format csv < data.csvFor scripts, the Python binding matches the CLI:
pip install firecrawl-anydocimport anydoc
markdown = anydoc.to_markdown("report.docx")
markdown = anydoc.to_markdown_bytes(data, "csv")
document = anydoc.to_document(data)The to_document variant returns the document model with embedded assets (images as alt text in Markdown, raw bytes tagged by media type on the model). See the GitHub README for the Node, WASM, and Rust APIs.
Related TMFNK Content
- Document OCR & Parsing: Docling, dots.ocr, and Alternatives For scanned documents with OCR, Docling is the better fit; anydoc handles born-digital files without an ML model.
- LiteParse: Fast Local PDF Parsing with OCR and Bounding Boxes Adds OCR and spatial bounding boxes that anydoc skips, at the cost of a heavier local stack.
- Unlimited-OCR: Parse 100-Page PDFs as One Continuous Document When the input is long scanned PDFs rather than office files, this is the model you want.
Crepi il lupo!