Playground Sign in Start free
APIs

Markdown Generation

Convert HTML to clean, LLM-friendly markdown with intelligent content filtering

Overview

The Markdown Generation API converts web pages to clean markdown perfect for LLM processing and RAG systems. Powered by Crawl4AI, it provides intelligent content filtering.

Quick Start

curl -X POST https://api.ujeebu.com/markdown \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{
    "url": "https://blog.example.com/article"
  }'
import { UjeebuClient } from '@ujeebu-org/ujeebu-sdk';

const client = new UjeebuClient('YOUR_API_KEY');

const response = await client.markdown(
  'https://blog.example.com/article'
);

console.log(response.data.markdown);
from ujeebu_python import UjeebuClient

client = UjeebuClient('YOUR_API_KEY')

response = client.markdown(
    'https://blog.example.com/article'
)

data = response.json()
print(data['markdown'])
client, _ := ujeebu.NewClient("YOUR_API_KEY")

result, _, err := client.Markdown(ujeebu.MarkdownParams{
    URL: "https://blog.example.com/article",
})

if err != nil {
    log.Fatal(err)
}

fmt.Println(result.Markdown)

Parameters

Parameter Type Required Default Description
url string Yes - URL to convert to markdown
filter string No Content filter: 'raw', 'fit' (default), 'bm25'
query string No Query for BM25 filtering
citations boolean No true Generate numbered citations. Defaults to false on POST requests.
js boolean No true Execute JavaScript.
proxy_type string No Proxy type: 'rotating', 'advanced', 'premium', 'residential', 'residential_us', 'residential_geo'. If not set, auto_proxy selects the best proxy automatically.
wait number No Wait time in ms after page load
wait_for_selector string No CSS selector to wait for before conversion
proxy string No Custom proxy URL to use for the request
timeout number No 60 Timeout in seconds.
auto_captcha_solve boolean No true Enable automatic CAPTCHA detection and solving.
auto_captcha_solve_timeout number No Timeout in milliseconds for CAPTCHA solving

Filter Types

Raw Filter

Complete page markdown without filtering.

curl -X POST https://api.ujeebu.com/markdown \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{
    "url": "https://example.com",
    "filter": "raw"
  }'
import { UjeebuClient } from '@ujeebu-org/ujeebu-sdk';

const client = new UjeebuClient('YOUR_API_KEY');

const response = await client.markdown(
  'https://example.com',
  { filter: 'raw' }
);

console.log(response.data.markdown);
from ujeebu_python import UjeebuClient

client = UjeebuClient('YOUR_API_KEY')

response = client.markdown(
    'https://example.com',
    params={'filter': 'raw'}
)

data = response.json()
print(data['markdown'])
client, _ := ujeebu.NewClient("YOUR_API_KEY")

result, _, err := client.Markdown(ujeebu.MarkdownParams{
    URL:    "https://example.com",
    Filter: "raw",
})

if err != nil {
    log.Fatal(err)
}

fmt.Println(result.Markdown)

Fit Filter (Default)

Extracts main content using Trafilatura/Readability.

curl -X POST https://api.ujeebu.com/markdown \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{
    "url": "https://blog.example.com",
    "filter": "fit"
  }'
import { UjeebuClient } from '@ujeebu-org/ujeebu-sdk';

const client = new UjeebuClient('YOUR_API_KEY');

const response = await client.markdown(
  'https://blog.example.com',
  { filter: 'fit' }
);

console.log(response.data.fit_markdown);
from ujeebu_python import UjeebuClient

client = UjeebuClient('YOUR_API_KEY')

response = client.markdown(
    'https://blog.example.com',
    params={'filter': 'fit'}
)

data = response.json()
print(data['fit_markdown'])
client, _ := ujeebu.NewClient("YOUR_API_KEY")

result, _, err := client.Markdown(ujeebu.MarkdownParams{
    URL:    "https://blog.example.com",
    Filter: "fit",
})

if err != nil {
    log.Fatal(err)
}

fmt.Println(result.FitMarkdown)

BM25 Filter

Relevance-based filtering with query.

curl -X POST https://api.ujeebu.com/markdown \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{
    "url": "https://docs.example.com",
    "filter": "bm25",
    "query": "installation instructions"
  }'
import { UjeebuClient } from '@ujeebu-org/ujeebu-sdk';

const client = new UjeebuClient('YOUR_API_KEY');

const response = await client.markdown(
  'https://docs.example.com',
  { filter: 'bm25', query: 'installation instructions' }
);

console.log(response.data.markdown);
from ujeebu_python import UjeebuClient

client = UjeebuClient('YOUR_API_KEY')

response = client.markdown(
    'https://docs.example.com',
    params={'filter': 'bm25', 'query': 'installation instructions'}
)

data = response.json()
print(data['markdown'])
client, _ := ujeebu.NewClient("YOUR_API_KEY")

result, _, err := client.Markdown(ujeebu.MarkdownParams{
    URL:    "https://docs.example.com",
    Filter: "bm25",
    Query:  "installation instructions",
})

if err != nil {
    log.Fatal(err)
}

fmt.Println(result.Markdown)

Response

{
  "success": true,
  "url": "https://blog.example.com/article",
  "markdown": "# Full content...",
  "fit_markdown": "# Filtered content...",
  "markdown_with_citations": "# Content⟨1⟩...",
  "references": "## References\\n\\n⟨1⟩ https://example.com",
  "metadata": {
    "html_length": 15420,
    "markdown_length": 3200,
    "conversion_time_ms": 150,
    "filter": "fit"
  }
}

Credits & Billing

Credit Cost

Credit cost per request depends on the proxy type and whether JavaScript rendering is enabled:

Proxy Type JS Enabled (default) JS Disabled
rotating (default) 5 1
advanced 10 5
premium 12 8
residential 30 20
residential_us 30 20
residential_geo 10 + 10/MB over 1MB 8 + 10/MB over 1MB

INFO — Credits Header

Consumed credits are returned in the Ujb-credits response header.

INFO — Auto Proxy

If no proxy_type is specified, auto proxy is enabled by default. The system automatically tries different proxies until one succeeds. Credits are charged based on the proxy that was actually used for the successful request.

Cost Example

# Convert a page with default proxy (rotating, js=true) — 5 credits
curl -X POST https://api.ujeebu.com/markdown \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{"url": "https://example.com/page"}'

# Convert a page with residential proxy — 30 credits
curl -X POST https://api.ujeebu.com/markdown \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{"url": "https://example.com/page", "proxy_type": "residential"}'
import { UjeebuClient } from '@ujeebu-org/ujeebu-sdk';

const client = new UjeebuClient('YOUR_API_KEY');

// Convert 100 pages with default proxy (rotating, js=true)
for (const url of pageUrls) {
  await client.markdown(url);
}
// Total: 100 × 5 = 500 credits

// Convert 100 pages with residential proxy
for (const url of pageUrls) {
  await client.markdown(url, { proxy_type: 'residential' });
}
// Total: 100 × 30 = 3,000 credits
from ujeebu_python import UjeebuClient

client = UjeebuClient('YOUR_API_KEY')

# Convert 100 pages with default proxy (rotating, js=true)
for url in page_urls:
    client.markdown(url)
# Total: 100 × 5 = 500 credits

# Convert 100 pages with residential proxy
for url in page_urls:
    client.markdown(url, params={'proxy_type': 'residential'})
# Total: 100 × 30 = 3,000 credits
client, _ := ujeebu.NewClient("YOUR_API_KEY")

// Convert 100 pages with default proxy (rotating, js=true)
for _, url := range pageURLs {
    _, _, err := client.Markdown(ujeebu.MarkdownParams{URL: url})
    if err != nil {
        log.Println(err)
    }
}
// Total: 100 × 5 = 500 credits

// Convert 100 pages with residential proxy
for _, url := range pageURLs {
    _, _, err := client.Markdown(ujeebu.MarkdownParams{
        URL:       url,
        ProxyType: "residential",
    })
    if err != nil {
        log.Println(err)
    }
}
// Total: 100 × 30 = 3,000 credits

Billing Notes

  • Credits charged only on successful conversion
  • Failed requests (4xx, 5xx errors) are not charged
  • residential_geo proxy requests exceeding 1MB incur an additional 10 credits per MB
  • When using auto_proxy, only the successful proxy attempt is billed
  • When a CAPTCHA is detected and solved, an additional +5 credits surcharge is applied on top of the base request cost (auto_captcha_solve is enabled by default)

Next Steps

Ready to build?

Spin up an API key in 60 seconds

Free tier: 5,000 credits, no card, full access to every endpoint on this page.