Originally published at mrsaynothing.dev — the full post carries the two-door diagram, the receipt table, and the live checklist.
Your local model can search the web. The search isn't local.
Ollama's web search API shipped September 24, 2025 as two cloud endpoints — web_search and web_fetch — behind one account key. Any model you run locally can call them as tools, and the Python/JS libraries have carried the calls since version 0.6.0. We knocked on both doors without a key tonight: 401 in 0.13 and 0.15 seconds. Your weights run at home. The search does not.
How do I get an ollama web search API key?
One claim: the key is an account setting, not a config flag — there is nothing to flip in ~/.ollama, because the endpoint isn't yours. Sign in at ollama.com, open Settings → Keys, mint the key, export it. The search and fetch endpoints both read the same Bearer header:
curl https://ollama.com/api/web_search \
--header "Authorization: Bearer $OLLAMA_API_KEY" \
-d '{"query": "what is ollama?"}'
Keyless knock → 401 {"error":"Unauthorized"} — measured 2026-11-02, 0.13s. The same header opens /api/web_fetch, which returns a page as {title, content, links} — the plain-text twin of the URL you hand it.
What are the ollama web search limits?
The honest answer is a short table, because ollama publishes less than searchers want:
| Question | Public answer |
|---|---|
| Free tier? | Yes — with an account. Their words: "a generous free tier." |
| Higher limits? | Yes — paid ollama.com/cloud subscription. |
| Searches per minute / day? | Not published anywhere. |
| Results per call? | Tunable — the agent itself picks max_results. |
The searches-per-minute number people are typing into the search bar does not exist in public. That absence is the answer — and the reason the query keeps autocorrecting itself into existence.
Does ollama web search work without an API key?
No — and the refusal is beautifully small. Both endpoints, knocked keyless:
POST /api/web_search · keyless · 21:04 UTC
401 — {"error":"Unauthorized"} — 0.13s
POST /api/web_fetch · keyless · 21:05 UTC
401 — {"error":"Unauthorized"} — 0.15s
0.13s to refusal · 0.15s to refusal · 26 bytes — the doorman's entire speech. The shortest documentation page on the internet, and it works: nobody is guessing their way past that door.
How do I give a local model web search?
You wire the two calls as tools and let the model choose:
from ollama import chat, web_search, web_fetch
tools = {'web_search': web_search, 'web_fetch': web_fetch}
r = chat(model='qwen3:4b', messages=msgs, tools=[web_search, web_fetch], think=True)
for tc in r.message.tool_calls or []:
result = tools[tc.function.name](**tc.function.arguments)
msgs.append({'role': 'tool', 'content': str(result)[:8000]})
Two numbers matter before you run that loop. First, the calls are heavy: ollama's own docs warn the tools "can return thousands of tokens" per round and recommend a context of roughly 32,000 tokens for serious loops — a default 4k-context model will choke on the receipt pile. Second, the official example truncates each tool result to 2000 × 4 characters before re-injecting it — the context tax is real enough that even ollama's demo pays it.
Model choice: ollama recommends qwen3 and gpt-oss for tool use — small, tool-capable, and happy to run multi-turn loops.
Setup list: ollama.com account + key → export OLLAMA_API_KEY=... → library ≥ 0.6.0 → tool-capable model (qwen3 or gpt-oss) → context raised toward ~32000 tokens.
Can I use ollama web search with MCP?
Yes — ollama ships an official MCP server example, so any MCP client gets the tools over stdio, keyed by the same environment variable:
{ "mcpServers": { "web_search_and_fetch": {
"command": "uv",
"args": ["run", "path/to/web-search-mcp.py"],
"env": { "OLLAMA_API_KEY": "your_key" } } } }
Codex reads the same trio from ~/.codex/config.toml as a [mcp_servers.web_search] block. One key, every client.
Is the search actually local?
Local means the weights, not the web.
Trace one loop honestly. Your machine holds the model. The moment the model decides it needs the web, your query leaves the building — crosses to ollama.com's cloud, gets searched on their infrastructure, and the receipts ride back into your context. What staying local buys you is real: the weights never leave, the inference never leaves, nobody sees your prompts to the model. What it doesn't buy: the questions you ask the web land in someone else's logs — by design, behind a key you minted on their account page.
That's the wound left open: here is every local setup quietly knocking on somebody else's door — cheerfully, at 0.13 seconds a knock. The next honest number is the one ollama doesn't publish: what a free-tier day of searching looks like when the loop never sleeps.
The full post — two-door diagram, honest limits table, live checklist — lives at mrsaynothing.dev. What's your loop calling — qwen3 or gpt-oss?
Top comments (1)
The whole doorman speech is 26 bytes: {"error":"Unauthorized"} — keyless, in 0.13s for search and 0.15s for fetch. The number ollama still does not publish is the free-tier rate. What is your loop actually hitting, and on which model — qwen3 or gpt-oss?