Content formats for LLMs — choosing what to feed your AI pipeline
You've extracted clean content from a web page. The navigation is gone, the cookie banners are stripped, the ad containers are history. The next question — what format should this content be in when your pipeline consumes it? — gets surprisingly little attention considering how much it affects everything downstream.
Contextractor can hand you five formats: plain text, Markdown, cleaned HTML, JSON, and the original raw HTML (the unmodified page source, saved before extraction). Its extraction engine is the Rust port of Trafilatura, so you get the same content-detection quality without any Python in the pipeline. Plenty of extraction tools give you only one or two. But the choice isn't cosmetic; it determines your token budget, what structural signals your model can work with, and how much glue code you'll need between extraction and inference.
For context on why content extraction matters before you even get to format selection, see the extraction for LLMs guide.
What each format gives your pipeline
The gap between formats is wider than most people assume.
Plain text gives your pipeline the words and nothing else. Headings become indistinguishable from body paragraphs. Tables collapse into space-separated values. Links vanish — you get the anchor text but not the URL. For embedding models that compute vector representations of meaning, that's ideal. For anything that needs structural context, you're starving the model of useful signals.
Markdown sits in an interesting middle ground. It preserves headings (##), lists, tables (pipe syntax), and links while adding almost no token overhead — roughly 10% more tokens than plain text for a typical article1. The ## and - markers are cheap. This is why the /llms.txt proposal, introduced by Jeremy Howard in September 2024, chose Markdown as the standard format for LLM-readable documentation2.
Cleaned HTML retains the most structural information: semantic tags, table markup, image references, link targets. The cost is tokens. HTML tags aren't free — <h2>, <p>, <table>, <tr>, <td> all eat into your context window.
JSON wraps the extracted text plus metadata (title, author, date, categories, tags) in a structured envelope. The text body itself is typically plain or lightly formatted, but the metadata fields are machine-parseable without regex. Contextractor's JSON output nests the content alongside fields like title, author, date, sitename, and source1.
Original (raw HTML) is the complete page source saved before extraction — every <div>, script, and inline style exactly as the server (or headless browser) returned it. Unlike cleaned HTML, nothing is stripped or scored; it's the raw input the extractor runs on. It's there for archival, debugging, and re-extraction with better settings later, not for feeding directly to a model.
Token costs of feeding each format
Even with 128K-token context windows, most RAG pipelines stuff multiple retrieved documents into a single prompt. If you're retrieving 10 chunks at 2,000 tokens each, format overhead adds up fast.
Markdown's ~10% overhead is almost negligible. JSON adds roughly 40% because of the metadata wrapper and field delimiters — "key": "value" isn't cheap to tokenize. HTML runs about 50% over plain text, mostly from tag pairs.
(These ratios shift depending on content type. Table-heavy pages see higher HTML and Markdown overhead; short articles with long metadata fields make JSON proportionally more expensive.)
The token cost reduction guide covers broader strategies for keeping context window usage under control.
Plain text: best for embeddings
For embedding-based retrieval, plain text is hard to beat. Embedding models like OpenAI's text-embedding-3-large or Cohere's embed-v3 don't understand Markdown syntax or HTML tags — they treat ## as two hash characters, not as a heading marker. Stripping all formatting before embedding means every token carries semantic weight rather than structural noise.
The same applies to classification and sentiment analysis tasks. If you're routing documents by topic or scoring them for tone, the formatting carries no useful signal and the extra tokens just add latency.
Simple text-to-speech pipelines also want raw text. Heading markers and Markdown syntax would get read aloud as literal characters.
There's an honesty to plain text. It makes no promises about structure it can't keep.
Markdown: what LLMs understand natively
Most LLMs were trained on enormous quantities of Markdown — GitHub READMEs, documentation sites, Stack Overflow posts, technical blogs. They've seen so much of it that they parse ## headings and - item lists natively, without needing any special instructions.
Jina's ReaderLM-v2, a 1.5B-parameter model specifically built for HTML-to-Markdown conversion, outperforms GPT-4o on content extraction benchmarks, achieving ROUGE-L scores of 0.84-0.86 versus GPT-4o's 0.69 on main content extraction3. That a purpose-built small model can beat a frontier model at this task tells you something about how natural the HTML-to-Markdown mapping is.
For RAG with LLM generation, Markdown is arguably the default choice. The heading hierarchy helps the model understand which section a chunk came from. Lists remain parseable. Tables render correctly in most LLM interfaces. And the token overhead is minimal.
The heading structure is especially valuable when you're doing multi-document QA. If three retrieved chunks all start with ## Methodology, the model can reason about them as parallel sections rather than treating them as unrelated text blobs. Plain text loses that signal entirely.
JSON: when your pipeline needs metadata
When your downstream system isn't just an LLM but a structured pipeline — think Airflow DAGs, ETL jobs, data warehouses — JSON is the natural fit. You don't want to regex-parse an author name out of free text when you could just read doc["author"].
Contextractor's JSON output looks like this:
{
"title": "...",
"author": "...",
"date": "2026-01-15",
"sitename": "...",
"source": "https://...",
"text": "The extracted body text..."
}
The text field contains the article body (plain text by default), and the surrounding fields give you clean metadata for indexing, deduplication, and routing1.
These fields are fixed: Contextractor extracts the article and its standard metadata automatically — it does not take a custom JSON schema or prompt to pull arbitrary fields (price, SKU, rating, and the like). It is readable-article extraction, not schema-driven field extraction; for bespoke structured data, feed the clean output to your own LLM or parser.
JSON makes sense when you're building a content lake where different consumers need different fields. A search index might only want title + text. A citation generator needs author + date + source. A dedup pipeline keys on URL. Having all of that in named fields avoids brittle parsing.
The overhead for the metadata wrapper is worth it when you'd otherwise have to re-extract that metadata separately.
Cleaned HTML: when structure helps the model
Here's where things get interesting. A 2025 paper from Renmin University, accepted at the WWW conference, argued that cleaned HTML outperforms plain text for RAG — and backed it up across six QA benchmarks4.
The HtmlRAG approach feeds pruned HTML (not raw HTML — the CSS, scripts, and boilerplate are stripped) directly to the LLM. Their key insight: structural tags like <h2>, <table>, <th>, and <li> carry semantic information that plain text conversion destroys. When an LLM sees <th>Year</th><th>Revenue</th>, it understands that's a table header. When it sees Year Revenue as plain text, that context is gone.
Their two-step block-tree pruning compressed 20 retrieved documents from 1.6 million tokens down to about 4,000 tokens of cleaned HTML while maintaining retrieval quality4. On Natural Questions, cleaned HTML hit 42.25% EM versus plain text's 41.00% and Markdown's 39.00% (using Llama-3.1-70B with 128K context).
The gains aren't dramatic, but they're consistent. And the approach makes the most sense for table-heavy and list-heavy content where structural semantics carry the most weight.
If you're already doing aggressive HTML preprocessing — and the HTML preprocessing guide covers the details — keeping a cleaned HTML representation may give you better results than converting to Markdown and then trying to reconstruct structure.
Choosing the right format for your use case
There's no universal best format. The decision tree is shorter than you'd expect:
Embedding/vectorization — feed plain text. Every token should carry meaning, not formatting.
LLM prompts and RAG generation — feed Markdown. Token-efficient, preserves structure LLMs already understand, and it's what /llms.txt standardized on for a reason.
Structured data pipelines — feed JSON. Named fields beat regex parsing every time.
Table-heavy QA — consider feeding cleaned HTML. The HtmlRAG results suggest structural tags help when the content is inherently tabular.
These formats aren't mutually exclusive, either. Nothing stops you from extracting Markdown for your RAG pipeline and JSON for your metadata store from the same source document. Contextractor supports multiple output formats from a single extraction run — you don't have to re-process the page for each one.
Citations
-
Trafilatura: Documentation. Retrieved March 27, 2026 ↩ ↩2 ↩3
-
Jeremy Howard: The /llms.txt file. Retrieved March 27, 2026 ↩
-
Jina AI: ReaderLM-v2: Frontier Small Language Model for HTML to Markdown and JSON. Retrieved March 27, 2026 ↩
-
Jiejun Tan, Zhicheng Dou, Yutao Zhu, Peidong Guo, Kun Fang, Ji-Rong Wen: HtmlRAG: HTML is Better Than Plain Text for Modeling Retrieved Knowledge in RAG Systems. Proceedings of the ACM Web Conference 2025 ↩ ↩2
Updated: May 31, 2026