Web to Markdown API — HTML Scraper works with all sites avatar

Web to Markdown API — HTML Scraper works with all sites

Pricing

from $0.20 / 1,000 results

Go to Apify Store
Web to Markdown API — HTML Scraper works with all sites

Web to Markdown API — HTML Scraper works with all sites

Convert any public URL to clean, token-efficient Markdown — purpose-built for RAG pipelines, LLM ingestion, and AI agents. Multi-layer bot evasion handles Cloudflare & JS SPAs. CSS selector filtering, metadata extraction, and token budget control included. Free trial, Pay-per-result from $0.0004.

Pricing

from $0.20 / 1,000 results

Rating

0.0

(0)

Developer

INAPP

INAPP

Maintained by Community

Actor stats

1

Bookmarked

2

Total users

1

Monthly active users

a day ago

Last modified

Share

Web → Markdown API — URL to LLM-Ready Markdown

$0.0004/result · Free 7-day Pro trial · No credit card

Convert any public URL into clean, token-efficient Markdown — purpose-built for AI agents, RAG pipelines, and LLM ingestion. Powered by Trafilatura with a multi-layer bot evasion stack that handles Cloudflare and JS-heavy SPAs.

Try it on Apify


Quick Start

# Basic URL → Markdown
curl -X POST https://imapp--web-markdown-api.apify.actor/v1/markdown \
-H "Content-Type: application/json" \
-d '{"url": "https://en.wikipedia.org/wiki/Markdown"}'
# Get a free trial key (7-day Pro access)
curl -X POST https://imapp--web-markdown-api.apify.actor/v1/trial
# Convert raw HTML (skip the fetch step)
curl -X POST https://imapp--web-markdown-api.apify.actor/v1/html \
-H "Content-Type: application/json" \
-d '{"html": "<html><body><h1>Hello</h1><p>World</p></body></html>"}'
# Using your API key
curl -X POST https://imapp--web-markdown-api.apify.actor/v1/markdown \
-H "Authorization: Bearer your_key" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com", "options": {"output_format": "text"}}'

Features

FeatureDescription
Clean MarkdownNavigation, sidebars, and ads stripped automatically
Multi-format outputmarkdown, text (plain), or json (structured)
CSS selector filteringExtract specific elements (article.main, #content)
Token budget controlSet max_length to fit LLM context windows (100–1M chars)
Metadata extractionTitle, description, author, date, word count, language
Bot evasion stackcurl_cffi TLS impersonation → httpx → Playwright browser
Browser renderingOptional headless Chromium for JS-heavy SPAs
Free trial7-day Pro access, no credit card required
Rate limitingPer-client RPS + monthly quota with tiered limits

Bot Evasion Stack

The API automatically falls through three layers to get content:

Fetch attempt ──► curl_cffi (Chrome TLS fingerprint)
success? ──► Return content
│ fail
httpx (plain HTTP)
success? ──► Return content
fail (use_browser=true)
Playwright (headless Chromium)
success? ──► Return content
  • Layer 1: curl_cffi — Impersonates Chrome 125 TLS fingerprint. Passes Cloudflare's first line of defense. Handles ~80% of sites.
  • Layer 2: httpx — Plain HTTP fallback for simple sites.
  • Layer 3: Playwright — Full browser rendering for JavaScript-heavy SPAs (React, Vue, Angular). Patches navigator.webdriver, WebGL, permissions, and plugins for stealth.

Pricing

Pay-per-result — you only pay for successful conversions.

EventPriceWhat You Get
API result$0.0004Per successful URL → Markdown conversion (10K = $4)
Actor start$0.00005One-time per session (first 5 seconds waived)

Tier Limits

TierCalls/monthRPSExample monthly cost at max usage
Free10,0005$0 (always)
Starter25,00010~$10
Pro100,00025~$40
Enterprise500,00050~$200

Prices shown are base rates before Apify platform discounts (Bronze/Silver/Gold).

Apify user discounts: Apify subscription tiers (Bronze/Silver/Gold) apply a discount to the per-result price automatically.


Authentication

Pass your API key via one of two methods:

# Option A: Authorization header (recommended)
curl -H "Authorization: Bearer sk_pro_abc123" ...
# Option B: x-api-key header
curl -H "x-api-key: sk_pro_abc123" ...

No key? Unauthenticated requests are rate-limited to 5 RPS / 10K calls/mo (free tier). Get a free 7-day Pro trial at POST /v1/trial to unlock 25 RPS and 100K calls/mo.

Free Trial

$curl -X POST https://imapp--web-markdown-api.apify.actor/v1/trial
{
"api_key": "trial_a1b2c3d4e5f6g7h8",
"tier": "pro",
"expires_in_days": 7,
"usage_instructions": {
"authorization": "Bearer trial_a1b2c3d4e5f6g7h8",
"endpoints": ["POST /v1/markdown"],
"note": "POST /v1/html also available for converting raw HTML",
"docs": "/docs"
}
}

Trial limits: 1 key per IP address · 1 request per 60 seconds.


API Reference

All endpoints are versioned under /v1. Full interactive docs at /docs (Swagger UI) or /redoc.

GET /health

Health check for load-balancer probes. Unversioned — always accessible.

$curl https://imapp--web-markdown-api.apify.actor/health
{"status":"ok","service":"web-markdown-api","version":"0.1.0"}

POST /v1/markdown

Convert a public URL to clean Markdown, plain text, or structured JSON.

Request Body

FieldTypeDefaultDescription
urlstringrequiredThe URL to convert (http/https)
options.output_formatstring"markdown"markdown, text, or json
options.css_selectorstringnullCSS selector for a specific element
options.max_lengthintnullMax output characters (100–1,000,000)
options.include_linksbooltruePreserve hyperlinks in output
options.include_imagesboolfalseInclude image references
options.exclude_navigationbooltrueStrip nav/sidebar/footer
options.use_browserboolfalseEnable headless Chromium for JS-rendered pages

Example: Markdown output

curl -X POST https://imapp--web-markdown-api.apify.actor/v1/markdown \
-H "Authorization: Bearer your_key" \
-H "Content-Type: application/json" \
-d '{
"url": "https://en.wikipedia.org/wiki/Markdown",
"options": {
"output_format": "markdown",
"max_length": 5000,
"include_links": true,
"exclude_navigation": true
}
}'
{
"success": true,
"url": "https://en.wikipedia.org/wiki/Markdown",
"markdown": "# Markdown\n\n**Markdown** is a lightweight markup language...",
"metadata": {
"title": "Markdown - Wikipedia",
"description": "Lightweight markup language for plain text formatting",
"word_count": 1450,
"char_count": 8900,
"image_count": 3,
"link_count": 45,
"language": "en"
},
"output_format": "markdown",
"source": "trafilatura"
}

Example: Plain text output

curl -X POST https://imapp--web-markdown-api.apify.actor/v1/markdown \
-H "Authorization: Bearer your_key" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com", "options": {"output_format": "text"}}'
{
"success": true,
"url": "https://example.com",
"text": "Example Domain\n\nThis domain is for use in illustrative examples...",
"metadata": {"word_count": 17},
"output_format": "text",
"source": "trafilatura"
}

Example: Browser rendering for JS-heavy pages

curl -X POST https://imapp--web-markdown-api.apify.actor/v1/markdown \
-H "Authorization: Bearer your_key" \
-H "Content-Type: application/json" \
-d '{
"url": "https://react.dev/reference/react/hooks",
"options": {
"output_format": "markdown",
"use_browser": true,
"max_length": 2000
}
}'

Note: use_browser: true enables headless Chromium via Playwright. This is slower (3-10s per page) but can handle JavaScript-rendered SPAs that HTTP-only fetchers can't parse.

POST /v1/html

Convert raw HTML directly to Markdown — no fetch step. Useful when you already have the HTML content and want to skip the network request.

Same options as /v1/markdown (minus the url field).

curl -X POST https://imapp--web-markdown-api.apify.actor/v1/html \
-H "Authorization: Bearer your_key" \
-H "Content-Type: application/json" \
-d '{
"html": "<html><body><h1>Hello</h1><p>This is <strong>bold</strong> text.</p></body></html>",
"options": {"output_format": "markdown"}
}'
{
"success": true,
"url": "",
"markdown": "# Hello\n\nThis is **bold** text.",
"metadata": {"word_count": 5},
"output_format": "markdown",
"source": "trafilatura"
}

POST /v1/trial

Get a free 7-day Pro trial key. See Authentication above for the full response format and limits.

GET /v1/usage

Rate-limit usage statistics — for monitoring and debugging.

curl https://imapp--web-markdown-api.apify.actor/v1/usage \
-H "Authorization: Bearer your_key"
{
"active_clients": 12,
"total_monthly_calls": 3421,
"by_tier": {
"free": {"clients": 8, "calls_this_month": 1200},
"pro": {"clients": 4, "calls_this_month": 2221}
}
}

Error Responses

StatusMeaning
400Bad request (invalid parameters)
404URL returned HTTP 404
422Validation error (invalid URL format, empty HTML)
429Rate limit exceeded (RPS or monthly quota)
502Failed to fetch, render, or convert the URL

Rate-limited responses include retry information:

{
"detail": "RPS limit exceeded",
"retry_after_seconds": 0.85,
"upgrade_url": "https://console.apify.com/actors/imapp~web-markdown-api",
"tier": "free"
}

All responses include rate-limit headers:

X-RateLimit-Limit-RPS: 5
X-RateLimit-Remaining-RPS: 4
X-RateLimit-Limit-Monthly: 10000
X-RateLimit-Remaining-Monthly: 9997
X-Tier: free

Use Cases

Use CaseHow It Helps
RAG PipelinesIngest web content into vector databases (Pinecone, Weaviate, Qdrant) for semantic search
AI AgentsProvide clean, token-efficient context for Claude, GPT, Gemini reasoning
Content AnalysisExtract and analyze article text, sentiment, or topics at scale
Documentation IngestionConvert docs to Markdown for LLM fine-tuning or RAG
Data CollectionBuild structured datasets from web sources without browser overhead
Competitor MonitoringTrack pricing, features, and content changes on competitor sites

Rate Limits

Each tier has a requests-per-second (RPS) cap and a monthly quota. See the Pricing section for tier-specific limits.

  • Free tier: 5 RPS, 10K calls/month
  • Pro trial: 25 RPS, 100K calls/month (7 days)
  • Paid keys: Configured per customer

When you exceed either limit, all endpoints return HTTP 429 with a retry_after_seconds field and a link to upgrade.


Environment Variables

VariableDefaultDescription
LOG_LEVELinfoLog verbosity (debug, info, warning, error)
DEFAULT_RPS5Free tier requests/second limit
DEFAULT_MONTHLY_CALLS10000Free tier monthly call limit
PRO_RPS25Pro tier requests/second
PRO_MONTHLY_CALLS100000Pro tier monthly calls
HTTP_TIMEOUT30HTTP fetch timeout in seconds
MAX_RESPONSE_SIZE5242880Max response size in bytes (5 MB)
PRIMARY_FETCHERcurl_cffiPrimary HTTP client (curl_cffi or httpx)
USER_AGENTCustom User-Agent override (disables rotation)
API_KEYS_JSON{}JSON mapping of API keys to tiers (set as Secret)
ENABLE_PROXYautoEnable Apify proxy (1, true, or auto-detect)
PROXY_GROUPSRESIDENTIALApify proxy group
TRIAL_DURATION_DAYS7Trial key validity period

Secrets: API_KEYS_JSON should be set as a Secret in the Apify Console (Settings → Secrets), not as a regular environment variable.



Supported Sites

TypeQualityNotes
Blog posts, news, docs⭐ ExcellentTrafilatura excels at article extraction
Static HTML sites⭐ ExcellentFast, reliable, low latency
JavaScript SPAs (React, Vue)⭐ GoodEnable use_browser: true for JS rendering
Cloudflare-protected sites⭐ GoodTLS impersonation handles most challenges
PDFs, images, binaries❌ Not supportedReturn HTTP 502 with error detail

About

Built by imapp. Part of the IM App suite of developer APIs on the Apify platform.

Questions? Open an issue or reach out via the Apify Console.