This is the full developer documentation for html-to-markdown
# html-to-markdown
> Turn messy, real-world HTML into clean Markdown, Djot, or plain text. Call one converter from Python, the browser, the CLI, and 13 more runtimes — and get identical output everywhere.
## Why html-to-markdown
[Section titled “Why html-to-markdown”](#why-html-to-markdown)
Handles messy, real-world HTML
Unclosed tags, odd entities, nested tables, mixed encodings — you get clean output without losing content.
Use it from your language, identical output
One converter behind Python, TypeScript, Go, Ruby, Java, and 11 more runtimes. The same input gives the same result everywhere.
Markdown, Djot, or plain text
Pick the output you need with a single option. Everything else works the same.
Get the metadata too
Pull the title, Open Graph, Twitter Card, JSON-LD, links, and images in the same pass — on by default.
Keep your tables structured
Get HTML tables back as structured rows and cells, spans and headers included, alongside the rendered Markdown.
Customize the conversion
Hook into the conversion to skip, replace, or preserve any element — and pay nothing when you don’t.
## Language support
[Section titled “Language support”](#language-support)
| Language | Install | API Reference |
| --------------------- | ------------------------------------------------------------ | ------------------------------------------- |
| **Rust** | `cargo add html-to-markdown-rs` | [Reference](/reference/api-rust/) |
| **Python** | `pip install html-to-markdown` | [Reference](/reference/api-python/) |
| **TypeScript / Node** | `pnpm add @xberg-io/html-to-markdown` | [Reference](/reference/api-typescript/) |
| **Go** | `go get github.com/xberg-io/html-to-markdown/packages/go/v3` | [Reference](/reference/api-go/) |
| **Ruby** | `gem install html-to-markdown` | [Reference](/reference/api-ruby/) |
| **PHP** | `pie install xberg-io/html-to-markdown` | [Reference](/reference/api-php/) |
| **Java** | Maven `io.xberg:html-to-markdown` | [Reference](/reference/api-java/) |
| **C#** | `dotnet add package XbergIo.HtmlToMarkdown` | [Reference](/reference/api-csharp/) |
| **Elixir** | `{:html_to_markdown, "~> 3.8"}` | [Reference](/reference/api-elixir/) |
| **R** | `install.packages("htmltomarkdown")` | [Reference](/reference/api-r/) |
| **C (FFI)** | Shared library + header | [Reference](/reference/api-c/) |
| **WebAssembly** | `pnpm add @xberg-io/html-to-markdown-wasm` | [Reference](/reference/api-wasm/) |
| **Swift** | Swift Package `HtmlToMarkdown` | [Reference](/reference/api-swift/) |
| **Dart** | `dart pub add h2m` | [Reference](/reference/api-dart/) |
| **Kotlin Android** | Maven `io.xberg:html-to-markdown-android` | [Reference](/reference/api-kotlin-android/) |
| **Zig** | Zig package `html_to_markdown_rs` | [Reference](/reference/api-zig/) |
| **CLI** | `cargo install html-to-markdown-cli` | [CLI Guide](/cli/) |
## Quick example
[Section titled “Quick example”](#quick-example)
* Python
main.py
```python
from html_to_markdown import convert
result = convert("
Hello
World
")
print(result.content)
print(result.metadata)
```
* TypeScript
index.ts
```typescript
import { convert } from "@xberg-io/html-to-markdown";
const result = convert("
Hello
World
");
console.log(result.content);
console.log(result.metadata);
```
* Rust
src/main.rs
```rust
use html_to_markdown_rs::convert;
fn main() -> Result<(), Box> {
let result = convert("
Hello
World
", None)?;
println!("{}", result.content.unwrap_or_default());
Ok(())
}
```
## Part of Xberg.io
[Section titled “Part of Xberg.io”](#part-of-xbergio)
[Xberg](https://github.com/xberg-io/xberg)The open-source content-intelligence engine: text, tables, and metadata from 101 formats (115 file extensions), with OCR, transcription, and code intelligence.
[Xberg Pro](https://xberg.io)A complete self-hosted content-intelligence backend in a single container. Commercial.
[Xberg Enterprise](https://xberg.io)The distributed, governed content-intelligence platform, scaled on Kubernetes with team governance and support. Commercial.
[crawlberg](https://github.com/xberg-io/crawlberg)Web crawling and scraping with HTML→Markdown and headless-Chrome fallback.
[html-to-markdown](https://github.com/xberg-io/html-to-markdown)Fast, lossless HTML→Markdown engine.
[liter-llm](https://github.com/xberg-io/liter-llm)Universal LLM API client with native bindings for 14 languages and 165 providers.
[tree-sitter-language-pack](https://github.com/xberg-io/tree-sitter-language-pack)Tree-sitter grammars and code-intelligence primitives.
[alef](https://github.com/xberg-io/alef)The polyglot binding generator that produces every per-language binding across the 5 polyglot repos.
## Explore the docs
[Section titled “Explore the docs”](#explore-the-docs)
[Get Started](/installation/)Install a binding and run your first \`convert()\` call.
[Guides](/visitor/)Visitor pattern, table extraction, and error handling.
[Concepts](/concepts/architecture/)Architecture, the conversion pipeline, and the plugin system.
[Reference](/configuration/)Options reference, generated API docs, and per-language guides.
[CLI](/cli/)Every conversion option as a command-line flag.
[Migration](/migration/)Upgrading from earlier versions.
## Getting help
[Section titled “Getting help”](#getting-help)
* **Bugs & feature requests** — [Open an issue on GitHub](https://github.com/xberg-io/html-to-markdown/issues)
* **Community chat** — [Join the Discord](https://discord.gg/xt9WY3GnKR)
* **Contributing** — [Read the contributor guide](/contributing/)
# API reference
> Generated, binding-accurate API pages from the Rust source (alef docs).
## API reference
[Section titled “API reference”](#api-reference)
These pages are **generated** from the public Rust API surface. You can run `task alef:generate` (or `alef docs`) after changing types, options, or `alef.toml` so the Markdown under `docs/reference/` stays in sync.
| Topic | Link |
| ----------------------------------- | ------------------------------------------------------ |
| All types and result shapes | [Types](/reference/types/) |
| Options, metadata, and field tables | [Configuration (generated)](/reference/configuration/) |
| Error / enum reference | [Error types (generated)](/reference/errors/) |
### Language APIs
[Section titled “Language APIs”](#language-apis)
| Language | Page |
| ----------------- | ---------------------------------------------------- |
| Rust | [api-rust](/reference/api-rust/) |
| Python | [api-python](/reference/api-python/) |
| TypeScript / Node | [api-typescript](/reference/api-typescript/) |
| Go | [api-go](/reference/api-go/) |
| Ruby | [api-ruby](/reference/api-ruby/) |
| PHP | [api-php](/reference/api-php/) |
| Java | [api-java](/reference/api-java/) |
| C# | [api-csharp](/reference/api-csharp/) |
| Elixir | [api-elixir](/reference/api-elixir/) |
| R | [api-r](/reference/api-r/) |
| Kotlin (Android) | [api-kotlin-android](/reference/api-kotlin-android/) |
| Swift | [api-swift](/reference/api-swift/) |
| Dart | [api-dart](/reference/api-dart/) |
| Zig | [api-zig](/reference/api-zig/) |
| C (FFI) | [api-c](/reference/api-c/) |
| WebAssembly | [api-wasm](/reference/api-wasm/) |
For how to *use* the API in your language, start with [Language guides](/language-guides/) and the narrative [Configuration](/configuration/) and [Error handling](/errors/) pages; this section is the exhaustive field-level reference.
# Changelog
All notable changes to html-to-markdown will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## \[Unreleased]
[Section titled “\[Unreleased\]”](#unreleased)
### Added
[Section titled “Added”](#added)
* **`ConversionOptions::hidden_content`** chooses whether the output holds the text that a browser does not show at first, so a search index can hold an inactive tab panel or a collapsed answer. `drop` (the default) writes none of it, as before. `reachable` keeps the text a reader can get to in the page: an element with the `hidden` attribute or with inline `display: none`, `visibility: hidden` or `font-size: 0`, an element of an inline `