Skip to main content

mdka

A HTML to Markdown converter written in Rust.

crates.io npm pypi License
Documentation Dependency Status CI Executable npm PyPi

logo

mdka balances conversion quality with runtime efficiency — correct, readable Markdown from real-world HTML, at competitive speed and near-flat memory.
"ka" means "化 (か)" pointing to conversion.


Why mdka?

There are several good HTML-to-Markdown converters in the Rust ecosystem. mdka's specific focus is:

  • Reliable output from diverse HTML sources. It is built on scraper, which uses html5ever — the HTML5 parser from the Servo browser engine. html5ever applies the same parsing algorithm that web browsers use, so it handles malformed tags, deeply nested structures, CMS output, and SPA-rendered DOM without special-casing.
  • Crash resistance. Conversion uses non-recursive DFS throughout. There is no stack overflow, no matter the nesting depth. That is a claim about crashing, not speed — deep nesting still costs real time, quadratically; see Scaling: Depth and Width.
  • Configurable pre-processing. Five conversion modes let you tune what gets kept or stripped, from noise-free LLM input to maximum retention. Four of the five currently produce identical output — see Conversion Modes.
  • Multi-language. The same Rust implementation is accessible from Node.js (napi-rs) and Python (PyO3).

Quick Start

Try it from the command line

Download a prebuilt binary (no Rust toolchain needed) from the latest release:

Platform Asset
Linux x64 (glibc) mdka@Linux-x64-gnu-<version>.tar.gz
Linux x64 (musl) mdka@Linux-x64-musl-<version>.tar.gz
Linux aarch64 (musl) mdka@Linux-aarch64-musl-<version>.tar.gz
macOS Apple Silicon mdka@macOS-aarch64-<version>.zip
Windows x64 mdka@Windows-x64-<version>.zip

Other platforms (macOS Intel, Windows ARM, Linux aarch64 glibc) aren't built as binaries — use cargo install mdka-cli below instead.

Extract the archive; it contains one folder holding the mdka binary:

cd mdka@Linux-x64-gnu-<version>  # the folder the archive extracted to

echo '<h1>Hello</h1><p><strong>world</strong></p>' | ./mdka
# # Hello
#
# **world**

Or install via cargo — requires cargo (Rust language) installed:

cargo install mdka-cli

echo '<h1>Hello</h1><p><strong>world</strong></p>' | mdka
# # Hello
#
# **world**
mdka page.html                          # → page.md  (same directory)
mdka --mode minimal --drop-shell -o out/ *.html  # strip nav/header/footer
mdka --help                             # full option list

Add to a Rust project

# Cargo.toml
[dependencies]
mdka = "2"
use mdka::html_to_markdown;

let md = html_to_markdown("<h1>Hello</h1><p><em>world</em></p>");
// "# Hello\n\n*world*\n"

With options:

use mdka::html_to_markdown_with;
use mdka::options::{ConversionMode, ConversionOptions};

let html = "<nav>menu</nav><h1>Hello</h1>";
let mut opts = ConversionOptions::for_mode(ConversionMode::Minimal);
opts.drop_interactive_shell = true;
let md = html_to_markdown_with(html, &opts);
// "# Hello\n"

Add to a Node.js project

npm install mdka

Prebuilt bindings are published for six platforms: Linux on x64 and arm64 (each with glibc and musl), macOS Apple Silicon, and Windows x64. macOS Intel and Windows ARM are not supported; the installation page lists what does work there.

const { htmlToMarkdown, htmlToMarkdownWithAsync } = require('mdka')

const md = htmlToMarkdown('<h1>Hello</h1>')
// "# Hello\n"

async function main() {
  const html = '<nav>menu</nav><h1>Hello</h1>'
  const minimal = await htmlToMarkdownWithAsync(html, {
    mode: 'minimal',
    dropInteractiveShell: true,
  })
  console.log(minimal)
}
main()

Add to a Python project

pip install mdka
import mdka

md = mdka.html_to_markdown('<h1>Hello</h1>')
# "# Hello\n"

html = '<nav>menu</nav><h1>Hello</h1>'
minimal = mdka.html_to_markdown_with(
    html,
    mode=mdka.ConversionMode.Minimal,
    drop_interactive_shell=True,
)

Conversion Modes

Mode Use when
Balanced General use — default
Strict Debugging, diff comparison
Minimal LLM input, text extraction
Semantic SPA content, ARIA-aware pipelines
Preserve Archiving, audit trails

Balanced, Strict, Semantic and Preserve currently produce identical output. They differ only in the defaults of fields that have no effect today, so choosing between them changes nothing today. They remain distinct API and may diverge again — see Conversion Modes, which explains why in full.

Tables convert to GFM tables. Column alignment is carried over, | in a cell is escaped, colspan/rowspan are expanded, and a cell holding block content is flattened (paragraphs join with <br>, a list becomes - one<br>- two). Four shapes have no Markdown expression and fall back to one paragraph per cell rather than a broken table: more than one header row, <th> used as each row's first cell, a nested <table>, and a <caption>. No table welds its cells together on either path. See Supported Elements for the full list of what is and is not supported.


Learn More

Full documentation is published as GitHub Pages, and its source lives in docs/.

https://nabbisen.github.io/mdka-rs/

Topic Link
Installation /getting-started/installation
Rust Usage & Examples /getting-started/usage-rust
Node.js Usage /getting-started/usage-nodejs
Python Usage /getting-started/usage-python
CLI Reference /getting-started/usage-cli
API Reference /api/index
Conversion Modes /api/modes
ConversionOptions /api/options
Supported Elements /api/elements
Design Philosophy /design/philosophy
Performance Characteristics /design/performance-characteristics
Architecture /design/architecture
Features /design/features
Changelog CHANGELOG.md
Roadmap ROADMAP.md

Open-source, with care

This project is lovingly built and maintained by volunteers.
We hope it helps streamline your work.
Please understand that the project has its own direction — while we welcome feedback, it might not fit every edge case 🌱

Acknowledgements

Depends on scraper (+ html5ever), ego-tree, rayon, thiserror.

Also, napi-rs on binding for Node.js and PyO3's pyo3 / maturin on bindings for Python.

Release files for mdka 2.5.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for mdka 2.5.1
File Size Uploaded
mdka-2.5.1.tar.gz 1.0 MB Details

Built distributions (wheels)

Table of built distributions (wheels) for mdka 2.5.1
File
mdka-2.5.1-cp310-abi3-win_amd64.whl CPython 3.10 abi3 Windows x86-64 Details
mdka-2.5.1-cp310-abi3-musllinux_1_2_x86_64.whl CPython 3.10 abi3 Linux musl 1.2+ x86-64 Details
mdka-2.5.1-cp310-abi3-musllinux_1_2_aarch64.whl CPython 3.10 abi3 Linux musl 1.2+ ARM64 Details
mdka-2.5.1-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.10 abi3 Linux glibc 2.17+ x86-64 Details
mdka-2.5.1-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl CPython 3.10 abi3 Linux glibc 2.17+ ARM64 Details
mdka-2.5.1-cp310-abi3-macosx_11_0_arm64.whl CPython 3.10 abi3 macOS 11.0+ ARM64 Details

Total release size: 5.1 MB

Release files / mdka-2.5.1.tar.gz

Download URL mdka-2.5.1.tar.gz
Size 1.0 MB
Tags Source
SHA-256 checksum
How to use checksums
8237a80a04383150b3d79fb7cbdc5a8d4c4f2e38366f2eb93a4268d8f21c0993
BLAKE2b-256 checksum
How to use checksums
00495b8aac18f7291fff19a5dc7d3761b93309b5fd083628658efe29fac37e25
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.18 {"installer":{"name":"uv","version":"0.12.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / mdka-2.5.1-cp310-abi3-win_amd64.whl

Download URL mdka-2.5.1-cp310-abi3-win_amd64.whl
Size 531.2 kB
Tags CPython 3.10 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
002f94fc03ca1dd02b8756d76f3db319dfb74b1a46ce40ba7512c94a3f4ebde9
BLAKE2b-256 checksum
How to use checksums
37898cfe0d743723961712dbc116f19ec661b9b94928fcf79078741fde8a5e4b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.18 {"installer":{"name":"uv","version":"0.12.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / mdka-2.5.1-cp310-abi3-musllinux_1_2_x86_64.whl

Download URL mdka-2.5.1-cp310-abi3-musllinux_1_2_x86_64.whl
Size 864.8 kB
Tags CPython 3.10 Linux musl 1.2+ x86-64 abi3
SHA-256 checksum
How to use checksums
1ac039910b47ad6ea0f4f3d3919fcf66595fed5cb569876c67832598f001d1f3
BLAKE2b-256 checksum
How to use checksums
d443bafd8d3543478cf16e2ed94ba7b4395488c0fcbd46a459e3517b3e557556
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.18 {"installer":{"name":"uv","version":"0.12.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / mdka-2.5.1-cp310-abi3-musllinux_1_2_aarch64.whl

Download URL mdka-2.5.1-cp310-abi3-musllinux_1_2_aarch64.whl
Size 813.0 kB
Tags CPython 3.10 Linux musl 1.2+ ARM64 abi3
SHA-256 checksum
How to use checksums
fa8fe0dd05a466306475206ecf3e41891a864e2c0ab1c754ec5ab877ba8b74fd
BLAKE2b-256 checksum
How to use checksums
92ea177ae98cc8b01962d199ad932fa06c4209d1fa0c9a412d5e0d5c1d66eb4d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.18 {"installer":{"name":"uv","version":"0.12.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / mdka-2.5.1-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL mdka-2.5.1-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 631.2 kB
Tags CPython 3.10 Linux glibc 2.17+ x86-64 abi3
SHA-256 checksum
How to use checksums
15329f8ba5749531f624f4b66f7975dfcf42a4d54e8c59c9240809e91f30927b
BLAKE2b-256 checksum
How to use checksums
c4f6344f416c097c7be6e8261f243e1d4387a419492ba2787a2ecce1bf4dd0d6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.18 {"installer":{"name":"uv","version":"0.12.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / mdka-2.5.1-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl

Download URL mdka-2.5.1-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Size 633.8 kB
Tags CPython 3.10 Linux glibc 2.17+ ARM64 abi3
SHA-256 checksum
How to use checksums
8fc39d70243152154ca44be279a103bd99de74569942ad62e4976f7d6d2cec70
BLAKE2b-256 checksum
How to use checksums
cbf1fd0300b16e069875fb6b3e449c08af3e617cb8b2799aa66914efaa016dda
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.18 {"installer":{"name":"uv","version":"0.12.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / mdka-2.5.1-cp310-abi3-macosx_11_0_arm64.whl

Download URL mdka-2.5.1-cp310-abi3-macosx_11_0_arm64.whl
Size 564.6 kB
Tags CPython 3.10 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
d4af01e8f54f193d1f332a6da449ac02a050d91e0387b298e2bc786cd7a3d1a4
BLAKE2b-256 checksum
How to use checksums
5111d0b03687a6912f227270d340c6b7049a0e47f23bb48a20d3f74e36bc5b98
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.18 {"installer":{"name":"uv","version":"0.12.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

2.7.0

7 release files

2.6.0

7 release files

This release

2.5.1 This release

7 release files

2.5.0

7 release files

2.4.2

7 release files

2.4.1

7 release files

2.4.0

7 release files

2.3.0

7 release files

2.2.3

47 release files

2.2.2

47 release files

2.2.0

47 release files

2.1.8

47 release files

2.1.5

48 release files

2.1.4

48 release files

2.1.1

48 release files

2.1.0

48 release files

2.0.3

48 release files

2.0.2

48 release files

1.6.8

40 release files

1.6.7

40 release files

1.6.5

40 release files

1.6.4

40 release files

1.6.3

40 release files

1.6.2

40 release files

1.6.1

40 release files

1.6.0

40 release files

1.5.0

49 release files

1.4.7

48 release files

1.4.6

48 release files

1.4.5

48 release files

1.4.4

48 release files

1.4.0

44 release files

1.3.3

44 release files

1.3.2

44 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page