Quick answer
How do I run my first search with a web search API for AI agents?
Send your question to POST https://llmwebsearch.com/api/v1/search with your API key as a Bearer token. LLMWebSearch runs a live web search and returns up to 20 ranked results, with the first 3 pages read and returned as Markdown. One credit pays for that whole call, from $1.20/1K searches as of October 2026. No KYC; pay in crypto.
The API on one card
| Base URL | https://llmwebsearch.com/api/v1 |
|---|---|
| Search | POST or GET https://llmwebsearch.com/api/v1/search |
| Read URLs you already have | POST https://llmwebsearch.com/api/v1/extract |
| Credits left | GET https://llmwebsearch.com/api/v1/credits, free of charge |
| Authentication | Pass your API key as a Bearer token in the Authorization header, or as the api_key query parameter |
| Billing | One credit pays for one search: up to 20 ranked results, with the pages of the first 3 read and returned as Markdown. Reading 4 to 10 pages makes it 2 credits. A call that ends in an error costs nothing |
| Our page reader | LLMWebSearch/1.0 (+https://llmwebsearch.com/bot/), robots.txt token LLMWebSearch |
| Smallest pack | 5,000 searches for $9.25; credits never expire |
How do I get an API key?
There is no sign-up form. Waiting for the blockchain to confirm your top-up is the longest part.
Fund your balance in crypto
Send at least $25 in BTC, USDT, USDC, ETH, SOL, LTC. Sign in with an account number; an email address is optional.
Buy a pack of searches
5,000 searches for $9.25 is plenty to wire search into one agent and try every option.
Copy the key
Once your crypto top-up is confirmed and a pack is bought, your API key is waiting in the dashboard. Keep it in an environment variable called
LLMWEBSEARCH_API_KEY.
What does the first search look like?
It is one HTTPS POST with a small JSON body. Only q is required: the question or keywords, as a person would type them. The defaults already suit most agents. You get 5 ranked results, and the pages behind the first 3 are read and returned as Markdown of up to 6,000 characters each.
The three snippets below send the same search. Pick the one that matches your stack, set LLMWEBSEARCH_API_KEY in your shell, and run it.
curl -s "https://llmwebsearch.com/api/v1/search" \
-H "Authorization: Bearer $LLMWEBSEARCH_API_KEY" \
-H "Content-Type: application/json" \
-d '{"q": "how to rotate api keys without downtime", "max_results": 5, "read": 3}'import os
import requests
resp = requests.post(
"https://llmwebsearch.com/api/v1/search",
headers={"Authorization": "Bearer " + os.environ["LLMWEBSEARCH_API_KEY"]},
json={"q": "how to rotate api keys without downtime", "max_results": 5, "read": 3},
timeout=60,
)
resp.raise_for_status()
data = resp.json()
print("credits used:", data["credits_used"])
for r in data["results"]:
size = r.get("word_count", 0)
print(r["position"], r["title"], r["url"], r["content_status"], size, "words")
const res = await fetch('https://llmwebsearch.com/api/v1/search', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.LLMWEBSEARCH_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ q: 'how to rotate api keys without downtime', max_results: 5, read: 3 }),
});
const data = await res.json();
if (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);
const first = data.results.find((r) => r.content_status === 'ok');
console.log(first ? `${first.title}\n${first.url}\n\n${first.content.slice(0, 600)}` : 'No page could be read.');
What comes back?
A JSON object with your query, the time of the call in created_at, the price in credits_used, and a results array in ranked order. Every result has its position, title, url, host and snippet, plus published_at when the date is known.
The field to watch is content_status. When it says ok, the page was read and its main content sits in content, with a word_count. Results beyond read say not_requested. A page that could not be read says why, for example blocked_by_robots. The response format page explains every field.
Which parameters will I change most often?
Six parameters cover nearly every agent. All of them are optional.
| Parameter | What it changes |
|---|---|
max_results | How many ranked results come back, from 1 to 20 |
read | How many of the first results are read, from 0 to 10 |
max_chars | The length cap of each page's content, 500 to 50,000 characters |
topic and time_range | News instead of web pages, and a freshness window |
include_domains | Results only from the sites you list |
country and language | Where and in which language the search runs |
The search reference documents each one with an example, plus format and exclude_domains.
How many credits does a call use?
Most calls use one. The full rule set:
- Search reading 0 to 3 pages: 1 credit. That includes up to 20 ranked results.
- Search reading 4 to 10 pages: 2 credits.
- Extract: Reading pages whose URLs you already have costs 1 credit for each started group of 3 pages returned with content, up to 20 URLs per call; refused or failed URLs are not counted.
- Errors: 0 credit. A bad parameter, a wrong key, an empty balance or a failed search costs nothing.
- A page that could not be read inside a successful search does not change its price.
- Checking your balance with
GET https://llmwebsearch.com/api/v1/creditsis free.
Search credits have no expiry date: what you do not use this month is still there next year.
What happens when a site does not want to be read?
The result still appears, with its title, URL and snippet, but without the page content. Our reader respects robots.txt: it introduces itself as LLMWebSearch, follows the rules a site writes for it or for all robots, and leaves out the content of any page it is not allowed to read. A site that sets Content-Signal: ai-input=no in its robots.txt keeps its pages out of your results' content.
When a site answers our reader with a refusal, the result carries content_status: "target_refused" and the site's own HTTP status in target_status. When a site turns our reader away, the result comes back without content and with the site's status: we never solve CAPTCHAs, sign in to accounts or work around a block or a paywall. The errors page lists every status and the ones worth a retry.
Where do I go next?
- Search endpoint Every parameter of /search, with examples
- Extract endpoint Read 1 to 20 URLs you already have
- Response format Each field and every content_status
- Errors HTTP errors, page statuses, retry rules
- Python requests, async httpx, an answer with citations
- Node.js fetch, a small pool, the same citation loop
- curl and jq Terminal recipes
- MCP server search_web for Claude Code and Claude Desktop
- LangChain and LlamaIndex A tool and a retriever
- OpenAI function calling Tool schema, loop and Agents SDK
- n8n HTTP Request tool for an AI Agent
- OpenClaw Our search through MCP
Quick start: common questions
Do I need an SDK?
No. LLMWebSearch is a plain HTTPS API, so any HTTP client works. These docs give copy-paste code for Python, Node.js and curl, and tool definitions for MCP, LangChain, LlamaIndex, OpenAI function calling, n8n and OpenClaw. We publish no package.
Does the API write the answer for me?
No. The API returns sources, not a written answer: your own model reads the pages, writes the reply and cites the URLs. That keeps you free to choose the model, the prompt and the citation style.
Can I put the key in the URL?
Yes, as the api_key query parameter of GET /search. The Authorization header is the safer choice, because URLs end up in logs and shell history. Make one API key per agent, app or teammate and revoke any of them from the dashboard without touching the others.
Is there a free tier to try it?
No. There is no free tier: the 5,000-search pack is the way to try it, bought from the minimum top-up; whatever you added only to reach that minimum comes back on request within 30 days, in USDT or USDC, as long as it is unspent.