>
Artificial Intelligence

microsoft/markitdown – Python tool for converting files and office documents to Markdown.

microsoft/markitdown: the Python tool that converts files to Markdown

I have been using markitdown (a small Python utility from Microsoft that converts a wide range of file formats including PDFs, Word documents, PowerPoint slides, images, and audio into clean Markdown text) since the first release in 2024. The 2026 version is the one I have been waiting for. It is faster, the Markdown output is cleaner, and the long-promised table extraction finally works on the kind of PDFs I actually receive.

This is not a review of the tool. The README is the review. This is the part I wish someone had written for me: how to use it in a pipeline, where it breaks, and the one architectural decision the maintainers made that is going to age well.

What it does, in one paragraph

You point markitdown at a file. It returns Markdown. The supported formats are the ones that come up in day-to-day work: PDF, Word (docx), PowerPoint (pptx), Excel (xlsx), images (with OCR, which stands for optical character recognition, the technique of reading text out of a picture), audio (with speech-to-text), HTML, CSV, JSON, XML, and a handful of others. The tool is a Python library and a CLI (command-line interface, a program you run from a terminal by typing its name and arguments).

The CLI is the part I use most. The pattern is markitdown input.pdf > output.md. The output is clean Markdown that pastes cleanly into a wiki, a chat window, or a static site generator. The library is the part I use when I am building a pipeline that processes a folder of files.

The pipeline I built

I have a folder of about 200 PDFs that I reference regularly: vendor contracts, technical specifications, regulatory filings. I used to open each one, find the section I needed, and copy the relevant text into my notes. The process took about 20 minutes per file. I am not going to say what the cumulative time was.

Here is the pipeline I built with markitdown.

from markitdown import MarkItDown
from pathlib import Path

md = MarkItDown()
src = Path("contracts/")
dst = Path("contracts_md/")
dst.mkdir(exist_ok=True)

for pdf in src.glob("*.pdf"):
    result = md.convert(str(pdf))
    out = dst / (pdf.stem + ".md")
    out.write_text(result.text_content)

The pipeline converts every PDF in the folder to a Markdown file with the same base name. The conversion is fast: about 2 seconds per file on my machine. The output is clean Markdown with headings, lists, and tables preserved. The 200 PDFs take about 7 minutes to convert.

The pipeline is not finished. The Markdown is a starting point, not a destination. I then run a second pipeline that extracts the specific fields I need (contract value, term length, renewal date) from the Markdown using a local LLM. The LLM extraction is the part I am still tuning. The Markdown conversion is the part I trust.

The one architectural decision that ages well

The maintainers of markitdown made a decision early that I want to call out, because it is the kind of decision that determines whether a tool is still useful in three years.

That decision: markitdown is a thin wrapper around format-specific converters. It does not contain the conversion logic itself. The conversion logic is delegated to existing libraries: pdfminer for PDFs, python-docx for Word, python-pptx for PowerPoint, and so on.

This matters because the underlying conversion libraries are maintained by people who specialize in those formats. pdfminer is maintained by people who understand the PDF spec (the format’s official technical document defining how files are structured) better than the markitdown team ever will. When the PDF spec changes, pdfminer gets updated. When markitdown upgrades its dependency on pdfminer, the user gets the fix.

A tool that contains its own conversion logic has to maintain that logic forever. A tool that delegates has to maintain the delegation. Delegation is the right call for a tool that supports 10+ input formats.

Where it breaks

I want to be specific about the failure modes, because every tool has them.

  • Scanned PDFs without OCR. markitdown will not extract text from a scanned PDF unless you have OCR installed. The OCR integration uses tesseract, which is available on every Linux distribution and is installable on macOS via brew. The first time I ran markitdown on a scanned contract, I got an empty Markdown file. The fix was installing tesseract. The error message could have been clearer.
  • PDFs with complex table layouts. The table extraction in the 2026 release is much better than it was in 2024, but it still misaligns columns in tables that span multiple pages. For a regulatory filing I process every quarter, the table layout is consistent enough that I have written a small post-processing step. For a one-off PDF with a weird table layout, I do the conversion by hand.
  • PowerPoint files with embedded media. markitdown extracts the text from slides. It does not extract the speaker notes. It does not describe the embedded images. For a slide deck that is mostly text, the conversion is good. For a slide deck that is mostly images, the conversion is thin.
  • Encrypted PDFs. The tool cannot read PDFs that are encrypted with a password unless you supply the password. The CLI flag is -p <password>. The library API has a password parameter. If you do not supply the password, the tool raises an exception with a clear message. The behavior is correct, but the error path is a real one for any pipeline that processes a folder of files.

None of these are deal-breakers. All of them are real. The tool is honest about its limitations in the README. I appreciate that.

What I would tell past me

If I could send a message back to the version of me that was opening PDFs by hand, I would say three things.

  • Install markitdown and tesseract together. The OCR dependency is the one that catches you on a scanned PDF. Installing both from the start saves the “why is this output empty” debugging session.
  • Use the library API, not the CLI, for anything that processes more than 10 files. The CLI is great for one-offs. The library API is the right tool for pipelines. The CLI is just a thin wrapper over the library.
  • Do not trust the table extraction on the first run. Always spot-check the Markdown output of a new file format against the source. The spot-check is fast, and the failure modes are the kind of thing you want to know about before you build a pipeline on top of the output.

Trade-offs

The markitdown output is Markdown, which is great for text-based workflows and bad for preserving the visual layout of the source document. A PDF that has a complex two-column layout with sidebars will not look right when converted to Markdown. The Markdown is a representation of the text content, not a representation of the page.

Dependency on a dozen underlying format libraries means there are a lot of transitive dependencies (libraries that your tool’s libraries in turn depend on, a chain that can be several layers deep) in the install. The pip install markitdown[all] command pulls in about 30 packages. This is a real cost for a tool that you might want to deploy in a constrained environment. The maintainers offer a smaller install for the most common formats. The smaller install does not include the less common formats.

Coming from Microsoft, the tool is backed by a large organization and a team of maintainers. It also means the tool’s roadmap (the maintainers’ published plan for what they are going to build next) is influenced by Microsoft’s priorities, not by the community’s. The trade is reliability in exchange for voice. For a tool I am going to depend on for years, the trade is one I am willing to make.

Bottom line

markitdown is the tool I use to convert files to Markdown, and the 2026 release is the one I have been waiting for. The thin-wrapper architecture is the right design. The failure modes are well-documented. The pipeline pattern is straightforward. If you are processing more than 10 documents a month, the tool will pay for itself in the first afternoon.

Filed under: #ai #devops #tools

Leave a comment