MarkItDown
Convert source material into Markdown optimized for language-model and text-analysis workflows. Preserve useful structure such as headings, lists, tables, links, and metadata; do not promise page-faithful visual reproduction.
Choose a workflow
- Convert one local file or supported URL: use the
markitdownCLI. - Convert several local files reproducibly: use
scripts/convert.py. - Integrate conversion into an application or pass streams: use the Python API.
- Read standalone images or images embedded in PPTX, DOCX, PDF, or XLSX: run the bundled script with an OpenAI-compatible vision model.
- Reject audio and video inputs; this Skill does not transcribe them.
Install safely
Require Python 3.10 or newer. Prefer an isolated environment:
python3 -m venv .venv
source .venv/bin/activate
python -m pip install 'markitdown[pdf,docx,pptx,xlsx,xls,outlook]' markitdown-ocr openai
Install only required extras when dependency size matters, for example:
python -m pip install 'markitdown[pdf,docx,pptx,xlsx]'
Do not install markitdown[all] for this Skill because it includes audio-transcription dependencies. Install only the document extras required by the task.
Do not alter a user's project environment without permission. Reuse an existing compatible environment when present; otherwise explain or create an isolated one within the task scope.
Convert content
For one input:
markitdown report.pdf -o report.md
markitdown https://example.com/page -o page.md
cat report.pdf | markitdown > report.md
For multiple local inputs, run:
python scripts/convert.py file.pdf slides.pptx notes.docx --output-dir markdown
python scripts/convert.py source-folder --output-dir markdown
The script recursively converts directories and preserves their relative structure. It preserves each source extension in the output name (file.pdf.md) to avoid collisions. Add --overwrite only when replacing existing outputs is intended.
Read images inside documents with a vision model
Use a service that exposes an OpenAI-compatible chat-completions API. This can be a local Ollama, LM Studio, or vLLM server, or another authorized URL. The model must support image input.
For Ollama, start the service and make sure a vision model is available, then run:
python scripts/convert.py diagram.png \
--vision-model <vision-model> \
--output-dir markdown
Use the same option for PPTX, DOCX, PDF, and XLSX. The OCR converter extracts embedded images, asks the configured model to read visible text and important visual information, and inserts the result into the document Markdown:
python scripts/convert.py presentation.pptx \
--vision-model <vision-model> \
--output-dir markdown
The default endpoint is the local Ollama URL http://127.0.0.1:11434/v1. Configure any other http:// or https:// OpenAI-compatible endpoint and its API key through dedicated environment variables:
export MARKITDOWN_LLM_BASE_URL=https://llm.example.com/v1
export MARKITDOWN_LLM_API_KEY=<api-key>
python scripts/convert.py presentation.pptx \
--vision-model <vision-model> \
--output-dir markdown
MARKITDOWN_LLM_API_KEY is optional for servers that do not authenticate; the script uses a non-secret placeholder when it is unset.
The CLI option overrides MARKITDOWN_LLM_BASE_URL when a one-off endpoint is needed:
python scripts/convert.py photos \
--vision-model <vision-model> \
--llm-base-url http://localhost:1234/v1 \
--image-prompt "Describe the image and transcribe visible text." \
--output-dir markdown
The script accepts valid http:// and https:// endpoints and never prints the API key. A remote endpoint receives standalone or document-embedded image bytes, so confirm authorization and data-handling requirements before using one. PPTX uses MarkItDown's built-in image-description path; DOCX, PDF, and XLSX explicitly register only their OCR converters rather than loading arbitrary plugins. Without --vision-model, JPG/PNG conversion is limited to locally extractable metadata, and document output omits model-generated image text.
For application code:
from markitdown import MarkItDown
converter = MarkItDown(enable_plugins=False)
result = converter.convert("report.xlsx")
markdown = result.markdown
result.text_content remains a soft-deprecated alias for result.markdown.
Choose the narrowest API that fits:
| Method | Use for |
|---|---|
convert(source) |
Trusted path, URL, or stream when permissive dispatch is useful |
convert_local(path) |
Local files only; safest default for on-disk content |
convert_uri(uri) / convert_url(url) |
Remote content, including supported YouTube URLs |
convert_stream(fileobj) |
An already-open binary stream; provide StreamInfo when the type is ambiguous |
convert_response(response) |
A requests.Response fetched under caller-controlled network policy |
When bytes have no useful filename, pass a hint:
from markitdown import MarkItDown, StreamInfo
with open("mystery.bin", "rb") as stream:
result = MarkItDown().convert_stream(
stream,
stream_info=StreamInfo(extension=".pdf", mimetype="application/pdf"),
)
Handle failures
Catch MarkItDownException when conversion errors need programmatic handling. Its subclasses include MissingDependencyException, UnsupportedFormatException, and FileConversionException. A recognized format with a missing parser can surface as a FileConversionException wrapping the dependency error, so inspect the full message and conversion attempts instead of catching only MissingDependencyException.
Install the exact extra named in a missing-dependency message and retry. If installation is unavailable, fall back to a dedicated format skill rather than abandoning the extraction task.
Verify the result
After conversion:
- Confirm the output exists, is non-empty, and is valid UTF-8 Markdown.
- Inspect headings, tables, links, and representative sections against the source.
- Report unsupported or weakly extracted content instead of silently claiming completeness.
- For standalone and embedded images, confirm the vision model returned useful visible text and visual descriptions.
- Keep the original source unless the user explicitly authorizes deletion.
Security boundaries
MarkItDown performs file and network I/O with the current process privileges. Treat source paths, URLs, archives, plugins, and generated output as untrusted when their provenance is unknown. Avoid broad filesystem privileges, do not enable plugins implicitly, and use the narrowest conversion method available. Prefer a loopback LLM for sensitive material; when a remote endpoint is configured, treat every extracted image as externally transmitted data.
Do not process audio or video with this Skill. Route those inputs to a separately reviewed local transcription workflow if support is added later.
MarkItDown produces analysis-oriented Markdown, not a high-fidelity replacement for the original document. Use a format-specific document skill when layout preservation, editing, tracked changes, or pixel-accurate rendering matters.