Converting Web Pages to Markdown: How to Build AI-Ready Content Pipelines

Clean markdown extraction from any URL for RAG pipelines, scraping, and AI agent workflows. JavaScript rendering, table preservation, and practical Python examples.

Converting Web Pages to Markdown: How to Build AI-Ready Content Pipelines

Large language models and AI agents consume text, not HTML. If you are building RAG pipelines, scraping pipelines, or feeding web content to an LLM, you need clean markdown, not raw page source cluttered with script tags, navigation, and boilerplate. Converting web pages to structured markdown is the first step in any content extraction workflow.

The problem with raw HTML

Fetching a page with curl or fetch() returns thousands of lines of HTML including:

  • Navigation bars, footers, cookie banners
  • Inline JavaScript and CSS
  • Tracking pixels and ad scripts
  • Boilerplate repeated across every page

Feeding this directly to an LLM wastes token budget on irrelevant content and degrades response quality. Markdown strips all of that and keeps the semantic structure: headings, paragraphs, lists, tables, and links.

What a web-to-markdown API does

A conversion API handles three hard problems:

  1. Content extraction: Identifies the main content area and strips boilerplate (nav, ads, cookie banners).
  2. Structure preservation: Converts HTML headings, lists, tables, and code blocks to their markdown equivalents.
  3. JavaScript rendering: Many modern sites load content dynamically via JS. A server-side renderer executes the JavaScript before extraction, so you get the actual content, not an empty shell.

Basic conversion

curl -X POST "https://theglitchstore.com/api/secure-proxy?api=web-to-markdown" \
  -H "x-api-key: gstore_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://en.wikipedia.org/wiki/Representational_state_transfer",
    "render_js": true,
    "preserve_tables": true
  }'

The response is clean markdown:

# Representational state transfer

Representational state transfer (REST) is a software architectural style
that defines a set of constraints for creating web services...

## Architectural constraints

| Constraint | Description |
|------------|-------------|
| Client-server | Separation of concerns |
| Statelessness | Each request is independent |
| Cacheability | Responses must define themselves as cacheable |

Building a RAG ingestion pipeline

For retrieval-augmented generation, you need consistent markdown chunks. Here is a Python pipeline that fetches a URL, converts to markdown, and splits into embeddings-ready chunks:

import requests

def url_to_markdown(url):
    """Fetch a URL and return clean markdown."""
    response = requests.post(
        "https://theglitchstore.com/api/secure-proxy",
        params={"api": "web-to-markdown"},
        headers={
            "x-api-key": API_KEY,
            "Content-Type": "application/json",
        },
        json={
            "url": url,
            "render_js": True,
            "preserve_tables": True,
        },
        timeout=30,
    )
    response.raise_for_status()
    return response.json()["markdown"]

def chunk_markdown(markdown, max_chars=1500):
    """Split markdown into chunks at heading boundaries."""
    sections = []
    current = []
    for line in markdown.split("\n"):
        current.append(line)
        if line.startswith("#") and len("\n".join(current)) > max_chars:
            sections.append("\n".join(current[:-1]))
            current = [line]
    if current:
        sections.append("\n".join(current))
    return sections

# Usage: fetch, chunk, embed
markdown = url_to_markdown("https://example.com/docs/api-reference")
chunks = chunk_markdown(markdown)
for chunk in chunks:
    embedding = embed(chunk)  # your embedding model
    store(embedding, chunk)   # your vector database

Handling JavaScript-heavy and protected sites

Sites behind Cloudflare or heavy JavaScript frameworks often return empty HTML to simple HTTP requests. The render_js parameter triggers a headless browser render before extraction, which:

  • Waits for JavaScript to populate the DOM
  • Bypasses basic bot detection that blocks raw fetch()
  • Captures content loaded via XHR or fetch

This adds latency (5 to 15 seconds) but is the only reliable way to extract content from single-page applications and protected sites.

Pricing

Web-to-markdown conversion costs 1 credit per call ($0.01). The first 100 credits are free on signup and never expire. For batch processing, 100 credits covers 100 page conversions, enough to build and test a full RAG pipeline before paying.

Start at theglitchstore.com and test the converter in the playground.