MarkItDown: convert PDF, Word, Excel and images to Markdown for LLMs
TL;DR
MarkItDown turns PDFs, Office files, images, audio and HTML into Markdown that keeps headings and tables, a format LLMs read well and that saves tokens. With untrusted input, use the narrowest conversion function since it runs with the process's privileges.
Hand a Word, PowerPoint or Excel file to an LLM and you immediately hit problems: binary formats, tables, messy headings. Copy-paste loses structure; writing a parser for each file type takes effort. Microsoft's MarkItDown is a lightweight Python library that converts most common file types into Markdown, the format LLMs read best, keeping headings, lists, tables and links.
What does it support?
| Group | Formats |
|---|---|
| Office | PDF, Word, PowerPoint, Excel |
| Media | Images (EXIF metadata, OCR), audio (metadata, speech transcription) |
| Web and data | HTML, CSV, JSON, XML, YouTube URLs, EPub |
| Archives | ZIP (iterates over contents) |
Install and use
pip install 'markitdown[all]' # or just [pdf, docx, pptx]
markitdown q3-report.pdf > q3-report.md
markitdown slides.pptx -o slides.md
from markitdown import MarkItDown
md = MarkItDown()
result = md.convert("contract.docx")
print(result.text_content) # Markdown ready to put in a prompt
It requires Python 3.10 or later. You can install dependency groups individually to stay lean. MarkItDown also supports plugins, such as an OCR plugin that uses a vision model to extract text from images embedded in PDF, Word, PowerPoint and Excel files.
Why Markdown?
- LLMs saw a lot of Markdown in training, so they understand headings, tables and lists well.
- Markdown is more compact than HTML or XML, saving tokens.
- Preserved structure makes chunking for RAG along headings more natural.
Fitting it into a pipeline
- Convert files to Markdown with MarkItDown.
- Chunk by heading (
#,##). - Embed and index, or put small documents straight into the prompt.
- Keep the intermediate Markdown for debugging wrong answers.
Risks and caveats
- Runs with the current process's privileges: the README warns that MarkItDown accesses files and URLs with the process's privileges, like
open()orrequests.get(). With untrusted input, sanitise it and use the narrowest conversion function (e.g.convert_stream()); don't let users pass arbitrary paths or URLs. - Not for high-fidelity human-readable conversion: it's meant for machine analysis; complex layouts can be lost.
- Scanned PDFs: without a text layer you need OCR; quality depends on the image.
- Complex tables: merged cells and nested tables may be flattened incorrectly; test with real documents.
- Sensitive data: plugins using a remote vision model send images outside.
How to apply it
- Dev: Replace per-format parsing code with MarkItDown; write tests with a few hard sample files (merged tables, multi-column PDFs).
- Tech Lead: Run conversions in an isolated environment when processing user uploads.
- PM: A "chat with your documents" feature can be prototyped in a day with MarkItDown plus Claude.
Sources & references
- markitdown — Microsoft (GitHub)