A clean, fast, non-AI search backend. SearXNG-powered, deterministically ranked, deduped, and stripped of SEO spam — so your model gets signal, not slop.
Sign up, mint a key, send a request. Three steps, less than a minute.
Sign up at bitseek.com, open the user drawer, and click API Keys → Create. Your key looks like bsk_live_ZQ4FPNQ5... — store it; we only ever show it once.
# Either header works. Bearer is recommended.
curl "https://bitseek.com/v1/search?q=fastapi+tutorial&limit=5" \
-H "Authorization: Bearer $BITSEEK_KEY"import os, requests
r = requests.get(
"https://bitseek.com/v1/search",
headers={"Authorization": f"Bearer {os.environ['BITSEEK_KEY']}"},
params={"q": "fastapi tutorial", "limit": 5},
timeout=15,
)
print(r.json()["results"][0])const res = await fetch(
"https://bitseek.com/v1/search?q=fastapi+tutorial&limit=5",
{ headers: { "Authorization": `Bearer ${process.env.BITSEEK_KEY}` } }
);
const data = await res.json();
console.log(data.results[0]);{
"query": "fastapi tutorial",
"results": [
{
"title": "FastAPI Tutorial — User Guide",
"url": "https://fastapi.tiangolo.com/tutorial/",
"snippet": "FastAPI is a modern, fast web framework...",
"score": 0.91,
"domain": "fastapi.tiangolo.com",
"published_at": null
}
],
"count": 5,
"took_ms": 187,
"cached": true,
"cards": [],
"spelling": null
}
Quota and rate-limit info comes back as response headers (see below), not in the body, so they don't bloat your JSON parser on every call.
Seven routes. Bearer auth. JSON in, JSON out.
/v1/search| Name | Type | Default | Description | |
|---|---|---|---|---|
| q | string | required | — | Search query. Supports operators (site:, "phrase", -exclude). |
| limit | integer | optional | 10 | Number of results. Max 50. |
| category | string | optional | general | SearXNG category: general, news, images, videos, map, science, it, files, social media. |
| date_range | string | optional | — | One of day, week, month, year. |
| boost_domains | string | optional | — | Comma-separated domains to upweight in ranking (e.g. nature.com,arxiv.org). |
| block_domains | string | optional | — | Comma-separated domains to filter out of results. |
/v1/news accepts q, limit, date_range. /v1/images accepts q, limit. /v1/instant accepts q only.
Every authenticated response includes:
| X-Plan | Your current plan id (free, starter, pro, scale, enterprise). |
| X-RateLimit-Remaining | Token-bucket tokens remaining right now. Refills at your plan's rps. |
| X-Quota-Remaining | Requests left in your current monthly window. |
| X-Quota-Limit | Total monthly quota for your plan. |
| X-Quota-Period | Identifier of the current billing window (e.g. 2026-05). |
| X-RateLimit-Reason | Only on 429s. Why you were rate-limited (rate_limited, quota_exhausted, etc.). |
| 401 | Missing, malformed, or revoked API key. |
| 402 | Monthly quota exhausted. Upgrade or wait for reset. |
| 403 | Key disabled or scope not granted. |
| 429 | Rate limit exceeded. Check X-RateLimit-Reason for cause; retry after a short backoff (your bucket refills at the plan's rps). |
| 5xx | Upstream issue. Safe to retry idempotent GETs with exponential backoff. |
Drop-in examples for the most common agent stacks. Copy, swap your key, ship.
from openai import OpenAI
import os, requests, json
client = OpenAI()
def bitseek_search(query: str, limit: int = 5) -> list:
r = requests.get(
"https://bitseek.com/v1/search",
headers={"Authorization": f"Bearer {os.environ['BITSEEK_KEY']}"},
params={"q": query, "limit": limit},
)
return r.json()["results"]
tools = [{
"type": "function",
"function": {
"name": "bitseek_search",
"description": "Search the open web with BitSeek. Returns ranked results with title, url, and snippet.",
"parameters": {
"type": "object",
"properties": {
"query": {"type": "string"},
"limit": {"type": "integer", "default": 5},
},
"required": ["query"],
},
},
}]
resp = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "What did SpaceX launch this week?"}],
tools=tools,
)import anthropic, os, requests
client = anthropic.Anthropic()
tools = [{
"name": "bitseek_search",
"description": "Search the open web. Use for current events, facts, or any info beyond the model's training cutoff.",
"input_schema": {
"type": "object",
"properties": {
"query": {"type": "string", "description": "The search query."},
"limit": {"type": "integer", "default": 5},
},
"required": ["query"],
},
}]
msg = client.messages.create(
model="claude-3-5-sonnet-latest",
max_tokens=1024,
tools=tools,
messages=[{"role": "user", "content": "Find recent papers on RAG-vs-long-context."}],
)
# When msg.stop_reason == "tool_use", call BitSeek and feed back:
for block in msg.content:
if block.type == "tool_use" and block.name == "bitseek_search":
results = requests.get(
"https://bitseek.com/v1/search",
headers={"Authorization": f"Bearer {os.environ['BITSEEK_KEY']}"},
params=block.input,
).json()from langchain_core.tools import tool
import os, requests
@tool
def bitseek_search(query: str, limit: int = 5) -> list:
"""Search the open web with BitSeek. Use for current events and facts."""
r = requests.get(
"https://bitseek.com/v1/search",
headers={"Authorization": f"Bearer {os.environ['BITSEEK_KEY']}"},
params={"q": query, "limit": limit},
timeout=15,
)
return r.json()["results"]
# Bind to any LangChain model:
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model="gpt-4o").bind_tools([bitseek_search])
print(llm.invoke("What happened at WWDC?"))from llama_index.core.tools import FunctionTool
from llama_index.core.agent import ReActAgent
from llama_index.llms.openai import OpenAI
import os, requests
def bitseek_search(query: str, limit: int = 5) -> list:
"""Search the open web with BitSeek."""
r = requests.get(
"https://bitseek.com/v1/search",
headers={"Authorization": f"Bearer {os.environ['BITSEEK_KEY']}"},
params={"q": query, "limit": limit},
)
return r.json()["results"]
tool = FunctionTool.from_defaults(fn=bitseek_search)
agent = ReActAgent.from_tools([tool], llm=OpenAI(model="gpt-4o"))
print(agent.chat("Latest research on Mamba SSMs?"))import { generateText, tool } from "ai";
import { openai } from "@ai-sdk/openai";
import { z } from "zod";
const bitseekSearch = tool({
description: "Search the open web with BitSeek.",
parameters: z.object({
query: z.string(),
limit: z.number().default(5),
}),
execute: async ({ query, limit }) => {
const r = await fetch(
`https://bitseek.com/v1/search?q=${encodeURIComponent(query)}&limit=${limit}`,
{ headers: { Authorization: `Bearer ${process.env.BITSEEK_KEY}` } }
);
return (await r.json()).results;
},
});
const { text } = await generateText({
model: openai("gpt-4o"),
tools: { bitseekSearch },
prompt: "What's the latest on AI legislation in the EU?",
});Pay-as-you-go in USD or Bitcoin. No vendor lock-in, no annual contracts, cancel anytime.
Rates use a token-bucket: each request consumes one token; tokens refill at the plan's req/s; the bucket holds up to burst tokens. Live plan limits available at /v1/plans.
The questions we get the most from agent builders.
No. We aggregate across a private SearXNG cluster (DuckDuckGo, Brave, Mojeek, Marginalia, and more), then re-rank with our own deterministic + learning-to-rank model trained on real click/dwell signals — not LLM hallucinations.
We log queries for ranking and abuse prevention, but everything is keyed by your API key — not a user identity. We never resell data. See privacy.
Not yet. We return titles, URLs, and snippets. A /v1/fetch endpoint that returns cleaned page text is on the roadmap (target: Q3 2026).
From your dashboard, click Upgrade → Pay with BTC. We use BTCPay Server — no third party touches your payment.
We publish realtime status at /status. Pro+ plans get a 99.9% SLA.