Anthropic Messages with and without a server prompt supports exactly two server tools. Claude API executes them, so your application does not send an ordinary client tool_result.
| Tool | Exact type | Required limits |
|---|---|---|
| Web search | web_search_20250305 | max_uses: 1–5 |
| Web fetch | web_fetch_20250910 | max_uses: 1–3; max_content_tokens: 1–25,000 (approximate, text only) |
{
"model": "claude-opus-5",
"max_tokens": 2048,
"tools": [
{
"type": "web_search_20250305",
"name": "web_search",
"max_uses": 3,
"allowed_domains": ["docs.python.org"]
},
{
"type": "web_fetch_20250910",
"name": "web_fetch",
"max_uses": 2,
"max_content_tokens": 12000,
"allowed_domains": ["docs.python.org"],
"citations": {"enabled": true}
}
],
"messages": [{
"role": "user",
"content": "Find the current asyncio docs and open the best result"
}]
}| Object | Allowed fields |
|---|---|
| Web search | type, name, max_uses; optional allowed_domains or blocked_domains, allowed_callers |
| Web fetch | Web search fields + required max_content_tokens; optional citations |
namemust be exactlyweb_searchorweb_fetch; at most one server tool of each type is allowed per request. Guard accepts only the listed fields: unknown fields (including the official search optionuser_location) and other typed tool variants are rejected with400.- If supplied,
allowed_callersmust be exactly["direct"]. allowed_domainsandblocked_domainsare mutually exclusive. Each list accepts at most 100 ASCII domains, with no scheme, IP address, query/fragment, backslash, or wildcard in the hostname.- Web search may include an optional path after the domain, such as
docs.python.org/3/*; Web fetch accepts a bare domain only, with no path. - Web fetch
citations, when supplied, must be exactly{"enabled": true}or{"enabled": false}with no extra fields. Client tools must omittypeor usetype: "custom".
- The client must pass the limits above explicitly. A value over the limit or an unknown server-tool version is rejected with
400before execution. - Both tools first return
server_tool_use, followed by the correspondingweb_search_tool_resultorweb_fetch_tool_result; search citations are always on, while fetch citations are optional. - A tool failure may arrive inside a successful HTTP
200: find a tool-result block whosecontent.typeends in_tool_result_error, then readcontent.error_code. - Web fetch accepts a URL no longer than 250 characters that already appeared in a user message, client tool result, or earlier search/fetch result. It supports text, HTML, and PDF; sites that require JavaScript rendering are unsupported, and failed fetches consume
max_uses. - A successful Web search with no matches returns
content: []; this is not a tool error.
| Item | Charge |
|---|---|
| Web search | $0.01 per provider-reported billed request + ordinary input tokens for generated content |
| Provider-nonbillable Web search error | No $0.01 tool charge |
| Web fetch | No separate fee; fetched content is billed as input tokens |
- Kimi. Search and page fetch live in two separate endpoints,
POST /v1/kimi/searchandPOST /v1/kimi/fetch. They never call the model: they return text that you put into your next chat request yourself. There is no separate charge for them, you pay only for the tokens of that request. Request bodies, limits and error codes are on Kimi: Chat Completions. - Composer and Grok. Built-in web search is available during a reply. There is no separate public call for controlling this search; typed Anthropic server tools are not accepted. Client functions are supplied separately through
toolsand run by your client.
Search is model-directed: tools permits the operation, but the model decides whether to use it. These are the three exact shapes; similar objects from another API are not substitutes.
Chat Completions:
{
"type": "web_search",
"web_search": {
"enable": true,
"search_engine": "search-prime",
"search_result": true,
"count": 2
}
}Messages:
{
"type": "web_search_20250305",
"name": "web_search",
"max_uses": 1
}Responses:
{"type": "web_search_preview"}| API | Confirmed operation marker |
|---|---|
| Chat | A non-empty terminal web_search |
| Messages | A server_tool_use (web_search) with its web_search_tool_result |
| Responses | A completed web_search_call |
Guard adds $0.10 only for a confirmed call. Chat count: 2 means two result rows, not two paid operations. Messages max_uses reserves the allowed operations, while final billing uses confirmed calls.
Gemini searches the web with Google search. Search works on all three APIs and is switched on by an object in tools; it is billed separately, by the number of search requests.
| API | Object in tools |
|---|---|
| Messages | {"type": "web_search_20250305", "name": "web_search"} |
| Chat Completions | {"type": "web_search"} |
| Responses | {"type": "web_search"} |
{
"model": "gemini-4-argon",
"max_tokens": 4096,
"messages": [{"role": "user", "content": "What is new today?"}],
"tools": [{"type": "web_search_20250305", "name": "web_search"}]
}| Item | Charge |
|---|---|
| A search request | $0.014 for each request, starting with the first |
| Before the answer | the cost of one search ($0.014) is held; the final charge uses the actual number of searches |
| Retrieved text | ordinary input tokens |
- Claude Code sends the
web_search_20250305tool too, so search from Claude Code works. - Gemini has no separate
web_fetchtool yet: a request with it gets a clear refusal, while Google search works. - The search limit
max_usesis accepted but not kept: Google decides how many searches to run. Every search is billed at the price above. - Site lists (
allowed_domains,blocked_domains) are not supported: a request with them gets a clear refusal.
Muse searches the web with Meta search through Messages and Responses; Chat Completions has no search. Guard translates the web_search_20250305 tool that Claude Code sends into Meta search.
{
"model": "muse-wonder-1.0",
"max_tokens": 4096,
"messages": [{"role": "user", "content": "What is new today?"}],
"tools": [{"type": "web_search_20250305", "name": "web_search"}]
}| Item | Charge |
|---|---|
| A search request | $0.0025 for each request, starting with the first |
| Before the answer | the cost of five searches (5 × $0.0025 = $0.0125) is held; the final charge uses the actual number of searches |
| Reading a page | goes through the native Meta search and is not counted as a paid search by itself |
- The native Meta search reads the pages. Muse has no separate
web_fetchtool. - The search limit
max_uses, which Claude Code sends with every search, is accepted but not kept: Meta decides how many searches to run. Every search is billed at the price above. Search from Claude Code works. - Meta does not support site lists (
allowed_domains,blocked_domains): a request with them gets a clear refusal.