Firecrawl has released anydoc, an open-source library written in Rust that converts Word, Excel, PowerPoint, OpenDocument, RTF, EPUB, CSV, and PDF files into Markdown ready for AI pipelines, RAG systems, automation workflows, and agents. For developers and system administrators, its main appeal is not just speed: it can run locally from the CLI, Node.js, Python, or WebAssembly, without requiring an external document-processing service.

The key facts about anydoc in 20 seconds

  • It converts common office documents to Markdown from the CLI or application code.
  • Its core is written in Rust, with bindings for Node.js, Python, and browsers.
  • It supports both modern and legacy formats such as .doc, .xls, and .ppt.
  • It can be integrated with agents such as Claude Code, Codex, Cursor, and OpenCode.
  • OCR is not built in, so scanned PDFs require an additional processing stage.

For anyone managing document pipelines, the problem is familiar. An AI application rarely receives plain text alone. Real-world environments contain .docx files, Excel spreadsheets, presentations, PDFs, legacy Office documents, and OpenDocument files.

Before those files can be indexed, stored in a vector database, or passed to a model, they usually need to be normalized.

Markdown has become a useful intermediate format for this task because it preserves enough structure, including headings, lists, tables, links, and code blocks, without carrying all the visual complexity of the original document.

One CLI for Word, Excel, PowerPoint, and PDF

Basic use of anydoc is straightforward.

It can be executed directly with npx:

npx @firecrawl/anydoc report.docxCode language: CSS (css)

To save the output:

npx @firecrawl/anydoc slides.pptx -o slides.mdCode language: CSS (css)

It can also accept data through stdin:

cat data.csv | npx @firecrawl/anydoc - --format csv

That makes it particularly convenient for shell scripts and automated pipelines.

A simple batch conversion could look like this:

find ./documents -type f -name "*.docx" -print0 |
while IFS= read -r -d '' file; do
    npx @firecrawl/anydoc "$file" -o "${file%.docx}.md"
doneCode language: JavaScript (javascript)

The resulting Markdown can then move to a chunking, indexing, embedding, or inference stage.

For servers, containers, and CI runners, this approach can also avoid installing a complete office suite just to extract structured content from documents.

Why Rust matters here

anydoc uses Rust for its core and exposes the same functionality through different interfaces.

The architecture can be simplified as:

                 anydoc core
                    Rust
                      │
        ┌─────────────┼──────────────┐
        │             │              │
        ▼             ▼              ▼
      Node.js       Python          WASM
        │             │              │
     Backend       Scripts        BrowserCode language: CSS (css)

A Node.js application can use it directly:

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

const markdown = await toMarkdown('report.docx');Code language: JavaScript (javascript)

The equivalent in Python is similarly straightforward:

import anydoc

markdown = anydoc.to_markdown("report.docx")Code language: JavaScript (javascript)

WebAssembly support means conversion can also happen directly inside a browser.

That creates some interesting possibilities for applications handling sensitive information. A document can, depending on the architecture, be converted locally before deciding which extracted information should subsequently be sent to a backend or AI model.

This does not automatically solve every privacy concern, but it makes architectures possible in which document conversion itself does not require uploading the complete original file to a third-party service.

Format detection goes beyond the file extension

Another useful feature for automation is that anydoc attempts to identify documents from their binary contents rather than relying exclusively on their filenames.

A pipeline therefore does not have to blindly assume that:

document.docxCode language: JavaScript (javascript)

is actually a DOCX file.

This matters in production systems where uploads may have incorrect extensions, files may have been renamed, or APIs may deliver binary data without reliable filenames.

The parser can inspect signatures and structures associated with the different formats before choosing the appropriate conversion mechanism.

A document ingestion pipeline could therefore look like this:

upload
  │
  ▼
binary detection
  │
  ├── DOCX
  ├── XLS
  ├── PPT
  ├── PDF
  └── ODT
  │
  ▼
parser
  │
  ▼
Markdown

CSV is a logical exception because it does not provide an equivalent binary signature and may require an explicit format hint.

A common internal document model

One of the more interesting technical details is that anydoc parsers do not independently generate Markdown.

Instead, they first create a common internal representation of the document.

That representation can contain elements such as paragraphs, headings, inline elements, lists, tables, links, footnotes, and resources.

A single serializer then turns this intermediate representation into Markdown.

This architecture can improve maintainability. If the project fixes how a particular table structure or list is serialized, multiple input formats can benefit from the change instead of each parser maintaining separate Markdown-rendering logic.

For developers maintaining document-ingestion software, that consistency can matter as much as raw conversion speed.

Legacy Office formats are supported too

Legacy files are often overlooked when companies begin building AI and RAG systems.

Enterprise file servers do not contain only .docx, .xlsx, and .pptx documents. Years of accumulated data may also include:

.doc
.xls
.ppt
.pps
.pot
.rtfCode language: CSS (css)

anydoc currently lists support for:

FamilySupported formats
Word.doc, .docx, .docm
PowerPoint.ppt, .pps, .pot, .pptx, .pptm, .ppsx, .ppsm
Excel.xls, .xlsx, .xlsm, .xlsb
OpenDocument.odt, .ods, .odp
Others.rtf, .epub, .csv, .pdf

For document migrations or enterprise RAG projects, support for .doc and .xls can be considerably more useful than it might initially appear.

anydoc vs MarkItDown, Docling, Pandoc, and Unstructured

Although these projects are often compared, they do not solve exactly the same problem.

ToolBest suited for
anydocFast, local document-to-Markdown conversion
MarkItDownStraightforward extraction from multiple formats for LLMs
DoclingAdvanced document understanding and complex PDFs
PandocGeneral conversion between a large number of formats
UnstructuredIngestion, partitioning, cleaning, and chunking pipelines

anydoc focuses primarily on traditional parsing and speed.

Docling goes further into understanding complex document structures. It can work with layouts, tables, formulas, and other document components, making its computational profile fundamentally different from a lightweight converter.

Pandoc also belongs to a broader category. It remains a general-purpose document converter capable of translating content between a very large number of input and output formats.

For example:

pandoc document.docx -t gfm -o document.mdCode language: JavaScript (javascript)

remains a perfectly valid way to generate GitHub-Flavored Markdown.

The relevant question is therefore not which tool universally wins, but which dependencies, formats, performance characteristics, and integration options a particular pipeline requires.

The benchmark reports millisecond-level conversions, with caveats

Firecrawl has published a benchmark using 100 real-world documents across 14 formats.

According to its results, anydoc achieved a median processing time of 4.4 milliseconds per document, with the other tested alternatives recording higher figures.

The number is impressive, but it should not be treated as a universal result.

The benchmark was produced by the project itself, each competing tool covered a different number of formats, and some alternatives perform substantially more work than direct document-to-Markdown conversion.

Process startup can also distort comparisons between an embedded Rust library and external CLI tools or systems that load machine-learning models.

For sysadmins, the more useful conclusion is that anydoc appears lightweight enough to make high-volume document conversion inside local services and CI pipelines a realistic use case.

What happens with scanned PDFs?

This is currently one of its most important limitations.

anydoc does not include OCR.

If a PDF contains an actual text layer:

PDF
 └── text layer
      └── anydoc

it can be processed.

If the PDF is essentially a collection of scanned images:

PDF
 └── images
      └── OCR required

another tool needs to enter the pipeline.

That suggests an architecture such as:

                  PDF
                   │
             inspect content
             ┌─────┴─────┐
             │           │
           text        scanned
             │           │
          anydoc         OCR
             │           │
             └─────┬─────┘
                   ▼
                Markdown
                   │
                   ▼
                chunking
                   │
                   ▼
                  RAG

This can be more efficient than sending every PDF through OCR when most documents already contain machine-readable text.

A useful component for containers and CI/CD

For system administrators, one particularly interesting use case is building document-processing workers.

A service could receive files from object storage, a NAS, or an upload endpoint:

S3 / NAS / Upload
       │
       ▼
   Worker ARM/x86
       │
     anydoc
       │
       ▼
    Markdown
       │
       ├── Elasticsearch
       ├── Vector DB
       ├── LLM
       └── Storage

Because conventional conversion does not require a GPU or an AI model, these workers can potentially run on relatively modest infrastructure.

They can also scale horizontally:

Queue
 │
 ├── worker-01 ── anydoc
 ├── worker-02 ── anydoc
 ├── worker-03 ── anydoc
 └── worker-04 ── anydoc

For large corporate document repositories, this architecture can be easier to operate than maintaining heavyweight conversion environments simply to extract text and structure.

AI agents that convert documents themselves

anydoc also includes an Agent Skill.

The installation documented by the project is:

npx skills add firecrawl/anydoc

Firecrawl describes integration with tools such as Claude Code, Codex, Cursor, and OpenCode.

The interesting part is not simply saving a manual conversion command.

An agent might encounter:

quarterly-report.xlsxCode language: CSS (css)

determine that it needs the contents, invoke anydoc, and continue working with:

quarterly-report.mdCode language: CSS (css)

without requiring the user to perform the conversion manually.

This is part of a broader change in agentic systems. AI agents increasingly need reliable system tools for interacting with formats that should not simply be dumped raw into a model context.

Local document conversion also has operational advantages

There are at least three reasons why infrastructure teams may prefer to perform this stage locally.

The first is privacy. Corporate documents may contain confidential information, and sending an entire file to an external service merely to convert it may be unnecessary.

The second is cost. If an organization processes millions of documents, conventional parsing inside its own infrastructure can avoid external processing charges for files that do not require AI or OCR.

The third is reproducibility.

A pipeline using a pinned version of the converter can behave consistently across development, CI, staging, and production.

That matters more than it might seem. Document conversion is often treated as a minor preprocessing step until a parser update changes headings, tables, or paragraph boundaries and consequently alters hundreds of thousands of chunks already stored in a vector database.

Versioning the document-processing layer alongside the rest of the application is therefore a sensible operational practice.

anydoc does not replace every document-processing tool

Its lightweight design also defines its limits.

If an application needs to understand an embedded chart, visually reconstruct a scanned invoice, extract a complex table from an image, or interpret formulas represented graphically, a conventional parser will not be enough.

OCR, computer vision, or specialized document models may still be required.

But many organizations face a simpler problem: millions of digital documents that already contain structured information and merely need to be converted into a machine-friendly representation.

Running vision models against every one of those files can add unnecessary cost and latency.

That is the space anydoc is trying to occupy: fast conventional parsing when the information is already available in the document, while leaving heavier OCR and visual-processing tools for the files that actually require them.

Frequently asked questions

What is anydoc?

anydoc is an open-source Firecrawl library written in Rust that converts Office, OpenDocument, EPUB, CSV, and PDF files into Markdown.

Can anydoc run without an Internet connection?

Document conversion can run locally. The project provides a CLI and bindings for Node.js, Python, and WebAssembly, so supported formats do not inherently require an external API.

Can anydoc be used to build a RAG system?

Yes. It can handle the extraction and normalization stage before chunking, embedding generation, and indexing.

Can it process scanned PDF documents?

OCR is not built in. A PDF consisting only of scanned images requires an additional OCR or visual document-processing stage.

Scroll to Top