> ## Documentation Index
> Fetch the complete documentation index at: https://docs.arouter.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Web Search Tool

> Give models access to real-time web search. ARouter executes the search and injects structured results with citations — no client-side code required.

The `web_search` Server Tool enables models to search the web during inference. The model decides when a search is needed, ARouter performs it, and the results are injected back into the model's context automatically.

<Note>
  This is the recommended replacement for the deprecated `web` plugin and `:online` model suffix. See [Migration Guide](#migrating-from-web-plugin) below.
</Note>

## Quick Start

```json theme={null}
{
  "model": "openai/gpt-5.4",
  "messages": [
    {"role": "user", "content": "What happened in AI research this week?"}
  ],
  "tools": [
    {"type": "arouter", "arouter": {"id": "web_search"}}
  ]
}
```

<Tabs>
  <Tab title="TypeScript">
    ```typescript theme={null}
    import OpenAI from "openai";

    const client = new OpenAI({
      baseURL: "https://api.arouter.ai/v1",
      apiKey: "lr_live_xxxx",
    });

    const response = await client.chat.completions.create({
      model: "openai/gpt-5.4",
      messages: [
        { role: "user", content: "What happened in AI research this week?" }
      ],
      tools: [
        { type: "arouter", arouter: { id: "web_search" } } as any,
      ],
    });

    console.log(response.choices[0].message.content);
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    from openai import OpenAI

    client = OpenAI(
        base_url="https://api.arouter.ai/v1",
        api_key="lr_live_xxxx",
    )

    response = client.chat.completions.create(
        model="openai/gpt-5.4",
        messages=[
            {"role": "user", "content": "What happened in AI research this week?"}
        ],
        tools=[
            {"type": "arouter", "arouter": {"id": "web_search"}}
        ],
    )

    print(response.choices[0].message.content)
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={null}
    curl https://api.arouter.ai/v1/chat/completions \
      -H "Authorization: Bearer lr_live_xxxx" \
      -H "Content-Type: application/json" \
      -d '{
        "model": "openai/gpt-5.4",
        "messages": [
          {"role": "user", "content": "What happened in AI research this week?"}
        ],
        "tools": [
          {"type": "arouter", "arouter": {"id": "web_search"}}
        ]
      }'
    ```
  </Tab>
</Tabs>

***

## Configuration

Pass configuration options inside the `arouter` object:

```json theme={null}
{
  "tools": [
    {
      "type": "arouter",
      "arouter": {
        "id": "web_search",
        "max_results": 5,
        "engine": "exa",
        "include_domains": ["arxiv.org", "nature.com"],
        "exclude_domains": ["reddit.com"]
      }
    }
  ]
}
```

| Parameter           | Type       | Default | Description                                                        |
| ------------------- | ---------- | ------- | ------------------------------------------------------------------ |
| `id`                | `string`   | —       | Must be `"web_search"`                                             |
| `max_results`       | `integer`  | `5`     | Maximum number of search results to return                         |
| `engine`            | `string`   | auto    | Search engine: `"native"`, `"exa"`, `"parallel"`, or `"firecrawl"` |
| `include_domains`   | `string[]` | —       | Restrict results to these domains (supports wildcards)             |
| `exclude_domains`   | `string[]` | —       | Exclude results from these domains (supports wildcards)            |
| `max_total_results` | `integer`  | —       | Cap total results across multiple searches in one request          |

***

## Engine Selection

| Engine        | Description                                         | Best For               |
| ------------- | --------------------------------------------------- | ---------------------- |
| (unset)       | Use native if provider supports it, else Exa        | General use            |
| `"native"`    | Provider's built-in search (OpenAI, Anthropic, xAI) | Best citation quality  |
| `"exa"`       | Exa's neural+keyword hybrid search                  | Research, niche topics |
| `"parallel"`  | Parallel's search API                               | Fast broad queries     |
| `"firecrawl"` | Firecrawl deep crawl (BYOK)                         | Full page content      |

### Engine Compatibility

| Engine             | `include_domains` | `exclude_domains`                     |
| ------------------ | ----------------- | ------------------------------------- |
| Exa                | Yes               | Yes                                   |
| Parallel           | Yes               | Yes (mutually exclusive with include) |
| Native (Anthropic) | Yes               | Yes (mutually exclusive)              |
| Native (OpenAI)    | Yes               | Ignored                               |
| Native (xAI)       | Yes               | Yes (mutually exclusive, max 5 each)  |

***

## Domain Filtering

Restrict or exclude domains with optional wildcards:

```json theme={null}
{
  "tools": [
    {
      "type": "arouter",
      "arouter": {
        "id": "web_search",
        "include_domains": ["*.edu", "arxiv.org", "openai.com/blog"],
        "exclude_domains": ["reddit.com", "quora.com"]
      }
    }
  ]
}
```

***

## Parsing Citations

Web search results are returned in `annotations` on the assistant message:

```json theme={null}
{
  "choices": [
    {
      "message": {
        "role": "assistant",
        "content": "According to recent research, [arxiv.org](https://arxiv.org/abs/...) ...",
        "annotations": [
          {
            "type": "url_citation",
            "url_citation": {
              "url": "https://arxiv.org/abs/2501.12345",
              "title": "Scaling Laws for LLMs",
              "content": "We study the relationship between...",
              "start_index": 32,
              "end_index": 96
            }
          }
        ]
      }
    }
  ]
}
```

***

## Usage Tracking

Each web search invocation is tracked:

```json theme={null}
{
  "usage": {
    "prompt_tokens": 320,
    "completion_tokens": 180,
    "total_tokens": 500,
    "cost": 0.0045,
    "server_tool_calls": {
      "web_search": 1
    }
  }
}
```

***

## Pricing

| Engine                          | Cost                          |
| ------------------------------- | ----------------------------- |
| Exa                             | \$4.00 per 1,000 results      |
| Parallel                        | \$4.00 per 1,000 results      |
| Native (OpenAI, Anthropic, xAI) | Pass-through at provider rate |
| Firecrawl                       | BYOK — your Firecrawl API key |

With the default `max_results: 5`, an Exa search costs \$0.02 per invocation. Search costs are charged in addition to normal LLM token costs.

***

## Migrating from Web Plugin

If you previously used the `web` plugin or `:online` suffix, migration is straightforward:

**Before (deprecated):**

```json theme={null}
{
  "model": "openai/gpt-5.4:online",
  "messages": [{"role": "user", "content": "Latest AI news"}]
}
```

```json theme={null}
{
  "model": "openai/gpt-5.4",
  "plugins": [{"id": "web", "max_results": 3}],
  "messages": [{"role": "user", "content": "Latest AI news"}]
}
```

**After (recommended):**

```json theme={null}
{
  "model": "openai/gpt-5.4",
  "tools": [
    {"type": "arouter", "arouter": {"id": "web_search", "max_results": 3}}
  ],
  "messages": [{"role": "user", "content": "Latest AI news"}]
}
```

The key behavioral difference: the plugin always runs web search on every request, while the Server Tool lets the model decide whether a search is warranted for the given query.

***

## Next Steps

* [Datetime Tool](/en/guides/features/server-tools/datetime) — Inject current time into model context
* [Server Tools Overview](/en/guides/features/server-tools/overview) — All available server tools
* [Web Search Plugin (Deprecated)](/en/guides/features/web-search) — Legacy plugin documentation
