Quick answer
Which errors can the LLMWebSearch API return, and are they charged?
LLMWebSearch has six HTTP errors: 400 invalid_parameter, 401 invalid_api_key, 402 insufficient_credits, 429 rate_limited, 502 search_failed and 504 search_timeout. None is charged. Pages that cannot be read show a content_status inside a 200 instead. A working search costs 1 credit, from $1.20/1K searches as of October 2026. No KYC; pay in crypto.
Which HTTP errors exist?
The body is always {"error": {"code": "…", "message": "…"}}. No error uses a credit.
| HTTP | code | Cause | Retry? |
|---|---|---|---|
| 400 | invalid_parameter | A required parameter is missing or a value is out of range | No: fix the request |
| 401 | invalid_api_key | The key is missing, wrong or revoked | No: check the key |
| 402 | insufficient_credits | The balance cannot pay for this call | No: buy a pack |
| 429 | rate_limited | More calls per minute than the account allows | Yes, after a pause |
| 502 | search_failed | The search could not be completed | Yes, with backoff |
| 504 | search_timeout | No search result within 30 seconds | Yes, with backoff |
How is a page status different from an error?
A page status describes one result, not the call. The search ran, the results are there, and credits_used is set as usual. Only the content of that one page is missing, and content_status says why: blocked_by_robots, blocked_by_site_policy, target_refused, fetch_failed, fetch_timeout or unsupported_content.
Do not treat these as failures to retry the whole search. Use the other results, the snippet of the missing page, or a different source. The response format page explains each status in a table.
Why do you never retry around a refusal?
Because a refusal is the site's answer, and we respect it. 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 rejects our reader with a 403, a 429 or a challenge page, we report it as target_refused with the site's 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. We do not retry with another identity or a disguised browser either. Your agent should not loop on such a page: the result will not change, and the site has said no.
When should my code retry?
Only on 429, 502 and 504. Wait, then try again, doubling the wait each time and adding a little randomness so parallel workers do not retry in step. Three to five attempts are enough; after that, report the failure.
Never retry 400, 401 or 402: the same request gives the same answer until you change something. For pages, fetch_failed and fetch_timeout may work later, through a new search or an /extract call. target_refused, blocked_by_robots and blocked_by_site_policy are final.
import os
import random
import time
import requests
API = "https://llmwebsearch.com/api/v1/search"
HEADERS = {"Authorization": "Bearer " + os.environ["LLMWEBSEARCH_API_KEY"]}
RETRY_ON = {429, 502, 504}
def search(body, attempts=5):
delay = 1.0
for attempt in range(1, attempts + 1):
resp = requests.post(API, headers=HEADERS, json=body, timeout=60)
if resp.status_code == 200:
return resp.json()
err = resp.json().get("error", {})
if resp.status_code not in RETRY_ON or attempt == attempts:
raise RuntimeError(f"{resp.status_code} {err.get('code')}: {err.get('message')}")
time.sleep(delay + random.uniform(0, delay / 2))
delay = min(delay * 2, 30)
data = search({"q": "how to rotate api keys without downtime"})
unread = [r["url"] for r in data["results"] if r["content_status"] not in ("ok", "not_requested")]
print("credits:", data["credits_used"], "| pages not read:", unread)
What should I do on 402 insufficient_credits?
Stop and top up. The call was not run and cost nothing. To avoid stopping in the middle of a long job, check your balance first with GET https://llmwebsearch.com/api/v1/credits, which is free, and compare it with the number of searches you plan. Remember that a search with read above 3 needs 2 credits.
Credits come from packs bought with your crypto balance. Search credits have no expiry date: what you do not use this month is still there next year.
How do I stay under the rate limit?
Limit how many calls run at once in your own code. Every account has a per-minute call limit, shown in the dashboard; ask support and it can be raised. A small pool of parallel workers, four to eight for most agents, keeps a steady pace without bursts. The Python and Node.js pages each show such a pool.
When you do get a 429, pause before the next attempt instead of firing it at once. Retrying immediately only adds more refused calls.
Errors: common questions
Does a search with every page refused still cost a credit?
Yes, if the search itself worked: you still get the ranked results and snippets. The price of a search does not depend on how many of its pages could be read.
Is a 401 caused by a revoked key?
It can be. A revoked key, a typo, a missing Bearer prefix or a header that never reached us all give 401 invalid_api_key. Make one API key per agent, app or teammate and revoke any of them from the dashboard without touching the others.
Why did a page return fetch_timeout?
Pages are read in parallel, and a page that takes longer than 15 seconds is returned without content so it does not hold up the whole answer. Slow sites sometimes respond on a later attempt.
Can I see my failed calls?
Yes. The dashboard history lists your calls for 30 days, failed ones included, with their status and credits. Failed calls show 0 credits.