Migrating to v3
Background
Section titled “Background”html-to-markdown began as a Python library — a fork of markdownify — focused on converting HTML to Markdown. Over time, the core was rewritten in Rust for performance, and generated packages were added for 15 language surfaces: Python, TypeScript, Ruby, Go, PHP, Java, C#, Elixir, R, C, WebAssembly, Swift, Dart, Kotlin Android, and Zig.
v3.0.0 rationalises the library’s API surface. Instead of multiple
specialised functions, there is now a single convert() function that
returns a structured ConversionResult. This simplifies the API while
making all extraction capabilities available through one call.
hOCR support moved to Xberg
Section titled “hOCR support moved to Xberg”hOCR (OCR-generated HTML) processing was removed from html-to-markdown and moved into Xberg, the document extraction library in the Xberg ecosystem. hOCR is a document-level concern — it belongs in the extraction pipeline, not in an html-to-markdown converter.
API changes
Section titled “API changes”Before (v2)
Section titled “Before (v2)”v2 had multiple functions for different extraction needs:
convert(html)→Stringconvert_with_metadata(html, options, config)→(String, Metadata)convert_with_inline_images(html, options, config)→Extractionconvert_with_tables(html, options)→TablesResultconvert_with_visitor(html, options, visitor)→String
After (v3)
Section titled “After (v3)”v3 has one function:
convert(html, options?, visitor?)→ConversionResult
ConversionResult contains all data:
content— the converted text (Markdown, Djot, or plain text)metadata— HTML metadata (title, OG, links, images, structured data)tables— extracted tables with cell datadocument— structured document tree (when enabled)images— extracted inline images where the binding exposes them (Rust and WASM when built with inline image support; generated native bindings may omit the Rust-only image payload)warnings— non-fatal processing warnings
Migration table
Section titled “Migration table”| v2 | v3 |
|---|---|
convert(html) |
convert(html).content |
convert_with_metadata(html, opts, cfg) |
convert(html, opts).metadata |
convert_with_inline_images(html, opts, cfg) |
convert(html, opts).images (set extract_images: true) |
convert_with_tables(html, opts) |
convert(html, opts).tables |
convert_with_visitor(html, opts, v) |
convert(html, opts, v).content |
convert_to_string(html) |
convert(html).content |
hocr_spatial_tables: true |
Use Xberg |
ExtendedMetadata |
HtmlMetadata |
start_profiling() |
Removed |
markdownify(html) (Python) |
convert(html).content |
Examples by language
Section titled “Examples by language”// v2let markdown = convert(html, None)?;let (md, meta) = convert_with_metadata(html, None, cfg, None)?;
// v3let result = convert(html, None)?;let markdown = result.content.unwrap_or_default();let metadata = result.metadata; // always availablePython
Section titled “Python”# v2markdown = convert(html)markdown, metadata = convert_with_metadata(html)
# v3result = convert(html)markdown = result.contentmetadata = result.metadataTypeScript
Section titled “TypeScript”// v2const markdown = convert(html);const { markdown, metadata } = convertWithMetadata(html);
// v3const result = convert(html);const markdown = result.content;const metadata = result.metadata;// v2markdown, err := htmltomarkdown.Convert(html, nil)markdown, meta, err := htmltomarkdown.ConvertWithMetadata(html, nil)
// v3result, err := htmltomarkdown.Convert(html, nil)markdown := result.Contentmetadata := result.Metadata# v2markdown = HtmlToMarkdown.convert(html)markdown, metadata = HtmlToMarkdown.convert_with_metadata(html)
# v3result = HtmlToMarkdown.convert(html)markdown = result[:content]metadata = result[:metadata]// v2$markdown = HtmlToMarkdown\convert($html);[$markdown, $metadata] = HtmlToMarkdown\convert_with_metadata($html);
// v3$result = HtmlToMarkdown\convert($html);$markdown = $result->content;$metadata = $result->metadata;// v2String markdown = HtmlToMarkdown.convert(html);ConversionPair pair = HtmlToMarkdown.convertWithMetadata(html);
// v3ConversionResult result = HtmlToMarkdown.convert(html);String markdown = result.getContent();HtmlMetadata metadata = result.getMetadata();// v2string markdown = HtmlToMarkdown.Convert(html);(string md, Metadata meta) = HtmlToMarkdown.ConvertWithMetadata(html);
// v3ConversionResult result = HtmlToMarkdown.Convert(html);string markdown = result.Content;HtmlMetadata metadata = result.Metadata;Elixir
Section titled “Elixir”# v2{:ok, markdown} = HtmlToMarkdown.convert(html){:ok, markdown, metadata} = HtmlToMarkdown.convert_with_metadata(html)
# v3{:ok, result} = HtmlToMarkdown.convert(html)markdown = result.contentmetadata = result.metadata# v2markdown <- html_to_markdown(html)result <- html_to_markdown_with_metadata(html)
# v3result <- convert(html)markdown <- result$contentmetadata <- result$metadataC (FFI)
Section titled “C (FFI)”/* v2 */char *markdown = htm_convert(html, NULL);htm_free(markdown);
/* v3 */HtmResult *result = htm_convert(html, NULL);const char *markdown = htm_result_content(result);htm_result_free(result);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.