Getting Started - Your First Document to Markdown
Tutorial
Using anydoc for the first time, most people worry about "will it even install and convert?" In practice, what shapes your experience is getting three things straight: what anydoc can convert, where it runs best, and what might be lost in the output. Sort those out and your first conversion takes under five minutes.
Set expectations first
anydoc is a conversion library, not a document editor. Its job: turn 14 office formats — Word, PPT, Excel, PDF, and more — into clean, well-structured GitHub-Flavored Markdown. Three things to accept up front:
- Conversion is local: no network, no uploads, and very fast (median under 5ms)
- Output is plain-text Markdown: visual fidelity isn't pixel-perfect (complex layouts get trade-offs)
- Headers, footers, and page numbers are stripped by design — intentional, to give LLMs clean input
Things to know before you start
- Supported formats: 14 (Word / PowerPoint / Excel / OpenDocument / RTF / EPUB / CSV / PDF)
- License: MIT — free, including commercial use
- Native bindings: Rust / Node.js / Python / browser (WebAssembly) / CLI / Agent Skill
- Known limit: scanned (image-only) PDFs are unsupported and need OCR
- Official repo: github.com/firecrawl/anydoc
First conversion: the CLI in three commands
The CLI is the fastest on-ramp — no project setup required, one command does it:
# 1. Print to the terminal
npx @firecrawl/anydoc report.docx
# 2. Write to a file
npx @firecrawl/anydoc slides.pptx -o slides.md
# 3. Read from stdin (pipeline-friendly)
npx @firecrawl/anydoc - --format csv < data.csvThe first run takes a moment
npx downloads the CLI package on first use; after that it's instant. To install globally: npm i -g @firecrawl/anydoc.
Open the output and eyeball it: are headings becoming # levels? Are tables clean? Are images rendered as ? That's anydoc's signature.
Common flags at a glance
| Usage | What it does |
|---|---|
anydoc <file> | Convert a file, print Markdown to stdout |
anydoc <file> -o out.md | Write to a specific file |
anydoc - --format csv < data.csv | Read from stdin, declare the format explicitly with --format |
anydoc <file> --json | Output JSON (the document model view, including embedded-asset metadata) |
First line of code in every language
Beyond the CLI, every binding starts with a single line:
// Node.js
import { toMarkdown } from '@firecrawl/anydoc'
const markdown = await toMarkdown('report.docx')# Python
import anydoc
markdown = anydoc.to_markdown("report.docx")// Rust
let markdown = anydoc::to_markdown("report.docx")?;// Browser (WASM)
import init, { toMarkdownBytes } from '@firecrawl/anydoc-wasm'
await init()
const markdown = toMarkdownBytes(bytes)Want to go deeper on one binding? Check the API quick reference, or jump to the full page for your language (Node.js / Python / Rust / WebAssembly / Agent Skill).
Three common misconceptions
Misconception 1: the extension decides the format
anydoc detects the format from file content, so mislabeled files still convert. But the bytes themselves must be a real document — renaming a text file to .docx won't work; you'll get a Malformed error.
Misconception 2: output should reproduce the layout
It can't, and it doesn't need to. anydoc's goal is information completeness (headings, lists, tables, footnotes all there), not visual identity. For pixel-perfect output use a PDF converter; for clean LLM input use anydoc.
Misconception 3: images get lost
Images aren't lost — they appear as alt text in Markdown, while the raw bytes stay on the document model (reachable via toDocument, tagged with media types). Converting straight to a string renders them as descriptive text.
Getting-started checklist
- Run your first conversion with
npx @firecrawl/anydoc - Combine stdin input with
-ooutput files for most pipeline scenarios - Page-level noise is stripped by default; that's the design
- Spot-check the output: headings, tables, code blocks
- A scanned PDF returning Unsupported is expected behavior, not a bug
If you remember one sentence: anydoc is the entry point of a "document → Markdown" pipeline — get the CLI running first, then dive into whichever binding you need. Next up: the API quick reference, or straight to your language's page.