4.4 Milliseconds to Crush LibreOffice and Pandoc: How a Rust Library Is Sparking a Document-Processing Revolution

If you work with RAG or AI agents, you've probably lived this particular nightmare:

A stakeholder fires over a zip archive stuffed with Word, PPT, Excel, PDF—every format imaginable—and your job is to convert them all into clean Markdown to feed an LLM. LibreOffice takes over a second per document. Pandoc is a bit faster, but only supports 5 formats. In the end, you're stuck writing a separate parsing pipeline for every file type, and the maintenance burden alone makes you question your life choices.

A project that recently surfaced in the open-source community may completely change all of that.

1. What Is It?

anydoc is an open-source document conversion library from the Firecrawl team. Written entirely in Rust, it converts 14 office document formats into clean GitHub Flavored Markdown.

Supported formats:

Word: .doc, .docx, .docm

PowerPoint: .ppt, .pps, .pot, .pptx, .pptm, .ppsx, .ppsm

Excel: .xls, .xlsx, .xlsm, .xlsb

OpenDocument: .odt, .ods, .odp

RTF, EPUB, CSV, PDF

Behind it is Firecrawl—the company that built the website-to-Markdown API. anydoc has been running in production for a long time; it's the document-parsing engine underneath Firecrawl Parse.

The project is released under the MIT license, with all code fully public on GitHub.

2. The Core Design: One Model, Unified Output

This is the most fundamental difference between anydoc and every competitor out there.

Most conversion tools take the approach of "writing a dedicated parser per format that emits Markdown directly." docx goes down one code path, pptx down another, rtf down yet another. Output quality is wildly inconsistent, and fixing a bug in one format leaves the same problems untouched in the others.

anydoc does something completely different:

Each format's parser first parses the document into a single intermediate representation (the Document Model), and then all formats share the same Markdown serializer.

Architecture at a glance:

Document bytes

→ Format detection (based on content signatures, not file extensions)

→ Format parsers (doc / docx / ppt / pptx / xls / xlsx / odt / ods / odp / rtf / epub / csv)

→ Document Model (unified intermediate representation: blocks, inline elements, tables, footnotes, resources)

→ GFM serializer → Markdown

Meanwhile, PDFs take a separate path: PDF → pdf-inspector → converted directly to Markdown

What does this mean in practice? A single fix to the table-escaping rules simultaneously fixes the output for docx, rtf, odt, and every other format. Output consistency is guaranteed, and maintenance costs drop to a minimum.

The information preserved in the Document Model is remarkably complete:

Heading hierarchy with anchors

Bold, italic, strikethrough

Inline code and code blocks

Links and internal cross-references

Bulleted lists with original numbering, numbered lists, nested lists, task lists

Tables with merged cells and header rows

Block quotes, footnotes, endnotes

Speaker notes

Embedded resources are handled cleanly too: images are rendered as Markdown alt text, while the original bytes are preserved in the Document Model with media type tags, so you can process them yourself downstream.

3. Format Detection: Content, Not Extensions

Many conversion tools identify formats by file extension. In the real world, though, extensions are frequently wrong—a PDF that someone renamed to .doc, for instance.

anydoc's format detection reads signatures directly from the file's contents:

PDF: reads the PDF header

RTF: reads the RTF opening marker

OLE formats (.doc, .ppt, .xls): reads the OLE stream names

ZIP-based formats (.docx, .pptx, .xlsx): reads the ZIP package's mimetype and content types

Only formats without embedded markers, such as CSV, require you to explicitly specify an extension or format parameter.

Rust, Node.js, and Python all provide three APIs: format_from_bytes, format_from_extension, and format_from_path.

4. Performance: Not Just Talk—A Total Rout

Let's go straight to the numbers.

The anydoc team ran a benchmark comparing 6 similar tools on 100 real-world documents. Scoring was done blind by Claude Sonnet 5 across four dimensions—completeness, structure preservation, format fidelity, and output cleanliness—with each pair of outputs judged twice in swapped order to eliminate position bias, for a total of 481 judgments.

Overall scores (0–100):

anydoc — 14/14 formats supported, 4.4 ms median time, overall score 81

libreoffice — 12/14, 1129.5 ms, 39

unstructured — 8/14, 572.9 ms, 62

markitdown — 6/14, 134.8 ms, 64

pandoc — 5/14, 102.1 ms, 56

docling — 4/14, 513.6 ms, 57

mammoth — 1/14, 52.5 ms, 69

With a median time of 4.4 milliseconds, it beats the second-fastest tool, pandoc (102 ms), by a full order of magnitude. At that speed, 500 DOCX files can be processed in about 2.2 seconds.

Format-by-format comparison (higher scores are better; a dash means the tool doesn't support that format):

doc — anydoc 87, libreoffice 57, unstructured 67

docm — anydoc 85, libreoffice 45

docx — anydoc 86, libreoffice 54, unstructured 53, markitdown 73, pandoc 67, docling 71, mammoth 69

epub — anydoc 77, unstructured 72, markitdown 72, pandoc 52

odp — anydoc 86, libreoffice 23

ods — anydoc 82, libreoffice 38

odt — anydoc 80, libreoffice 52, unstructured 68, pandoc 60

ppt — anydoc 80, libreoffice 26

pptx — anydoc 75, libreoffice 24, markitdown 61, docling 52

rtf — anydoc 88, libreoffice 54, unstructured 45, pandoc 44

xls — anydoc 80, libreoffice 38, unstructured 66, markitdown 62

xlsm — anydoc 76, libreoffice 32

xlsx — anydoc 72, libreoffice 30, unstructured 66, markitdown 55, docling 47

anydoc is the only tool that covers all 14 formats, and it posts the highest score in every format where a comparison exists.

Speed test environment: Ryzen 9 9950X3D, Windows 11, 64GB DDR5-6400. Timing for anydoc and the Python libraries excluded process startup overhead; CLI tools included process startup, since that's how they're actually used in practice.

5. PDF Support: No Dependence on OCR Services

anydoc converts text-based PDFs directly through its built-in pdf-inspector, without calling any external OCR service.

Roughly 54% of PDFs in the wild are pure text, and those can be converted entirely locally—zero network latency, zero API costs.

For scanned or image-based PDFs (anydoc returns an Unsupported error), you have two options:

Process them with another OCR tool first, then feed the resulting text to anydoc

Use Firecrawl's hosted API version, which comes with built-in OCR models

6. Multi-Language Bindings: Node.js, Python, Browser, Rust

anydoc isn't just a Rust library—it offers full cross-language support.

CLI (one command does it all):

npx @firecrawl/anydoc report.docx

npx @firecrawl/anydoc slides.pptx -o slides.md

npx @firecrawl/anydoc - --format csv < data.csv   # reads from stdin

The first run automatically downloads a precompiled binary; for a global install, use npm install -g @firecrawl/anydoc.

Node.js (conversions run on a thread pool, so the event loop is never blocked):

import { toMarkdown } from '@firecrawl/anydoc';

const markdown = await toMarkdown('report.docx');

Python (the GIL is released during conversion, so other threads keep running):

import anydoc

markdown = anydoc.to_markdown("report.docx")

Browser (WebAssembly) (files are converted locally, never uploaded to any server):

import init, { toMarkdownBytes } from '@firecrawl/anydoc-wasm';

await init();

const markdown = toMarkdownBytes(bytes);

There's also an official online demo that runs the WASM build directly in your browser—your files never leave your machine.

Rust (direct crate integration):

let markdown = anydoc::to_markdown("report.docx")?;

7. Agent Skill: AI Coding Assistants Can Read Documents Directly

anydoc also ships with built-in Agent Skill support:

npx skills add firecrawl/anydoc

This single command teaches AI coding assistants like Claude Code, Codex, Cursor, and OpenCode how to use anydoc to read documents. When your agent runs into a Word or PDF file, it can call anydoc directly to convert it to Markdown and then process it.

8. Error Handling: Finely Grained Failure Classification

anydoc breaks conversion failures down into fine-grained categories:

Unsupported — unknown format or impossible to convert (e.g., image-based PDFs)

Malformed — corrupted structure; no meaningful content can be extracted

Encrypted — encrypted or password-protected

ResourceLimit — exceeds safety limits (decompression, nesting depth, node count)

MissingPart — required part missing

Io — file read failure

Node.js and WASM expose the error type via error.code; Python raises the corresponding anydoc.ConvertError subclass.

This finely grained error classification is extremely practical in production pipelines—you can handle different failures differently, say by logging encrypted files separately instead of letting the entire workflow crash.

9. Where It Shines

anydoc is best suited for pipelines that need to batch-process documents in mixed formats:

Document preprocessing for RAG systems

File-reading capability for AI agents

Index building for internal enterprise documents

Any step where office documents need to be turned into LLM input

Project page: github.com/firecrawl/anydoc

Related Articles

分享網址
AINews·AI 新聞聚合平台
© 2026 AINews. All rights reserved.