markmaton

markmaton is a lightweight HTML-to-Markdown parser for agent workflows.
It takes already-fetched page HTML, cleans the structure, and returns Markdown plus page metadata.
[!NOTE]
markmaton is a general parser, not a crawler.
Feed it HTML from Playwright, fetch, Firecrawl, or another upstream page-visit tool.
Why it exists
- Keep the parser core narrow and deterministic.
- Accept both fetched HTML and rendered HTML.
- Make HTML-to-Markdown robust enough for real agent workflows.
- Ship a simple Python CLI around a Go engine.
Install
pip
pip install markmaton
uv tool install markmaton
[!TIP]
markmaton itself now develops as a uv-managed Python 3.12 project.
The installed package still works through plain pip, but local development assumes uv.
Quickstart
CLI
markmaton convert \
--html-file page.html \
--url https://example.com/article \
--output-format markdown
To get the full structured response:
markmaton convert \
--html-file page.html \
--url https://example.com/article \
--output-format json
Python API
from markmaton import ConvertOptions, ConvertRequest, convert_html
html = "<article><h1>Hello</h1><p>World</p></article>"
response = convert_html(
ConvertRequest(
html=html,
url="https://example.com/article",
options=ConvertOptions(only_main_content=True),
)
)
print(response.markdown)
print(response.metadata.title)
[!TIP]
Pass url whenever you can.
markmaton uses it as parsing context for canonical metadata and absolute link resolution.
What you get back
The JSON response includes:
markdown
html_clean
metadata
links
images
quality
This keeps the parser useful both as a Markdown generator and as a page-normalization step in a larger workflow.
Project shape
- Go engine:
cmd/markmaton-engine
- Python wrapper and CLI:
markmaton/
- Parser fixtures and golden files:
testdata/
- Research, benchmark, and release docs:
docs/
Documentation
Start here:
Development
Set up the local development environment:
uv sync --group dev
Run the core test suites:
uv run python -m unittest discover -s tests -p 'test_*.py'
go test ./...
For a manual end-to-end smoke:
The repo is pinned to:
[!IMPORTANT]
Automated coverage stays unit-test-first.
Live page visits and benchmark sampling are intentionally kept out of the default automated test path.
Release notes