Claude's training data has a cutoff date. Your users' questions do not. If you are building on the Anthropic API and someone asks about this week's release notes, today's pricing, or a breaking news event, the model either hallucinates or shrugs.
Anthropic's answer is the web_search server tool: a tool you declare in your API request that lets Claude search the web mid-response, on Anthropic's infrastructure, with zero search code on your side. Here is how to turn it on, how to keep it on a leash, and where it falls short.
Enabling Web Search in One Request
Web search is a server-side tool. You do not implement anything, run a search backend, or handle a tool-use loop. You add one entry to the tools array and Claude does the rest:
import anthropic
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-opus-4-8",
max_tokens=16000,
tools=[{
"type": "web_search_20260209",
"name": "web_search",
"max_uses": 5
}],
messages=[{
"role": "user",
"content": "What changed in the most recent Node.js LTS release?"
}]
)
No beta header. No API loop where you execute searches and feed results back. Claude decides whether to search, runs the queries server-side, reads the results, and answers with citations, all inside a single API call.
Two version strings matter:
web_search_20260209is the current variant on Claude Opus 4.6 and later, Sonnet 4.6, and Sonnet 5. It includes dynamic filtering: Claude writes small snippets of code behind the scenes to filter search results before they hit the context window, which saves tokens and improves accuracy.web_search_20250305is the basic variant for older models, and the only one available on Google Vertex AI.
One gotcha with the newer variant: do not also declare a separate code_execution tool unless you genuinely need code execution for your own workload. The 20260209 tools already run code under the hood, and a second execution environment confuses the model.
The Knobs You Actually Get
The tool takes four optional parameters. In my experience, you want at least two of them set in production.
max_uses caps how many searches Claude can run in a single request. Without it, a vague research question can fan out into a surprising number of queries, and you pay for each one. Start at 3 to 5 for Q&A workloads.
allowed_domains restricts searching to a whitelist. Domains are bare hostnames (no https://), and subdomains are included automatically:
tools=[{
"type": "web_search_20260209",
"name": "web_search",
"max_uses": 3,
"allowed_domains": ["docs.python.org", "peps.python.org"]
}]
blocked_domains is the inverse: search anywhere except these sites. You cannot use both lists in the same request. Pick one.
user_location biases results geographically. Pass an approximate location object (city, region, country, timezone) so "best hardware store near me" resolves sensibly.
Reading the Response
The response interleaves several content block types. A server_tool_use block shows the query Claude ran. A web_search_tool_result block carries the results. Then ordinary text blocks contain the answer, and any text that draws on a search result includes a citations array with the source URL, title, and the exact cited_text.
Anthropic's usage policy expects you to display those citations to end users when you show search-derived answers. Practically, that means walking response.content, rendering text blocks, and attaching linked sources from each block's citations. Do not throw them away.
One trap worth knowing: search failures do not raise exceptions. A failed search comes back as HTTP 200 with a web_search_tool_result block whose content is an error object like {"error_code": "max_uses_exceeded"} instead of a list of results. If your parser assumes content is always a list, it will crash on the first rate limit. Branch on the shape before indexing.
The Limits
Pricing. Web search bills at $10 per 1,000 searches on top of normal token costs, and the search results themselves count as input tokens. A five-search request against a long conversation is not cheap. Check Anthropic's pricing page for current numbers, then set max_uses accordingly.
Iteration caps and pause_turn. Server tools run in a server-side loop with a default limit of around 10 iterations. A long research turn can stop with stop_reason: "pause_turn". That is not an error and not a finished answer. You re-send the conversation with the paused assistant turn appended and the server resumes. Code that treats pause_turn as done will silently return half an answer.
Platform availability. This is the limit that surprises teams most. Web search is available on the first-party Claude API and Claude Platform on AWS. On Google Vertex AI you only get the older web_search_20250305 variant. On Amazon Bedrock, web search is not available at all. If your infrastructure lives on Bedrock, the tool simply is not there.
No control over the search itself. You never see the raw ranked results, cannot choose the search engine, cannot get more than what Claude decided to read, and cannot reuse the results outside that one API call. It is a black box by design.
When a Model-Agnostic Search Layer Makes More Sense
That last limit is the structural one. Claude's web search only works inside Claude. If your product also calls GPT, Gemini, or an open-weights model, or if you want to log, cache, rerank, or reuse search results across requests, you need search as its own layer rather than a per-vendor tool flag.
That is the model we built link.sc around. The Search API returns structured SERP results you control, and the Fetch API pulls full page content as clean markdown, ready to drop into any model's context window. Same search layer whether the downstream model is Claude, GPT, or Llama, which also means switching models never silently changes your retrieval behavior. I walked through that architecture in real-time web search for LLMs.
The two approaches also compose. Several of our users run Claude's built-in search for casual freshness questions and route research-grade retrieval through their own pipeline, where they can enforce domain lists, dedupe sources, and cache fetches.
Claude web_search tool |
Your own search layer (link.sc) | |
|---|---|---|
| Setup | One tools entry | One HTTP call per search or fetch |
| Works with | Claude only | Any model |
| Raw results access | No | Yes |
| Caching and reuse | No | Yes |
| Available on Bedrock | No | Yes (it is just HTTP) |
| Citations | Automatic | You build them from URLs you control |
And if your Claude usage is in Claude Desktop or Claude Code rather than the raw API, the MCP route is the better fit: see connecting Claude to the web with the link.sc MCP server.
Bottom Line
Enabling web search in the Claude API is genuinely a one-line change, and for Claude-only products that need freshness, it is the fastest path. Set max_uses, handle pause_turn, render the citations, and check that your deployment platform actually supports it before you commit. When you need search that outlives a single Claude call, put the search layer in your own hands.
Need web search and page fetching that works with every LLM, not just Claude? Get a free link.sc API key and make your first search call in under a minute.