Marcato
Marcato is the HTML-to-Markdown library used by Analog. It is also available as a standalone Python package.
Use it when you already have HTML and need readable Markdown without site-specific rules. Conversion runs in your Python process: Marcato does not fetch pages or choose which part of a page to keep.
Install and convert
Section titled “Install and convert”Install Marcato in your Python environment, then pass the HTML string
to html_to_markdown(). It returns the Markdown as a string.
html_to_markdown() accepts plain text, an HTML fragment, a full document, or
an empty string. It also handles malformed HTML when lxml can recover it.
Install the package
pip install marcatoConvert a heading and paragraph
from marcato import html_to_markdown
html = "<h1>Hello</h1><p>Good to meet you!</p>"markdown = html_to_markdown(html)print(markdown)Output# Hello
Good to meet you!What Marcato preserves
Section titled “What Marcato preserves”Marcato renders headings, links, lists, quotes, code, images, media, callouts, inline emphasis, and tables. It carries authored accessibility text into the Markdown when an otherwise visual element would be silent.
Simple tables become GitHub Flavored Markdown tables. When spanning cells, tables inside other tables, or block content cannot fit that model, Marcato emits each cell in source order so the content is not lost.
Marcato’s output is deterministic: the same input, Marcato version, and
supported lxml version produce the same output.
Convert a table with a link and emphasis
from marcato import html_to_markdown
html = """<h2>Reading list</h2><table> <tr><th>Title</th><th>Status</th></tr> <tr> <td><a href="/guide/">Guide</a></td> <td><strong>Ready</strong></td> </tr></table>"""print(html_to_markdown(html))Output## Reading list
| Title | Status || --- | --- || [Guide](/guide/) | **Ready** |The heading, column labels, link, and bold text remain in the Markdown.
Resolve relative links
Section titled “Resolve relative links”By default, link and media destinations remain as written in the HTML.
Pass the page’s address as base_url when you want those relative
destinations resolved to absolute URLs.
A document’s own <base href> takes precedence. Bare #fragment
links stay local to the document. Supplying base_url only changes
how destinations are written; Marcato does not fetch them.
Give a relative link its full address
from marcato import html_to_markdown
html = '<a href="guide/">Read the guide</a>'markdown = html_to_markdown( html, base_url="https://example.com/docs/",)print(markdown)Output[Read the guide](https://example.com/docs/guide/)The complete Marcato contract on PyPI documents its exact treatment of whitespace, block boundaries, code fences, destinations, tables, compatibility, and attribution.