Skip to content

Usage

convert() accepts an HTML string and returns a ConversionResult.

use html_to_markdown_rs::convert;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let html = "<h1>Hello</h1><p>This is <strong>fast</strong>!</p>";
let result = convert(html, None)?;
let markdown = result.content.unwrap_or_default();
println!("{markdown}");
Ok(())
}

Every call to convert() returns a ConversionResult with the following fields:

Field Type Description
content Optional<String> The converted text (Markdown, Djot, or plain). There is no extraction-only none output format.
document Optional<DocumentStructure> Structured document tree (headings, paragraphs, lists, tables). Only populated when include_document_structure is true.
metadata HtmlMetadata Extracted HTML metadata (title, description, Open Graph, Twitter Card, JSON-LD, links, images).
tables Vec<TableData> Extracted tables with full grid data (headers, rows, colspan/rowspan).
images Vec<ExtractedImage> Inline image extraction output. Rust and WASM expose it when built with inline-images; generated native bindings may omit the Rust-only image payload.
warnings Vec<ProcessingWarning> Non-fatal warnings raised during conversion.

Control output style, metadata extraction, and more via ConversionOptions.

use html_to_markdown_rs::{ConversionOptions, HeadingStyle, convert};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let options = ConversionOptions::builder()
.heading_style(HeadingStyle::Atx)
.skip_images(true)
.build();
let result = convert("<h1>Hello</h1><img src='pic.jpg'>", Some(options))?;
println!("{}", result.content.unwrap_or_default());
Ok(())
}

Enable extract_metadata to populate the metadata field with structured data parsed from the HTML <head> and document body.

use html_to_markdown_rs::{convert, ConversionOptions};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let html = r#"<html><head><title>My Page</title></head>
<body><h1>Hello</h1><a href="https://example.com">Link</a></body></html>"#;
let options = ConversionOptions::builder()
.extract_metadata(true)
.build();
let result = convert(html, Some(options))?;
let markdown = result.content.clone().unwrap_or_default();
println!("Markdown: {markdown}");
println!("Title: {:?}", result.metadata.document.title);
println!("Links: {:?}", result.metadata.links);
Ok(())
}

result.metadata is an HtmlMetadata with five top-level fields: document, headers, links, images, and structured_data. Everything is populated in a single pass.

Field Type Description
title Option<String> Page title from the <title> element.
description Option<String> <meta name="description"> content.
keywords Vec<String> Parsed <meta name="keywords">, split on commas.
author Option<String> <meta name="author"> content.
canonical_url Option<String> <link rel="canonical"> href.
base_href Option<String> <base href="…"> value.
language Option<String> lang attribute on <html>.
text_direction Option<TextDirection> dir attribute on <html>. One of left_to_right, right_to_left, auto.
open_graph BTreeMap<String, String> All og:* meta tags keyed by property (without the og: prefix).
twitter_card BTreeMap<String, String> All twitter:* meta tags keyed by name (without the prefix).
meta_tags BTreeMap<String, String> Every other <meta name> tag, keyed by name.
Field Description
headers HeaderMetadata entries for every <h1><h6> with level, text, and id.
links LinkMetadata entries for every <a> with href, text, rel values, and classified link_type.
images ImageMetadata entries for every <img> with src, alt, dimensions, and classified image_type.
structured_data JSON-LD, Microdata, and RDFa blocks with a data_type tag and the raw content.
Value Matches
anchor href starts with # (same-page anchors).
internal relative href or href that resolves inside the document’s own host.
external absolute URL on a different host.
email mailto: URI.
phone tel: URI.
other anything else (javascript:, data:, custom schemes).
Value Matches
data_uri src starts with data:.
inline_svg inline <svg> element (captured when extract_images is enabled).
external absolute URL on a remote host.
relative relative path or same-host URL.
Value Matches
json_ld <script type="application/ld+json"> blocks.
microdata itemscope/itemprop subtrees.
rdfa typeof/property subtrees.

Enable include_document_structure to get a parsed tree of the document’s structural elements.

use html_to_markdown_rs::{convert, ConversionOptions};
let options = ConversionOptions::builder()
.include_document_structure(true)
.build();
let result = convert("<h1>Title</h1><p>Paragraph</p>", Some(options))?;
if let Some(doc) = &result.document {
for node in &doc.nodes {
println!("{:?}", node);
}
}

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.