# Firecrawl AnyDoc: Local Documents to Markdown Guide

> Use AnyDoc from Node.js, Python, Rust, WebAssembly, or an Agent Skill, while handling OCR gaps, benchmark claims, errors, and untrusted files.

- **Published**: 2026-08-07
- **Category**: DevOps
- **URL**: https://agentpedia.codes/blog/firecrawl-anydoc-document-markdown-guide

---

**Firecrawl AnyDoc** is an open-source Rust document converter with Node.js, Python, WebAssembly, Rust, CLI, and Agent Skill entry points. It turns Word, PowerPoint, Excel, OpenDocument, RTF, EPUB, CSV, and text-based PDF files into GitHub-Flavored Markdown through a shared document model.

The useful idea is consistency: one parser family feeds one serializer, so headings, tables, lists, links, footnotes, and escaping do not change merely because an upload arrived as `.docx` instead of `.odt`. The harder production problem remains: deciding when local parsing is trustworthy enough and when a file needs OCR, quarantine, or manual review.

> **Note callout**

As of August 7, 2026, the project is MIT-licensed and publishes packages for Rust, Node.js, Python, and WebAssembly. The repository also includes an Agent Skill. Package versions and supported platforms can change quickly; pin a tested version in production.

**Best fit:**

- Mixed office-document ingestion that needs one Markdown shape.
- Local or private conversion without an API key.
- Agent workflows that encounter legacy and modern Office files.
- A fast first stage before selective OCR.
- Pipelines willing to validate output against their own corpus.

## What AnyDoc is

AnyDoc parses supported formats into a common `Document` representation and serializes that model to Markdown. Embedded asset bytes remain available through the model; Markdown output uses alt text for embedded images because Markdown cannot contain arbitrary binary data.

PDF takes a related path. AnyDoc uses Firecrawl's `pdf-inspector` for text-based PDFs. Scanned or image-only pages do not become accurate text locally without an OCR or vision stage.

> introducing anydoc -- now your agents get 100x faster local parsing for pdf, docx, pptx & 10 more formats: sub-5ms md conversion, 500 docx files in 1.7s, top quality across all 13 formats, rust-based, open source, already powering @firecrawl /parse.
>
> -- [@nickscamara_, August 4, 2026](https://x.com/nickscamara_/status/2084669934194266370)

The launch post and repository changed quickly. The current README lists PDF and additional extension variants beyond the "13 formats" phrasing in the first announcement. Use the package documentation for current support and record the exact version you deploy.

## Supported formats

| Family | Listed extensions | Important note |
| --- | --- | --- |
| Word | `.doc`, `.docx`, `.docm` | Legacy OLE and OOXML variants |
| PowerPoint | `.ppt`, `.pps`, `.pot`, `.pptx`, `.pptm`, `.ppsx`, `.ppsm` | Speaker notes and structure may matter more than slide appearance |
| Excel | `.xls`, `.xlsx`, `.xlsm`, `.xlsb` | Validate merged cells, formulas, and table semantics |
| OpenDocument | `.odt`, `.ods`, `.odp` | Uses the same normalized output model |
| Rich Text | `.rtf` | Encoding and malformed-input cases deserve fixtures |
| EPUB | `.epub` | Check chapter order and internal links |
| CSV | `.csv` | Has no reliable content signature; supply a filename or explicit format |
| PDF | `.pdf` | Local text extraction; image-only pages need OCR |

Content-based detection looks for PDF headers, RTF groups, OLE stream names, and ZIP package metadata. CSV cannot be identified reliably from bytes alone, so its extension or explicit format is required.

## Quick start

### CLI

```bash
npx @firecrawl/anydoc report.docx > report.md
npx @firecrawl/anydoc slides.pptx -o slides.md
npx @firecrawl/anydoc - --format csv < export.csv > export.md
```

Expected output: each command writes GitHub-Flavored Markdown to stdout or the selected file. `npx` downloads the platform package on first use.

### Node.js

```bash
npm install @firecrawl/anydoc
```

```javascript
import { toDocument, toMarkdown, toMarkdownBytes } from '@firecrawl/anydoc';

const markdown = await toMarkdown('report.docx');
const detected = await toMarkdownBytes(uploadBytes);
const csv = await toMarkdownBytes(csvBytes, 'csv');
const document = await toDocument(uploadBytes);

console.log(markdown.slice(0, 120));
console.log(document.assets.length);
```

Expected output: Markdown text is returned without a network request; `document.assets` exposes embedded asset metadata and bytes for separate handling.

The Node binding uses the libuv thread pool so conversion does not run on the JavaScript event loop. That does not make concurrency unlimited--set a queue and measure memory under your real file sizes.

### Python

```bash
pip install firecrawl-anydoc
```

```python
import anydoc

markdown = anydoc.to_markdown("report.docx")
from_bytes = anydoc.to_markdown_bytes(data)
from_csv = anydoc.to_markdown_bytes(csv_data, "csv")
document = anydoc.to_document(data)
```

Expected output: strings contain Markdown; the document object preserves structured blocks and embedded assets. The Python binding releases the GIL during conversion, according to the project documentation.

### Rust and WebAssembly

```rust
let markdown = anydoc::to_markdown("report.docx")?;
let document = anydoc::to_document(&bytes, None)?;
```

Browser applications can use `@firecrawl/anydoc-wasm`. Firecrawl's public demo says conversion stays in the browser. Confirm this in network inspection if privacy is a requirement, and remember that your own application code can still upload a file even when the library itself does not.

### Agent Skill

```bash
npx skills add firecrawl/anydoc
```

Expected output: a compatible agent installs the repository's document-conversion skill and can invoke the AnyDoc CLI when it encounters supported files. Review the skill instructions and package source before granting an agent access to untrusted uploads.

## Design a production pipeline

Do not treat "Markdown returned" as "document understood." A production pipeline records provenance and uncertainty.

1. **Quarantine the original.** Store it in a non-executable area with a content hash, source, upload time, declared type, and detected type.
2. **Apply limits first.** Reject excessive size, archive expansion, nesting, page count, and processing time before conversion.
3. **Detect by content.** Compare AnyDoc's result with the extension and MIME type. Flag disagreement.
4. **Convert locally.** Capture package version, elapsed time, warnings, error variant, and output hash.
5. **Route OCR selectively.** Send scanned PDF pages or image-heavy documents to a reviewed OCR/vision service, not every file by default.
6. **Normalize assets.** Validate image media types, dimensions, filenames, and extraction paths before storing them.
7. **Run quality checks.** Compare heading count, table count, visible text coverage, sheet or slide count, and critical fields with source expectations.
8. **Chunk after conversion.** Preserve page, sheet, slide, heading, and table boundaries in retrieval metadata.
9. **Keep citations.** Every chunk should point back to the original file and a stable location inside it.
10. **Sample manually.** Review failures and a percentage of successes per format and source system.

A useful output envelope is:

```json
{
  "sourceHash": "sha256:<hash>",
  "detectedFormat": "docx",
  "converter": "firecrawl-anydoc",
  "converterVersion": "<pinned-version>",
  "status": "converted",
  "needsOcr": false,
  "markdownPath": "outputs/<hash>.md",
  "warnings": []
}
```

Expected output: downstream indexing receives Markdown plus enough provenance to reproduce or invalidate it when the converter changes.

### Handle failures deliberately

The project exposes meaningful failure categories: unsupported input, malformed structure, encryption, resource limits, missing required package parts, and I/O errors. In Node and Wasm, the conversion error includes a code. Python provides specific exception subclasses. Rust returns `ConvertError` variants.

Do not flatten these to one generic retry. Encrypted files need an authorized password workflow; image-only PDFs need OCR; resource-limit failures need review, not larger limits by default; malformed files may need a safer alternative parser.

## Interpret the benchmarks

The current repository reports a vendor-run comparison over 100 real-world documents spanning 14 formats, with 94 documents receiving quality judgments. It lists a 4.4 ms median for AnyDoc, 14-of-14 format coverage in that benchmark, and an aggregate score of 81.

The methodology includes useful controls: quality is judged blind against rendered source pages, pairwise results are evaluated with output order swapped, and per-format results are reported. Important limits remain:

- Firecrawl designed and ran the benchmark.
- The corpus is not redistributable.
- An LLM judge--reported as Claude Sonnet 5--scores completeness, structure, formatting, and cleanliness.
- Aggregate scores cover different format sets for different tools.
- Speed excludes process spawn for AnyDoc and Python libraries but includes it for CLI alternatives.
- Hardware and warm-run choices affect latency.
- The launch blog and live README show changing figures as the project evolves.

Treat the table as a hypothesis generator. Re-run on your own contracts, spreadsheets, decks, malformed files, languages, and PDFs. Score the fields and structure your application actually needs.

## Untrusted-file safety

Local parsing keeps data off a hosted API, but parsing complex binary formats is still attack surface.

- Run conversion in a container, sandbox, or restricted worker process.
- Disable network access unless the workflow explicitly needs external linked assets.
- Use read-only input mounts and a fresh output directory.
- Set wall-clock, CPU, memory, output-size, node-count, and decompression limits.
- Keep the parser and its Rust dependencies patched.
- Fuzz and mutation-test formats important to your workload.
- Never execute macros, embedded binaries, formulas, or scripts from uploaded documents.
- Sanitize extracted filenames and block path traversal.
- Scan extracted assets separately.
- Escape or isolate Markdown before rendering it as HTML.
- Treat document text as untrusted instructions when an agent or model consumes it.

Resource-limit errors are a safety feature. Do not automatically raise them for a single hostile or pathological file.

## Limits and alternatives

AnyDoc is a good fit when deterministic local extraction is enough. Choose a different or additional path when you need:

- OCR for scanned pages or photographs;
- visual layout reconstruction faithful to source pages;
- handwriting recognition;
- chart interpretation;
- pixel-level slide or PDF comparison;
- managed scaling and support rather than a library;
- independent benchmark evidence for a regulated procurement decision.

Firecrawl's hosted Parse endpoint adds OCR for pages the local parser cannot read. Other tools may be stronger on one format: for example, a DOCX-specific converter can be appropriate when completeness for Word documents matters more than broad format coverage. Benchmark by format, not by one aggregate rank.

## Verdict

AnyDoc reduces a real integration burden: mixed office formats can enter one local API and leave through one Markdown serializer. Its language bindings and Agent Skill make it easy to place at the front of an agent or retrieval pipeline.

Adopt it as a **first-stage parser**, not as an oracle. Pin the version, sandbox untrusted files, preserve provenance, test quality per format, and route scanned or visually complex content to OCR or review. That design captures the speed and privacy benefit without hiding the cases deterministic parsing cannot solve.

## FAQ

## FAQ

### Does AnyDoc send files to Firecrawl?

The open-source CLI and language bindings run locally. The browser demo uses WebAssembly locally. Firecrawl's hosted Parse API is a separate option for teams that want managed conversion and OCR.

### Can AnyDoc OCR scanned PDFs?

No. Local PDF handling uses pdf-inspector for text-based PDFs. Image-only or scanned pages require an OCR or vision fallback, such as Firecrawl Parse or another OCR pipeline.

### Which formats does AnyDoc support?

The current project lists Word, PowerPoint, Excel, OpenDocument, RTF, EPUB, CSV, and PDF variants, including legacy binary Office formats and modern OOXML files.

### Can an AI coding agent install AnyDoc as a skill?

Yes. The repository publishes an Agent Skill installable with npx skills add firecrawl/anydoc for compatible agents.

### Are AnyDoc's benchmark results independent?

No. Firecrawl publishes the harness and methodology, but the corpus is not redistributable and the quality evaluation is vendor-run with an LLM judge. Treat the figures as useful claims to reproduce on your own document set.


## Sources and links

- [Firecrawl AnyDoc repository and benchmark methodology](https://github.com/firecrawl/anydoc)
- [Firecrawl launch article](https://firecrawl.dev/blog/anydoc-and-pdf-inspector)
- [AnyDoc Rust crate](https://crates.io/crates/anydoc)
- [firecrawl-anydoc Python package](https://pypi.org/project/firecrawl-anydoc/)
- [Nicolas Camara launch post](https://x.com/nickscamara_/status/2084669934194266370)


---

- [All articles](https://agentpedia.codes/blog)