Quick answer
How do I convert a URL to Markdown with an API?
Send the URL to GET https://webreaderapi.com/api/v1/read with your API key in the Authorization header. WebReaderAPI fetches the page, keeps the main content and returns it as Markdown with its title, author, date and word count. One page costs one credit (two if it needs a browser), from $0.07/1K pages as of October 2026. No KYC; pay in crypto.
The API in one table
| Base URL | https://webreaderapi.com/api/v1 |
|---|---|
| Read one page | GET or POST https://webreaderapi.com/api/v1/read |
| Many URLs or a site | POST https://webreaderapi.com/api/v1/batch and POST https://webreaderapi.com/api/v1/crawl, results from GET https://webreaderapi.com/api/v1/jobs/{job_id} |
| Credits left | GET https://webreaderapi.com/api/v1/credits (free) |
| Authentication | Send your API key in the Authorization header as a Bearer token, or in the api_key query parameter |
| Billing | 1 credit = 1 page read without a browser; 2 credits when the page needs a browser to render JavaScript. A request that fails, or that a site's robots.txt refuses, is not charged |
| Our crawler | WebReaderAPI/1.0 (+https://webreaderapi.com/bot/), robots.txt token WebReaderAPI |
| Smallest pack | 10,000 pages for $3.75; credits never expire |
How do I get an API key?
Three steps, no form to fill in. The slowest one is the blockchain confirmation of your top-up.
Top up in crypto
Send at least $25 in BTC, USDT, USDC, ETH, SOL, LTC. Account-number login; email is optional.
Buy a credit pack
10,000 pages for $3.75 is enough to test every option on your own URLs.
Copy your key
Your API key is ready in the dashboard once your crypto top-up is confirmed and you have bought a pack. Store it in an environment variable named
WEBREADER_API_KEY.
What does the first request look like?
It is a plain HTTPS GET with the page address in the url parameter. Encode the address, because it contains its own : and / characters; curl does it for you with --data-urlencode. The default settings already suit most articles and documentation pages: Markdown output, main content only, and a browser only when the page needs one.
curl -sG "https://webreaderapi.com/api/v1/read" \
-H "Authorization: Bearer $WEBREADER_API_KEY" \
--data-urlencode "url=https://example.com/blog/first-post"import os
import requests
resp = requests.get(
"https://webreaderapi.com/api/v1/read",
headers={"Authorization": "Bearer " + os.environ["WEBREADER_API_KEY"]},
params={"url": "https://example.com/blog/first-post"},
timeout=70,
)
resp.raise_for_status()
page = resp.json()
print(page["title"], "-", page["word_count"], "words,", page["credits_used"], "credit(s)")
with open("first-post.md", "w", encoding="utf-8") as f:
f.write(page["markdown"])
const params = new URLSearchParams({ url: 'https://example.com/blog/first-post' });
const res = await fetch(`https://webreaderapi.com/api/v1/read?${params}`, {
headers: { Authorization: `Bearer ${process.env.WEBREADER_API_KEY}` },
});
const page = await res.json();
if (!res.ok) throw new Error(`${page.error.code}: ${page.error.message}`);
console.log(page.title, page.word_count, 'words');
console.log(page.markdown.slice(0, 500));
What comes back?
A JSON object with the Markdown in the markdown field and the page's metadata next to it: title, description, author, published_at, language, site_name and word_count. Two fields help you check what happened: final_url is the address after redirects, and rendered tells you whether a browser was needed.
credits_used shows what the call cost: 1 for a plain page, 2 when rendered is true, one more if you chose a country. The response format page lists every field with an example.
Which options will I use most?
Five parameters cover most needs. All of them are optional.
| Parameter | Use it to |
|---|---|
format | Get text or cleaned html instead of markdown |
main_content | Set false to convert the whole page, menus included |
render | Force (true) or forbid (false) the browser; auto decides |
include_links | Get the page's links as a separate list |
max_chars | Cut long pages to fit a model's context budget |
The read reference describes every parameter, including country, include_images and timeout.
How do I check my remaining credits?
Call GET https://webreaderapi.com/api/v1/credits with the same key. It returns credits_remaining, credits_used_today and your concurrency_limit, and it costs nothing. Run it at the start of a long job so the job stops cleanly instead of failing on 402 insufficient_credits halfway through.
Prepaid credits never expire: unused pages stay on your account until you use them, so a pack bought for one project keeps its value for the next.
What happens if a site does not allow robots?
We do not read the page, and you are not charged. Our crawler announces itself as WebReaderAPI/1.0 (+https://webreaderapi.com/bot/) and follows the site's robots.txt. A disallowed page returns 403 blocked_by_robots; a site that refuses the request another way returns 502 target_refused with the site's own status code.
If a site refuses our request, we return its answer: we never solve CAPTCHAs, log in to accounts, or try to get around a block or a paywall. The errors page explains which errors are worth a retry and which are final.
Where do I go next?
- Read endpoint reference Every parameter of /read, with examples
- Batch and crawl Up to 100 URLs per batch, or a whole site
- Response format Every field of the answer
- Errors and robots.txt Codes, causes and retry rules
- Python requests, async httpx, RAG chunking
- Node.js fetch, a small pool, crawl polling
- curl and jq Recipes for the terminal
- MCP server A read_url tool for Claude and Cursor
- LangChain and LlamaIndex Loaders and tools for RAG
- OpenAI function calling A read_url tool schema and loop
- n8n HTTP Request tool for an AI Agent
- OpenClaw Add the MCP server next to web_fetch
Quick start: common questions
Is there an SDK to install?
No. WebReaderAPI is a plain HTTPS API, so any HTTP client works. The docs give copy-paste code for Python, Node.js and curl, and tool definitions for MCP, LangChain, LlamaIndex and OpenAI function calling. Nothing is published as a package.
Can I send the key in the URL instead of a header?
Yes, as the api_key query parameter. The Authorization: Bearer header is safer, because URLs often end up in logs and browser history. Create several API keys, for example one per agent or project, and revoke any of them from your dashboard.
Does a failed page use a credit?
No. 1 credit = 1 page read without a browser; 2 credits when the page needs a browser to render JavaScript. A request that fails, or that a site's robots.txt refuses, is not charged. Only a page that comes back with content is billed.
Can I try it before buying?
There is no free tier. There is no free tier: the smallest pack is the way to test, paid from the minimum top-up, and the amount added only to reach that minimum can be sent back on request within 30 days, in USDT or USDC, while unspent.