Blog

How to Turn PDF and Word Files into Text for AI: Microsoft’s MarkItDown

Markdown

In-depth review: How to turn PDF and Word files into text for AI: Microsoft’s MarkItDown.

Read full article

Key takeaways

MarkItDown is a free Microsoft utility that turns Word, Excel, presentations, and PDFs into structured text for AI. It parses Office files cleanly in a fraction of a second. It turns PDFs with complex layouts into a mess, and returns an empty file with a zero exit code for a scan. Below are a working installation command, measurements on documents containing Cyrillic text, and a rule for when to use another tool.

More instructions are available in the Ailoot documentation.

What is MarkItDown, and what is it for?

Key takeaways

MarkItDown is a Python utility from Microsoft that reads a file and returns its contents as structured text. Headings become headings, and tables become tables. It lives in an open GitHub repository under the MIT license, installs with one command, and does all its processing on your machine. It has one job: prepare a document so an AI can see not only the words but also the structure.

You send an AI a contract, a report, or an accounting export, and get an answer that has nothing to do with the document. The cause usually isn't the model. The file contains a format: Word is an archive with markup, Excel is a spreadsheet with links between cells, and PDF is a set of characters with coordinates on a page. The model works with text, and someone has to extract that text.

That's what MarkItDown does. The repository is at github.com/microsoft/markitdown, under the MIT license, so you can use it without restrictions. As of August 18, 2026, it has 174,412 stars and 12,756 forks; the latest release, 0.1.7, came out on July 29. The project is active, though its focus has shifted from development to maintenance: it has 481 open pull requests, compared with 183 merged over its entire history.

The developers describe its purpose this way:

MarkItDown is a lightweight Python utility for converting files of various formats into Markdown for use with large language models and related text-analysis pipelines.

— Microsoft, project description (translated), https://github.com/microsoft/markitdown

The next sentence in the description explains half of the complaints people make about the tool:

Although the output often looks quite decent and human-friendly, it is intended for consumption by text-analysis tools and may not be the best choice for high-fidelity conversion of documents meant to be read by people.

— Microsoft, project description (translated), https://github.com/microsoft/markitdown

The output is raw material for a model. It won't be a beautiful document, and the project says so plainly, right in the first section.

The description answers directly why it uses Markdown: leading models already “speak” this markup and include it in their responses without being asked, because they saw huge volumes of it during training. The markup is also compact: three hash marks for a heading instead of a dozen lines of metadata.

How is MarkItDown different from a regular converter?

Key takeaways

Converters such as pandoc translate one markup language into another and preserve the layout for people. pandoc does not accept PDF as input at all. MarkItDown solves the opposite problem: extract content from an Office file and arrange it so a model can understand it immediately without wasting tokens. Preserving visual layout isn't its goal, and that's the whole difference.

The difference is clear from one example. Take a folder with twenty PDFs and try to run them through pandoc. It won't work: pandoc can produce PDFs as output, but it can't read them as input. And this situation—“I have a stack of documents; give them to the model”—is the most common one.

The MarkItDown authors compare themselves with textract, a library that simply extracts text from anywhere. The difference is that MarkItDown tries to preserve structure: headings, lists, tables, and links.

FeaturepandocMarkItDown
Reads PDFsnoyes, with caveats
Reads Word, Excel, presentationspartiallyyes
Intended audience for outputpeoplemodels
Main valuelayout fidelitystructure and low character count
Installationstandalone programone Python command

The practical conclusion is simple. If you need to convert an article into layout for publication, use pandoc. If you need an AI to make sense of twenty contracts, use MarkItDown.

How do you install MarkItDown without getting the first release?

Key takeaways

With release 0.1.8, the command in the project description installs the latest version on Python 3.14 and 3.12; this has been rechecked in eight clean environments. A silent downgrade to 0.0.2, the second release in the project's history, still happens on Python 3.15, on Intel Macs running 3.14, and on Macs with older macOS versions running 3.13 and 3.14. In these cases the installer reports success. So use Python 3.12, list the formats you need by name, and check the version number immediately.

First, the right command; then, why it is the right one.

  1. Check the Python version

    Python 3.12 is the most reliable: the latest MarkItDown installs in every environment tested on it. The command python3 --version shows what you have. On Intel Macs or Macs running an older version of macOS, Python 3.13 and 3.14 can silently downgrade; Python 3.15 is not supported yet, as explained below.

  2. Install with the formats listed

    Run pip install 'markitdown[pdf,docx,xlsx,pptx]'. The quotation marks are required, or the shell will interpret the square brackets. On an Intel Mac, add the --prefer-binary flag after install.

  3. Check immediately that it installed

    Run markitdown --version. The response should be markitdown 0.1.8 or later. A lower number means the installation downgraded; this section explains why.

pip install 'markitdown[pdf,docx,xlsx,pptx]'
markitdown --version

The project description lists pip install 'markitdown[all]' as the main command—to install everything at once. On September 28, 2026, a week after 0.1.8 came out, four variants were run in clean environments on an Apple Silicon Mac with Python 3.14.6 and 3.12.12:

CommandInstalled on Python 3.14Installed on Python 3.12
pip install markitdown0.1.80.1.8
pip install 'markitdown[pdf,docx,xlsx,pptx]'0.1.80.1.8
pip install 'markitdown[all]'0.1.80.1.8
pip install 'markitdown[all]==0.1.8'0.1.80.1.8

All eight installations ended with “Successfully installed,” and markitdown --version returned 0.1.8 in every case. In August, when 0.1.7 was the latest release, the third command on Python 3.14 installed 0.0.2, released on March 8, 2025—the second release in the project's history. It now has eleven stable releases, from 0.0.1 to 0.1.8, and twenty-six including pre-releases.

The cause was the dependency chain. In 0.1.7, the [all] extra pulls in a YouTube subtitle library from a specific release series, and all releases in that series declare that they do not work on Python 3.14. The installer rejects them and, because no version is pinned, steps back through MarkItDown versions until it finds one that can be installed. It finds 0.0.2 and installs it, putting a release from a year and a half ago on your machine. In 0.1.8, the subtitle library requirement was raised to a series that works on 3.14, and the downgrade stopped at that point.

The mechanism is still there. If the installer cannot find one required component for your system, it silently steps back to 0.0.2 in the same way. In recent versions, that component is the onnxruntime engine used by the file-type detector. On Mac, it is built as follows: for Python 3.12, macOS 11 and later; for 3.13, macOS 13; for 3.14, Apple Silicon only with macOS 14 or later. If your Mac does not meet those requirements, even the bare command pip install markitdown installs 0.0.2. A test on an Intel Mac running Python 3.14 through Rosetta produced exactly this: “Successfully installed,” no warnings, and 0.0.2 inside.

Intel Macs have another complication. Since June 2026, the cryptography library pulled in for reading PDFs has been released without a prebuilt version for this processor, so the installer tries to build it from source. Add the --prefer-binary flag to the command, and it will use the previous version with a prebuilt package. In testing on Python 3.13 for Intel, that installed 0.1.8, and the PDF opened. The flag installs cryptography 48.0.1, which has three known vulnerabilities: in PKCS#7 decryption and certificate-chain verification. MarkItDown uses it only to decrypt encrypted PDFs, and document reading does not reach those parts.

With Python 3.15, the downgrade happens for two reasons. Version 0.1.8 declares support only from 3.10 through 3.14, and there is no engine for 3.15 yet. The installer's resolution for 3.15 confirms this: both the bare command and the command with formats install the same 0.0.2.

A downgrade warning looks like this, one line for each extra in the command:

WARNING: markitdown 0.0.2 does not provide the extra 'all'

The line gets lost among dozens of download lines, and it says nothing about the version being substituted. With a bare command without extras, there isn't even a warning. The final report is cheerful: “Successfully installed.”

Installing without extras is not a solution either. The bare package installs, but it cannot open PDFs:

PdfConverter recognized the input as a potential .pdf file, but the
dependencies needed to read .pdf files have not been installed. To resolve
this error, include the optional dependency [pdf] or [all] when installing
MarkItDown. For example:

* pip install 'markitdown[pdf]'
* pip install 'markitdown[all]'

The tool itself recommends [all], and with 0.1.8 that advice works again on Python 3.14 and 3.12. Still, it is better to list formats by name: [all] adds another fifteen or so packages and about 55 megabytes, including a pre-release Azure library and the very YouTube dependency chain that already broke installation once.

The installer handles the Azure pre-release itself. Usually pip skips pre-releases, but here the requirement explicitly names a pre-release, so it installs it. Four pip versions, from 23.2 to 26.2, were tested on Python 3.12; all select 0.1.8.

Attention

Immediately after installation, run markitdown --version. It takes five seconds, and it's the only way to know that you installed what you asked for. The success report means nothing here.

In August, reinstalling in another clean environment gave the same result: 0.0.2 and the word “Successfully.”

A few practical details are worth knowing in advance.

It's fairly large: a bare installation takes 143 megabytes; with four formats, 303. The heaviest component, at 81 megabytes, is the file-type detector, which is pulled in even by the basic installation. That doesn't matter for a laptop, but it does matter for a cloud function with a size limit.

Don't count on mirrors as a fallback. A tested mirror provided an index, and the MarkItDown files were present, but one required dependency was missing, so installation failed on both Python 3.14 and 3.12.

Installation is minor compared with the main issue. Much more often, an AI produces garbage because the wrong thing, or the wrong representation of it, went into its context window. The ability to decide what to give a model before a task is called context engineering, and document preparation is part of it.

How do you turn your first document into text?

Key takeaways

One command in the terminal: the program name and the file path. By default, the result prints right in the window, so you can save it straight to a file. There are three methods: output to the console, write with a flag, or pass the file as a stream. For embedding it in your own scripts, there is a three-line Python wrapper, which also accepts URLs.

The shortest option:

markitdown dogovor.docx

The text prints in the terminal. To save it to a file, there are two ways:

markitdown dogovor.docx -o dogovor.md
markitdown dogovor.docx > dogovor.md

The difference is negligible on Mac and Linux, but it matters on Windows: redirecting through > can crash the program when the output contains Cyrillic text.

You can pass a file as a stream; in that case, the extension hint is useful:

cat dogovor.docx | markitdown -x docx

Here are the main flags from the 0.1.8 help:

FlagWhat it does
-o, --outputwrite the result to a file instead of printing it to the window
-x, --extensionextension hint when the file is passed as a stream
-m, --mime-typecontent-type hint
-c, --charsetcharacter-encoding hint
-d, --use-docintelprocessing through Microsoft's paid cloud service
-v, --versionshow the version

The same help lists three more useful flags, each of which has been tested: --list-plugins shows installed plugins, -p enables them for a particular run, and --keep-data-uris keeps images embedded in the document in the output (they are cropped by default). The rest are settings for Microsoft's cloud services.

The Python wrapper takes three lines:

from markitdown import MarkItDown

md = MarkItDown()
print(md.convert("ostatki.xlsx").text_content)

The same call accepts a URL. A simple page returned clean text with 167 characters, including a heading and a link, without its menu and footer:

r = md.convert("https://example.com")

Which formats does MarkItDown understand, and what does that really mean?

Key takeaways

The project description lists a wide range: Office files, PDFs, images, audio, archives, YouTube links, and ebooks. Three items don't work the way they sound. The free version has no image text recognition at all. Speech is sent to an English-language engine. Files that could not be parsed disappear from archives without warning.

A summary table of what is claimed and what it means in practice.

FormatClaimedWhat actually happens
Word, Excel, presentationsyesworks cleanly; this is its strength
CSV, JSON, XML, HTMLyesworks, but CSV has a delimiter trap
PDFyesdepends on layout: one column is assembled, two columns fall apart
Images“metadata and recognition”no recognition, only metadata or a paid vision model
Audio“speech transcription”goes to Google's English-language engine
ZIP archives“walks through contents”anything it cannot parse disappears silently
YouTube linksyesonly full links of the form '<OFFICIAL_URL>'?...
EPUB ebooksyesworks

Three items in more detail.

Images. The description includes the word OCR, so people expect the program to read text from a photo. It does not. It reads metadata using a separate program, exiftool, and, if you connect a vision model with your own key, can send the image to it for a description.

Audio. Speech transcription is available, but the language is not passed along, and the engine expects English by default. It also calls Google's unofficial free endpoint, which is limited to about fifty requests a day per key.

Archives. The program unpacks ZIP files and walks through the files inside, concatenating the results. If it cannot parse a file, the error is caught and suppressed. The file simply won't appear in the result, and you won't know about it.

What happens with documents containing Cyrillic text?

Key takeaways

Three files containing Cyrillic text—a Word contract, an Excel inventory sheet, and a presentation—were run through the latest version. The Cyrillic text and the number survived intact in all three. Things break in three places: CSV files using semicolons, currency formatting in Excel cells, and Windows console output. All three have workarounds.

The files below were created specifically for testing; their data is made up.

The Excel inventory sheet came out just as cleanly, with the sheet name turned into a heading:

## Stock
| Item | In stock | Reserved | Available |
| --- | --- | --- | --- |
| Coffee beans, kg | 420 | 38 | 382 |
| Loose-leaf tea, kg | 180 | 52 | 128 |

The presentation became text, with slide numbers shown as annotations and slide titles turned into headings. The Cyrillic text is intact here, too. The blanket claim that “MarkItDown doesn't understand Cyrillic” is false.

Now for the three places where things do break.

CSV with semicolons. Two identical invoice exports were run for comparison. The one using commas produced a proper four-column table. With semicolons, the whole line goes into a single cell.

The entire line ended up in one cell. The encoding was recognized correctly, and there was no error; the -c flag doesn't help. The model will receive this table and won't understand which value is the amount and which is the status. Export the file again with an explicit comma delimiter and the correct encoding, keeping the original unchanged. Do not replace semicolons globally: separators inside quoted text and decimal commas can be part of a value. If re-export is unavailable, parse the original with its actual delimiter and write a new CSV with a CSV-aware writer that preserves quoting and cell values. Before analysis, compare column counts, row counts, and control totals with the source export.

Excel currency formatting. The currency symbol is stored in the cell's display settings and does not make it into the value itself. The project maintainers confirmed the cause. For a price list or an invoice, this matters: the model will see numbers without knowing which currency they represent.

Windows console. On files with non-Latin characters, the program can crash.

The error trace shows the cp1251 encoding, meaning the Windows console. The document itself parses correctly; printing the result in the terminal window is what fails. So there are two workarounds:

markitdown dogovor.docx -o dogovor.md
$env:PYTHONUTF8 = "1"; markitdown dogovor.docx > dogovor.md

The first bypasses the console entirely; the second makes Python write in UTF-8. People have submitted fixes for the issue in the tool itself at least six times: some proposals were closed without being merged, while the rest remain open. So you have to work around it.

A fourth symptom appears in PDFs: sequences such as (cid:1090) in place of letters. This means the file has a nonstandard font table and its characters could not be decoded. There is no point processing such a document with MarkItDown; you need another tool.

Why does a PDF come out as a mess?

Key takeaways

A PDF contains no structure, just characters with coordinates on the page. Single-column text is assembled reasonably well. Two columns turn into a mess: lines are joined across columns, words run together, and the layout turns into tables that were never in the document. The tool does not identify headings in PDFs at all—this is clear from both the source code and independent measurements.

For testing, a 2.16-megabyte, two-column scientific paper was processed. The exit code was zero; after 0.9 seconds, the output contained 88,000 characters, almost all garbage. Eighty-eight thousand characters give the impression that everything worked. That is, until you open the file:

|     | Hybrid |          | OCR-LLM     |     | Framework  |
| --- | ------ | -------- | ----------- | --- | ---------- |
...
Informationextractionfromcopy-heavydoc-
5202 tcO 11  ]LC.sc[  1v83101.0152:viXra

Three things went wrong at once. The two-column layout became tables that are not in the paper. Words ran together without spaces. The last line is a vertical sidebar on the page, extracted backwards.

Then came the funny part. The test paper turned out to be the very work that measured MarkItDown and compared it with other tools. The tool turned the paragraph reporting its own measurements into this:

cues. This name-matching error could be miti-  OCRpreprocessingoverhead(0.056s),whileDo-
gatedthroughpromptengineeringtoprovidemore  clingandMinerUadoptmorecomputationallyin-
explicit matching instructions or fine-tuning the  tensive strategies with OCR latencies of approxi-

The left and right columns are joined line by line. A model given this will read half a sentence from one paragraph and half from another.

The cause is technical and simple. Word explicitly stores “this is a heading” and “this is a table cell.” A PDF stores “this is a character” and “these are its coordinates on the page.” Reconstructing structure from coordinates is a separate, difficult task, and MarkItDown barely attempts it. The PDF parsing source code contains no heading detection: if a page isn't recognized as a form or table, the entire document goes through basic text extraction.

Users regularly report this in the project's repository, including for scientific papers and tables.

The tool does not find headings in PDFs, exactly as its source code shows.

The figure “MarkItDown achieves 82% accuracy” circulates online without any methodology. Tracing it to the original source leads nowhere: the chain of links ends at a page that won't load. It cannot be treated as a measurement.

What happens with a scanned contract?

Key takeaways

Nothing. The file is processed, the program reports success, and the output contains zero characters. No error, no warning. This was tested twice on a PDF made from an image, and separately on the image itself—the result was the same. The tool extracts text that is already stored as text in the file; the free version has no recognition capability.

This behavior is more dangerous than the others because it doesn't look like a failure.

For testing, a PDF was made from an image containing text—that is, exactly what you get when a contract is photographed or scanned. The run was repeated to rule out chance:

InputExit codeCharacters in outputError message
PDF from image, run 100none
PDF from image, run 200none
PNG image directly01 (line break)none

Zero characters and zero errors, twice in a row. A zero exit code means “everything went well,” and any script that checks success by exit code will count the document as processed. Then the empty output goes to the model, the model sees nothing, and starts making up an answer out of thin air.

Attention

If you process documents in batches, check the length of the output. The exit code won't tell you anything: an empty file with a zero exit code is what a scan looks like.

There are two workarounds, and both are paid. The first is the -d flag, which sends the document to Microsoft's cloud recognition service; the flag's help text explicitly says that a valid service endpoint is required. The second is a separate add-on package that sends pages to a vision model using your key, so you pay the model provider for each page. Since April 2026, an open discussion about the second method has reported that only the first page of a multipage scan is processed.

You can also run a recognition model on your own machine, but that's a separate project.

For a one-off document, it's easier to open it and copy the text manually. For a stream of scans, you need a tool with built-in recognition.

Can you just upload the file to an online converter?

Key takeaways

Technically, yes; there are many domains with this name. But none of them is affiliated with Microsoft. The claim “the file never leaves your browser” can be checked with one click, and isn't always true. Before uploading a contract or an export with people's names, see for yourself where the file goes.

“MarkItDown online” is one of the most common search suggestions, and there are sites offering it. Microsoft's original tool has no website at all; it is only available as a program you install yourself. Anything with a similar name that opens in a browser was made by someone else.

You can check such a service in a minute: open the developer tools on the network requests tab, upload any harmless file, and see whether it goes to a server. If it does, the claim about processing in the browser is false, however confidently it may be presented in the FAQ.

Attention

A contract, an invoice, or an export containing employees' names includes personal data. If you send such a file to a third-party website, you are the one who transmitted it. A local utility avoids that problem: the file does not leave your machine.

That's why MarkItDown is valued where documents cannot be sent outside the organization. In one discussion, someone described their situation: arbitrary programs were prohibited on their work laptop, but Python libraries were allowed, and the local utility turned out to be the only available option.

How much does MarkItDown actually save?

Key takeaways

The main benefit is that the model can understand the document at all. There is also a difference in size: comparing the weight of the markup inside Office files with the size of the extracted text shows a five- to sevenfold reduction. It also removes everything the model doesn't need to read: descriptions of fonts, margins, and cell colors.

An Office file is structured as an archive containing markup. If you unpack the three test files and compare the size of the part containing the content with the size of the output, you get this:

FileMarkup insideExtracted textTimes smaller
Word contract3,701 bytes711 bytes5.2
Excel spreadsheet1,561 bytes262 bytes6.0
Presentation2,203 bytes296 bytes7.4

The files are small; the proportions will differ for larger ones, and there is no single savings figure. When round numbers appear in comparison articles, ask about the methodology.

The developers themselves also talk about savings: the project description specifically says that Markdown conventions are very economical in terms of characters. That's true, but it shouldn't be the main selling point. The difference between “the model got three thousand characters instead of fifteen thousand” and “the model got a clear structure instead of a jumble” is of a different order. The first saves money; the second determines whether the answer will make sense.

If context usage is a concern for you, it is covered separately: Where tokens go in Claude and how many are included in each plan.

How do you connect MarkItDown to Claude through MCP?

Key takeaways

The project has a separate package that runs an MCP server with a single command: provide a file path, get text back. In September 2026, the package was finally updated to 0.0.1a7, but the build is still a pre-release and sends telemetry to Microsoft by default. The command below connects it through uv, pins the version, uses Python 3.12, and disables telemetry. There is no authentication, and according to its own documentation, the server can read any file available to the user who launched it.

MCP is a way to give an AI an external tool that it can use itself. For an overview of the mechanism and other servers, see the review of MCP servers for Claude Code.

The MarkItDown server exposes exactly one tool: convert a document to text. It accepts a local file path, a page URL, or data embedded directly in the request.

It connects to Claude Code with a single command, with the server version pinned. You need the uv package manager:

claude mcp add --scope user --env 'ORT_DISABLE_TELEMETRY=1' --env 'UV_PYTHON=3.12' --transport stdio markitdown -- uvx markitdown-mcp@0.0.1a7
claude mcp list

The response to the second command should show “Connected” for markitdown. The first launch downloads about seventy packages and takes up to a minute; after that, the server starts in one to one and a half seconds.

Here are the caveats, each checked manually.

Build 0.0.1a7 was released on September 14, 2026. Before that, the server had been stuck at 0.0.1a4 from May 2025 for over a year. The latest version number is still a pre-release.

It won't install on every system with a recent version of Python. The onnxruntime engine it depends on is available for Python 3.14 on Mac only for Apple Silicon running macOS 14 or later, so installation fails on Intel Macs and on macOS 13 or earlier with Python 3.14. On an Apple Silicon Mac, the server was run on Python 3.14, 3.13, and 3.12, and installed on all three. The command uses UV_PYTHON=3.12: prebuilt packages for 3.12 are available on Windows, Linux, and Apple Silicon Macs, and if you don't have that version of Python, uv will download it. There's a caveat for Intel Macs here, too: uv will build the cryptography library from source because there has been no prebuilt package for Intel since June 2026. Installation takes longer and may fail.

The version of MarkItDown installed inside depends on the version of uv. Starting with MarkItDown 0.1.6, its [all] extra requires a pre-release Azure library: uv 0.12 and later installs it and the latest MarkItDown 0.1.8, while older uv versions downgrade to 0.1.5. Check your uv version with uv --version.

Two things are sent outside the machine. The first is telemetry: on Mac and Linux, the onnxruntime engine inside the server sends it to Microsoft by default. The ORT_DISABLE_TELEMETRY=1 variable in the command disables it. In testing, the server connected to Microsoft's telemetry endpoints without it. With the variable set, there were no connections at all while files were processed from disk.

The second is audio. The server sends WAV, MP3, M4A, and MP4 files to Google's speech recognition service for transcription over ordinary HTTP, without encryption. It's better not to send recordings of conversations with clients through it.

A large document won't fit through it. An open discussion describes a server response of 51,000 tokens hitting a 25,000-token limit, and the tool does not split files into chunks.

And security. The package's own documentation says plainly:

The server does not support authentication and runs with the permissions of the user who launched it. The conversion tool can be used to read any file accessible to the server user, or any data on the network.

— Microsoft, description of the markitdown-mcp package (translated), https://github.com/microsoft/markitdown/tree/main/packages/markitdown-mcp

In other words, an agent with this tool can read anything you can read. That's acceptable for work on your own machine. You must not expose the server publicly or give it to an untrusted agent.

Attention

The project's documentation does not include a configuration specifically for Claude Code—it describes only Claude Desktop and launching through a container. If you find a ready-made config online described as “from the official documentation” for Claude Code, know that there is no such config in the repository.

For regular work, it is easier to invoke the program with a command and put the resulting text in the project. The file then sits beside the other materials, where the model can consult it on its own.

When is it more honest to use another tool?

Key takeaways

The rule is simple: if the structure is already recorded inside the file, use MarkItDown—it is the fastest and free. If the structure has to be reconstructed from an image of the page, use a tool with layout models. Docling handles tables and complex layouts, MinerU handles formulas and multiple columns, and paid cloud services help when there is no time to fiddle with it.

A task-based comparison; GitHub stars have nothing to do with it:

ToolStrengthWhat you pay in
MarkItDownOffice files, speed, freecannot handle complex PDFs or scans
Doclingtables and layouts through specialized modelstens of seconds per document
MinerUmultiple columns, formulas, dense tablesmore difficult to install
Markerhigh accuracy, formulas, illustrationsrequires a graphics card, and its license restricts revenue
unstructuredreturns the document structure in chunks with descriptionsoutput is harder to use
Cloud parsersno setupmoney and sending the document outside your machine

There is a detail about Marker that comparison articles omit. Since July 2026, the code itself has been under a permissive license, while the model weights are under a separate license with a threshold: use is free if your company did not exceed five million dollars in revenue and the same amount in funding raised in the previous year. A separate clause prohibits use by anyone building a competing product. This does not matter to most readers, but it is a reason for a growing business to read the license before adopting it.

That leads to a practical four-step workflow:

  1. Run everything through MarkItDown—it is free and instant.
  2. Open the result and check its size.
  3. If the text makes sense, the task is done; nothing else is needed.
  4. If the output is a mess or empty, run that specific file through a heavier tool.

That way, you pay the time and complexity cost only for documents that need it.

How do you work MarkItDown into your workflow?

Key takeaways

Anthropic itself states the rule in its skill descriptions: use this tool to read a document. Do not plan edits based on it. Here are three scenarios where it pays off on the first run: parsing a batch of similar documents, adding standing reference materials to an AI project once, and preparing an export from an accounting system for analysis.

Anthropic uses MarkItDown in its own ready-made skills for working with Office files, and those skills spell out the boundary you should adopt in full:

Quickly inspect a sheet: markitdown file.xlsx. Cell coordinates are not available, so do not plan edits based on this.

— Anthropic, description of the skill for working with tables (translated), https://github.com/anthropics/skills/blob/main/skills/xlsx/SKILL.md

Cell and page references are lost in the text, so you cannot use it to make changes to the source file. Here are three scenarios.

A batch of similar documents—acts, invoices, forms, applications. Put them in a folder and run them with one line:

for f in dokumenty/*.docx; do markitdown "$f" -o "text/$(basename "$f" .docx).md"; done

Then give the model the folder of text files and ask it to compile the relevant information into a table. This works with digital files; scans will fail, and you'll spot them immediately by their zero size.

Standing project materials—price lists, contract templates, policies, service descriptions. Convert them to text once and put them alongside the project. The model can then read them with every request, so you don't need to attach the files to the conversation each time. The article about uploading files to Claude explains how this differs from uploading a file to chat.

An export from an accounting system. An Excel export from accounting software or a bank account becomes a table in a third of a second, and the model can calculate from it without any intermediate fiddling. Check that a CSV was exported or parsed with its real delimiter, quoting, and encoding, and compare rows, columns, and control totals before giving it to the model. Do not normalize separators with search-and-replace. Also record the currency explicitly: a symbol stored only in an Excel cell’s formatting will not survive extraction.

Processing large PDFs in the terminal is not on this list. That is a separate issue involving context usage, covered in the article about PDFs in Claude Code without losing tokens. If you're just setting up your workspace, start with installing Claude Code.

To get started right now, run pip install 'markitdown[pdf,docx,xlsx,pptx]', process the first Word contract you find, and check the size of the result. In half a minute, you'll know whether it works with your files.

Frequently asked questions

Is MarkItDown free?

Yes. It has an MIT license, with no restrictions on commercial use. You only pay for two optional methods: cloud recognition by Microsoft through the -d flag, and image descriptions by a vision model using your own key. Everything else runs on your machine for free.

Is data sent to any server?

For ordinary conversion of Office files and PDFs, no—everything is processed locally. There are three exceptions: audio transcription goes through Google's service, the -d flag sends the document to Microsoft's cloud, and image descriptions go to a model using your key. None of these methods is enabled automatically.

Why can't I find the markitdown command after installation?

Most often, the program was installed in an environment that isn't on your search path. Check the full path to the file inside the environment. Another common case is that you installed it for one version of Python but are calling it with another. One more trap: on Python versions below 3.10, an empty package is installed without an installation error.

What should I do if I see (cid:1090) and similar strings instead of letters?

This is an undecoded font table inside the PDF. Settings won't fix it; you need to run the file through another tool, such as Docling or MinerU. For a one-off document, copying the text manually from a viewer is faster.

Can I process a whole folder of files at once?

There is no separate folder mode, but you can do it with a one-line terminal loop: for f in papka/*.docx; do markitdown "$f" -o "$f.md"; done. Another option is to put everything in a ZIP and provide the archive: the program will process its contents, but files it cannot parse will disappear without warning.

How is the output different from copying the text by hand?

It preserves structure. Copying gives you flat text where a heading is indistinguishable from a paragraph and a table falls apart. MarkItDown preserves headings, lists, and tables, so the model can tell what is what. The difference is small for one short document, but decisive for twenty.

Can MarkItDown open password-protected documents?

No. A password-protected file won't open, and you can't pass the password to the program. You have to remove the protection beforehand in the application that applied it.

When you're ready, meet Ailoot.

More details

Questions about How to Turn PDF and Word Files into Text for AI: Microsoft’s MarkItDown

Can I fix a semicolon CSV by replacing every semicolon with a comma?

No. Quoted text and decimal formats can contain those characters. Re-export with the intended delimiter, or use a CSV parser and writer with explicit delimiter, encoding, and quoting; verify columns, rows, and control totals against the original.

Does a zero exit code mean a PDF was converted usefully?

No. The article’s scan example returned empty output without an error, and a complex PDF produced unreadable text. Open the result, check its length and structure, and use a layout or recognition tool when the extracted text is empty or garbled.

All articles