Language Binding Guides
Every binding wraps the same Rust core. The option names and return shapes are identical across languages; only the syntax differs. This page covers per-language install notes and naming conventions.
Package: html-to-markdown-rs on crates.io
html-to-markdown-rs = "3.6"Option structs follow Rust naming conventions (snake_case). Use the builder API via ConversionOptions::builder() or construct ConversionOptions directly.
See Installation: Feature Flags for the five Cargo features.
Python
Section titled “Python”Package: html-to-markdown on PyPI
Requires: Python ≥ 3.10
pip install html-to-markdownfrom html_to_markdown import convert, ConversionOptions
result = convert("<h1>Title</h1>", ConversionOptions(heading_style="atx"))print(result.content)Option keys match the Rust field names (snake_case). ConversionOptions accepts keyword arguments. ConversionResult is a class with attributes — access fields as result.content, result.metadata, result.tables, result.images, result.document, result.warnings.
TypeScript
Section titled “TypeScript”Package: @xberg-io/html-to-markdown on npm
Requires: Node.js ≥ 18
npm install @xberg-io/html-to-markdownimport { convert, HeadingStyle } from "@xberg-io/html-to-markdown";
const result = convert("<h1>Title</h1>", { headingStyle: HeadingStyle.Atx });console.log(result.content);Option keys are camelCase (headingStyle, linkStyle, outputFormat). The package ships both ESM and CJS outputs. TypeScript types are bundled.
Module: github.com/xberg-io/html-to-markdown/packages/go/v3
Requires: Go ≥ 1.26
go get github.com/xberg-io/html-to-markdown/packages/go/v3import ( "fmt" "log"
htmltomarkdown "github.com/xberg-io/html-to-markdown/packages/go/v3")
result, err := htmltomarkdown.Convert("<h1>Title</h1>", nil)if err != nil { log.Fatal(err)}fmt.Println(*result.Content)Options use Go struct field names (PascalCase). Convert returns (*ConversionResult, error). Errors are standard Go errors. Use errors.Is/errors.As to inspect them.
Gem: html-to-markdown on RubyGems
Requires: Ruby ≥ 3.2
gem install html-to-markdownrequire 'html_to_markdown'
result = HtmlToMarkdown.convert('<h1>Title</h1>', heading_style: :atx)puts result.contentOptions are keyword arguments with snake_case symbols. result is a ConversionResult object exposing accessor methods (content, metadata, tables, …), not a hash. Errors raise HtmlToMarkdown::ConversionError.
Package: xberg-io/html-to-markdown (native ext-php-rs extension)
Requires: PHP ≥ 8.2
Install with PIE — not composer require, which cannot load a native extension:
pie install xberg-io/html-to-markdownuse HtmlToMarkdown\HtmlToMarkdownApi;use HtmlToMarkdown\ConversionOptions;
$options = ConversionOptions::from_json(json_encode(['headingStyle' => 'Atx']));$result = HtmlToMarkdownApi::convert('<h1>Title</h1>', $options);echo $result->content;Classes live in the flat HtmlToMarkdown\ namespace. HtmlToMarkdownApi::convert returns a ConversionResult object: $result->content is a public property, while $result->getMetadata() and $result->getTables() are accessor methods. Conversion failures throw HtmlToMarkdown\HtmlToMarkdownException.
Maven: io.xberg:html-to-markdown
Requires: Java ≥ 25
<dependency> <groupId>io.xberg</groupId> <artifactId>html-to-markdown</artifactId> <version>3.6.8</version></dependency>import io.xberg.htmltomarkdown.HtmlToMarkdown;import io.xberg.htmltomarkdown.ConversionOptions;import io.xberg.htmltomarkdown.ConversionResult;import io.xberg.htmltomarkdown.HeadingStyle;import io.xberg.htmltomarkdown.HtmlToMarkdownRsException;
public class Main { public static void main(String[] args) throws HtmlToMarkdownRsException { ConversionOptions options = ConversionOptions.builder() .withHeadingStyle(HeadingStyle.Atx) .build(); ConversionResult result = HtmlToMarkdown.convert("<h1>Title</h1>", options); System.out.println(result.content()); }}Uses a builder for options. Conversion failures throw io.xberg.htmltomarkdown.HtmlToMarkdownRsException and its subtypes (ParseErrorException, ConfigErrorException, InvalidInputException, PanicException, OtherException). Native binaries ship in the JAR for Linux x86_64, macOS arm64/x86_64, and Windows x86_64.
C# (.NET)
Section titled “C# (.NET)”NuGet: XbergIo.HtmlToMarkdown
Requires: .NET 10
dotnet add package XbergIo.HtmlToMarkdownusing HtmlToMarkdown;
var options = new ConversionOptions { HeadingStyle = HeadingStyle.Atx };var result = HtmlToMarkdownConverter.Convert("<h1>Title</h1>", options);Console.WriteLine(result.Content);Classes live in the HtmlToMarkdown namespace (the XbergIo.HtmlToMarkdown prefix is only the NuGet package id). Properties are PascalCase. Errors throw HtmlToMarkdownRsException and subtypes.
Elixir
Section titled “Elixir”Hex: html_to_markdown
Requires: Elixir ≥ 1.14
{:html_to_markdown, "~> 3.8"}case HtmlToMarkdown.convert("<h1>Title</h1>", %{heading_style: :atx}) do {:ok, result} -> IO.puts(result.content) {:error, _kind, reason} -> IO.warn("failed: #{reason}")endconvert/2 returns {:ok, result} or {:error, kind, reason}. Options are a map or a %HtmlToMarkdown.ConversionOptions{} struct. The struct fields match the Rust names (snake_case).
CRAN: htmltomarkdown
Requires: R ≥ 4.2
install.packages("htmltomarkdown", repos = "https://xberg-io.r-universe.dev")library(htmltomarkdown)
result <- htmltomarkdown::convert("<h1>Title</h1>", heading_style = "atx")cat(result$content)Options are named function arguments. The returned list matches the ConversionResult shape with snake_case names. Errors stop execution with a message; wrap in tryCatch if you need to handle them.
Link against: libhtml_to_markdown
Header: html_to_markdown.h (HTM*H, all symbols prefixed htm*_/HTM_)
Download a pre-built release archive for your platform from the GitHub releases page, or build from source with cargo build --release -p html-to-markdown-ffi.
#include "html_to_markdown.h"
HTMAlefHandle result = htm_convert("<h1>Title</h1>", 0);if (result != 0) { char *content = htm_conversion_result_content(result); if (content != NULL) { printf("%s\n", content); htm_free_string(content); } htm_conversion_result_free(result);}Every heap-allocated string must be released with htm_free_string and every handle with the matching htm_*_free function. The C API is a thin synchronous FFI layer. No async mode, no thread-local state. Conversion errors return 0 and set the thread-local error accessible via htm_last_error_code / htm_last_error_context.
npm: @xberg-io/html-to-markdown-wasm
npm install @xberg-io/html-to-markdown-wasmimport { convert, WasmConversionOptions, WasmHeadingStyle } from "@xberg-io/html-to-markdown-wasm";
const options = WasmConversionOptions.default();options.headingStyle = WasmHeadingStyle.Atx;
const result = convert("<h1>Title</h1>", options);console.log(result.content);The package’s default (Node.js) entry point loads the .wasm module synchronously — no init() call needed. Browser and bundler consumers import the web/bundler build instead, which exports an async init() function that must complete before the first convert() call. convert() takes a WasmConversionOptions instance built via WasmConversionOptions.default(), not a plain object literal — its fields use camelCase and have the same shape as the TypeScript binding. The WASM build exposes inline image extraction when built with inline-images; generated native bindings may omit the Rust-only image payload.
Package: HtmlToMarkdown via SwiftPM
Requires: Swift ≥ 6.0
Add the package from https://github.com/xberg-io/html-to-markdown and import HtmlToMarkdown.
Package: h2m on pub.dev
Requires: Dart ≥ 3.11
dart pub add h2mThe package is pure Dart from the caller’s point of view and uses the generated flutter_rust_bridge runtime.
Kotlin Android
Section titled “Kotlin Android”Package: io.xberg:html-to-markdown-android
Requires: Android minSdk 21
Kotlin Android is an AAR with bundled JNI libraries. Kotlin/JVM users should use the Java package (io.xberg:html-to-markdown) directly.
Package: html_to_markdown_rs
Requires: Zig ≥ 0.16
The Zig package wraps the C FFI surface and links to the generated native library.
Found a bug or mistake on this page?
If something here is wrong or out of date, open an issue on GitHub or contribute a fix via pull request.