Convert HTML to Markdown. Native Node.js bindings powered by Rust for maximum performance.
This monorepo provides two ways to use turndown:
| Package | Platform | Description |
|---|---|---|
turndown-node |
npm | Node.js bindings with HTML parsing |
turndown-cdp |
crates.io | Rust crate for CDP-style DOM trees |
npm install turndown-nodeconst TurndownService = require("turndown-node");
const turndownService = new TurndownService();
const markdown = turndownService.turndown("<h1>Hello World</h1>");
// => "Hello World\n==========="100% compatible with turndown v7.2.0 - drop-in replacement with identical output.
turndown-node is significantly faster than the JavaScript implementation thanks to native Rust code:
| Fixture | Size | turndown-node | turndown (JS) | Speedup |
|---|---|---|---|---|
| small | 2 KB | 59,146 ops/s | 3,276 ops/s | 18.1x |
| medium | 16 KB | 7,061 ops/s | 433 ops/s | 16.3x |
| large | 141 KB | 774 ops/s | 47 ops/s | 16.6x |
| huge | 1.4 MB | 64 ops/s | 3 ops/s | 19.9x |
Average speedup: ~18x faster
Benchmarks run on Apple M-Series, Node.js v24. Run
node benchmarks/benchmark.jsto reproduce.
cargo add turndown-cdpuse turndown_cdp::{TurndownService, Node};
let service = TurndownService::new();
// Build a DOM tree
let mut h1 = Node::element("h1");
h1.add_child(Node::text("Hello World"));
let markdown = service.turndown(&h1).unwrap();The Rust crate uses a CDP-style Node structure (Chrome DevTools Protocol), making it ideal for:
- Browser automation with chromiumoxide
- Readability/content extraction pipelines
- Any scenario where DOM is already parsed
┌─────────────────────────────────────────────────────────────────┐
│ turndown-core │
│ Markdown AST types + Serialization │
└─────────────────────────────────────────────────────────────────┘
▲
│
┌─────────────┴─────────────┐
│ │
┌──────────┴──────────┐ ┌──────────┴──────────┐
│ turndown-napi │ │ turndown-cdp │
│ HTML → AST │ │ CDP Node → AST │
│ (tl parser) │ │ (for Rust apps) │
└──────────┬──────────┘ └─────────────────────┘
│
┌──────────┴──────────┐
│ turndown-node │
│ (npm package) │
└─────────────────────┘
See Architecture Decision Records for design rationale.
| Platform | Architecture | npm | Rust |
|---|---|---|---|
| macOS | ARM64 (Apple Silicon) | ✅ | ✅ |
| Linux | x64 (glibc) | ✅ | ✅ |
| Linux | ARM64 (glibc) | ✅ | ✅ |
| Windows | x64 | ✅ | ✅ |
- Node.js >= 22
- Rust >= 1.70
- pnpm >= 10
# Install dependencies
pnpm install
# Build native module
pnpm build
# Run tests
pnpm test
# Run Rust tests
cargo test --workspace
# Run benchmarks
node benchmarks/benchmark.jsturndown-node/
├── crates/
│ ├── turndown-core/ # Shared Markdown AST + serialization
│ ├── turndown-cdp/ # CDP Node → AST (crates.io)
│ └── turndown-napi/ # HTML → AST with NAPI-RS bindings
├── packages/
│ ├── turndown-node/ # Main npm package
│ ├── darwin-arm64/ # Platform-specific bindings
│ ├── linux-x64-gnu/
│ ├── linux-arm64-gnu/
│ └── win32-x64-msvc/
├── benchmarks/ # Performance benchmarks
├── tests/ # Jest parity tests
└── docs/adr/ # Architecture Decision Records
MIT
Copyright 2026 Sebastian Software GmbH, Mainz