MarkItDown is Microsoft’s Python utility for turning documents into Markdown. The README is precise about why that target format: it is “meant to be consumed by text analysis tools” — the output is intended for LLM and text-analysis pipelines, not for people.
That sentence deserves to be the first thing you read about it, because it continues: it “may not be the best option for high-fidelity document conversions for human consumption.” If you want a Word file to become a beautiful web page, this is the wrong tool. If you want a PDF to become something a model can read cheaply while keeping headings, lists, tables and links intact, it is the right one.
What it eats
The documented inputs are broad: PDF, PowerPoint, Word, Excel, images (EXIF metadata and OCR), audio (EXIF metadata and speech transcription), HTML, text-based formats including CSV, JSON and XML, ZIP archives (iterating over contents), YouTube URLs and EPub — the list closing with “… and more!”.
Requirement is “Python 3.10 through 3.14” — note the upper bound, which is unusual to state and worth checking against your environment.
Installing only what you need
The extras are the practical detail. [all] pulls everything:
pip install 'markitdown[all]'
But the groups are granular — [pptx], [docx], [xlsx], [xls], [pdf], [outlook], [az-doc-intel], [az-content-understanding], [audio-transcription], [youtube-transcription] — so a pipeline that only handles PDFs and Word files can stay lean:
pip install 'markitdown[pdf, docx, pptx]'
Usage is unceremonious, as a CLI or a library:
markitdown path-to-file.pdf -o document.md
cat path-to-file.pdf | markitdown
from markitdown import MarkItDown
md = MarkItDown(enable_plugins=False)
result = md.convert("test.xlsx")
print(result.markdown)
The security note to take seriously
For a tool whose job is ingesting files, the README’s warning is the part to internalise: “MarkItDown performs I/O with the privileges of the current process.”
It follows with the right advice — sanitise untrusted input, and use the narrowest conversion method available, for instance convert_local() when you only mean to read local files. If you are pointing this at user uploads, that is not a footnote; it is the design constraint for your pipeline. Run it with as little privilege as the job allows.
Optional backends, and what they cost
LLMs are optional. For image descriptions you “provide llm_client and llm_model”, which currently applies to pptx and image files; the markitdown-ocr plugin uses LLM vision to OCR images embedded in PDF, DOCX, PPTX and XLSX, and without an llm_client that OCR is simply skipped.
Two Azure backends improve extraction quality: Document Intelligence via -d -e "<endpoint>", and Content Understanding via --use-cu --cu-endpoint "<endpoint>", the latter adding YAML front matter with extracted fields and supporting audio and video. The README is clear that each call to either is a billable Azure API call — so these are a quality-for-money trade, not free upgrades.
Plugins are disabled by default (--use-plugins to enable, --list-plugins to see them), which is the correct default for a converter handling arbitrary files. There is a Dockerfile too.
Why it earns a place in the toolbox
Because document ingestion is the unglamorous blocker in most retrieval and analysis work, and this covers an unusually wide range of formats behind one interface with MIT licensing and granular dependencies. Keeping tables and headings rather than flattening everything to prose is what makes the output usable downstream.
Set expectations from the README’s own framing: a lossy but structure-preserving conversion aimed at machines. Install only the extras you need, run it with minimal privileges on anything you did not create yourself, and treat the Azure backends as a deliberate cost decision rather than a default.






