markitdown-converter · git:20260922.391e00a · 2026-09-22 · sha256 04cac45e940d041f
markitdown-converter git:20260922.391e00aA
Immutable. This exact content is served forever at /api/v1/blob/04cac45e940d041f.
---
name: markitdown-converter
description: "Create a new MarkItDown converter or plugin. Use when: adding a new file format converter, creating a plugin package, registering converters via entry points, or understanding the converter interface. Covers DocumentConverter subclass, accepts/convert pattern, plugin registration, pyproject.toml entry points, and priority system."
---
# MarkItDown Converter/Plugin Creation
## Quick Reference
### Converter Interface
```python
from markitdown import DocumentConverter, DocumentConverterResult, StreamInfo
class MyConverter(DocumentConverter):
ACCEPTED_MIME_TYPE_PREFIXES = ["application/vnd.myformat"]
ACCEPTED_FILE_EXTENSIONS = [".myf"]
def accepts(self, file_stream: BinaryIO, stream_info: StreamInfo, **kwargs) -> bool:
# Check extension first (exact match), then MIME type prefix
# MUST NOT change stream position — seek back if you read
extension = (stream_info.extension or "").lower()
if extension in self.ACCEPTED_FILE_EXTENSIONS:
return True
mimetype = (stream_info.mimetype or "").lower()
return any(mimetype.startswith(p) for p in self.ACCEPTED_MIME_TYPE_PREFIXES)
def convert(self, file_stream: BinaryIO, stream_info: StreamInfo, **kwargs) -> DocumentConverterResult:
# Read the stream and produce Markdown
content = file_stream.read()
markdown = self._do_conversion(content)
return DocumentConverterResult(markdown=markdown)
```
### Plugin Package Structure
```
packages/markitdown-myplugin/
├── pyproject.toml
└── src/
└── markitdown_myplugin/
├── __init__.py
├── __about__.py
├── _plugin.py # register_converters() + converter class(es)
└── py.typed
```
### pyproject.toml (plugin)
```toml
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[project]
name = "markitdown-myplugin"
dynamic = ["version"]
requires-python = ">=3.10"
dependencies = ["markitdown>=0.1.0"]
[project.entry-points."markitdown.plugin"]
myplugin = "markitdown_myplugin"
[tool.hatch.version]
path = "src/markitdown_myplugin/__about__.py"
```
### _plugin.py Template
```python
__plugin_interface_version__ = 1
def register_converters(markitdown: MarkItDown, **kwargs):
markitdown.register_converter(MyConverter())
```
### Priority System
| Constant | Value | Use Case |
|---|---|---|
| `PRIORITY_SPECIFIC_FILE_FORMAT` | `0.0` | Default for format-specific converters |
| `PRIORITY_GENERIC_FILE_FORMAT` | `10.0` | Catch-all (PlainText, HTML, ZIP) |
| Custom (e.g., OCR) | `-1.0` | Replace built-in converters |
Lower = tried first. Use `markitdown.register_converter(converter, priority=N)`.
## Optional Dependencies Pattern
```python
_dependency_exc_info = None
try:
import some_package
except ImportError:
_dependency_exc_info = sys.exc_info()
# In convert():
if _dependency_exc_info is not None:
raise MissingDependencyException(
"some_package", "pip install markitdown[myfeature]"
) from _dependency_exc_info[1]
```
## HTML-as-Intermediate Pattern
For formats that have an HTML representation, convert to HTML first, then use `_CustomMarkdownify`:
```python
from markitdown.converters import HtmlConverter
class MyConverter(DocumentConverter):
def convert(self, file_stream, stream_info, **kwargs):
html = self._extract_html(file_stream)
return HtmlConverter().convert_string(html, **kwargs)
```
## Testing
- Test files go in `packages/<pkg>/tests/test_files/`
- Expected outputs in `test_files/expected_outputs/`
- Use `FileTestVector` for parametrized tests
- See `packages/markitdown-sample-plugin/tests/` for a minimal plugin test example