One HTTP request. Clean, structured Markdown back. web‑fetch fetches any public page and strips it down to what machines actually need — no scripts, no noise, no CSS soup.
$ curl -s 'https://web-fetch.xuss.us/fetch?url=https://example.com'
Models are trained to read Markdown fluently. Give them the same document as clean headings, lists and links — not 2,000 lines of tangled HTML.
HTML carries a huge overhead of tags, scripts and inline CSS that models pay for token-by-token. Conversion removes the dead weight before it ever reaches the API.
Clean content means accurate retrieval. No hidden text, no ad injections, no scripts — just the real article, chunked and embedded the way you want it.
Your agent asks for a URL, gets an answer it can actually use: title, final URL, status, and structured content — in one deterministic JSON envelope.
SSRF-hardened so it survives being open to the internet: every resolved IP, port, redirect and scheme is validated before a single byte is fetched.
Plain HTTP, JSON in and out. Works from Python, Node, curl, n8n, Make, Zapier — or straight from a prompt-tool like a glorified curl.
This box is calling the real API, right now. Paste any public http(s) URL and watch the web become Markdown.
// GET /fetch?url=<url> · try it with any public page — or an RSS feed, a JSON API, a robots.txt…
// output will appear here…
$ curl -s 'https://web-fetch.xuss.us/fetch?url=https://example.com'
{
"ok": true,
"url": "https://example.com",
"final_url": "https://example.com/",
"status": 200,
"content_type": "text/html",
"mode": "html",
"title": "Example Domain",
"redirects": [],
"truncated": false,
"markdown": "# Example Domain\\n\\nThis domain is for use in illustrative examples…"
}
const res = await fetch(
'https://web-fetch.xuss.us/fetch?url=' +
encodeURIComponent('https://example.com')
);
const { markdown, title, status } = await res.json();
// or raw markdown mode:
const md = await fetch(
'https://web-fetch.xuss.us/fetch?url=https://example.com',
{ headers: { accept: 'text/markdown' } }
).then(r => r.text());
import requests
r = requests.get(
"https://web-fetch.xuss.us/fetch",
params={"url": "https://example.com"},
timeout=30,
)
data = r.json()
print(data["title"])
print(data["markdown"])
# POST works too:
r = requests.post(
"https://web-fetch.xuss.us/fetch",
json={"url": "https://example.com"},
timeout=30,
)
| FIELD | TYPE | MEANING |
|---|---|---|
ok | bool | true on success, false on error |
url | string | the URL you submitted |
final_url | string | URL after redirects (useful for citations) |
status | int | HTTP status of the fetched page |
content_type | string | MIME type actually returned |
mode | string | html (converted) or text (plain/JSON) |
title | string|null | page <title>, when present |
redirects | int[] | status codes of each redirect hop |
truncated | bool | true if content hit a size cap |
markdown | string | the converted content |
| PARAM | WHERE | NOTES |
|---|---|---|
url required | query or JSON body | http/https only, max 4096 chars |
raw | query | raw=1 returns the markdown body directly (text/markdown) |
Accept: text/markdown | header | same as raw=1 |
| HTTP | CODE | WHEN |
|---|---|---|
| 400 | invalid | malformed URL, missing url, bad JSON body |
| 403 | blocked | private/loopback IP, disallowed port, credentials in URL |
| 404 | dns | hostname does not resolve |
| 413 | too-large | request body over 16 KB |
| 415 | unsupported | content type can’t become markdown (images, PDFs…) |
| 422 | redirect | too many redirects / bad redirect location |
| 429 | rate-limited / busy | over 60 req/min per IP, or server at capacity |
| 502 | unreachable / tls / reset / upstream | upstream refused, bad certificate, reset, other failure |
| 504 | timeout | upstream did not respond in 25 s |
Anyone can call this API, so it is built like an SSRF honeypot turned inside out. Every hop in the fetch path is validated — before any connection is made.
::ffff:127.0.0.1. Cloud metadata (169.254.169.254) is dead.Host header and SNI. The DNS answer cannot be swapped mid-flight.2130706433, 0x7f000001 and friends are decoded and checked before anything happens.script, style, iframe, object, embed, template, svg… removed before conversion.Add “fetch the URL as markdown” to your AI workflow — RAG, summarization, research, chat-with-web. It costs one request and makes every downstream call cheaper and sharper.