> ## Documentation Index > Fetch the complete documentation index at: https://openrouter.ai/docs/llms.txt > Use this file to discover all available pages before exploring further. # Web Fetch > Give any model the ability to fetch content from URLs export const Template = ({children, data}) => { const replace = s => s.replace(/\{\{(\w+)\}\}/g, (_, k) => (k in data) ? data[k] : `{{${k}}}`); const leafText = node => typeof node === 'string' ? node : node?.$$typeof && typeof node.props?.children === 'string' ? node.props.children : null; const collapseTokens = nodes => { const out = []; let i = 0; while (i < nodes.length) { const ta = leafText(nodes[i]); const tb = leafText(nodes[i + 1]); const tc = leafText(nodes[i + 2]); if (ta != null && tb != null && tc != null) { const m = (ta + tb + tc).match(/^([\s\S]*)\{\{(\w+)\}\}([\s\S]*)$/); if (m && (m[2] in data)) { out.push(m[1] + data[m[2]] + m[3]); i += 3; continue; } } out.push(nodes[i]); i++; } return out; }; const process = node => { if (typeof node === 'string') return replace(node); if (Array.isArray(node)) return collapseTokens(node.map(process)); if (node && typeof node === 'object') { if (node.$$typeof) return { ...node, props: process(node.props) }; return Object.fromEntries(Object.entries(node).map(([k, v]) => [k, process(v)])); } return node; }; return <>{process(children)}; }; export const API_KEY_REF = ''; Beta **Beta** Server tools are currently in beta. The API and behavior may change. The `openrouter:web_fetch` server tool gives any model the ability to fetch content from a specific URL. When the model needs to read a web page or PDF document, it calls the tool with the URL. OpenRouter fetches and extracts the content, returning text that the model can use in its response. ## How It Works 1. You include `{ "type": "openrouter:web_fetch" }` in your `tools` array. 2. Based on the user's prompt, the model decides whether it needs to fetch a URL and generates the request. 3. OpenRouter fetches the URL using the configured engine (defaults to `auto`, which uses native provider fetch when available or falls back to [Exa](https://exa.ai)). 4. The page content (text, title, and URL) is returned to the model. 5. The model incorporates the fetched content into its response. It may fetch multiple URLs in a single request if needed. ## Quick Start ## Configuration The web fetch tool accepts optional `parameters` to customize behavior: ```json lines theme={null} { "type": "openrouter:web_fetch", "parameters": { "engine": "exa", "max_uses": 10, "max_content_tokens": 100000, "allowed_domains": ["docs.example.com"], "blocked_domains": ["private.example.com"] } } ``` | Parameter | Type | Default | Description | | -------------------- | --------- | ------- | -------------------------------------------------------------------------------------- | | `engine` | string | `auto` | Fetch engine to use: `auto`, `native`, `exa`, `openrouter`, `firecrawl`, or `parallel` | | `max_uses` | integer | N/A | Maximum fetches per request. Once exceeded, the tool returns an error | | `max_content_tokens` | integer | N/A | Maximum content length in approximate tokens. Content exceeding this is truncated | | `allowed_domains` | string\[] | N/A | Only fetch from these domains | | `blocked_domains` | string\[] | N/A | Never fetch from these domains | ## Engine Selection The web fetch server tool supports multiple fetch engines: * **`auto`** (default): Uses native fetch if the provider supports it, otherwise falls back to Exa * **`native`**: Forces the provider's built-in web fetch * **`exa`**: Uses [Exa](https://exa.ai)'s Contents API to extract page content (supports BYOK) * **`openrouter`**: Uses direct HTTP fetch with content extraction * **`firecrawl`**: Uses [Firecrawl](https://firecrawl.dev)'s scrape API (BYOK, bring your own key) * **`parallel`**: Uses [Parallel](https://parallel.ai)'s extract API for high-quality content extraction ### Engine Capabilities | Feature | Exa | Parallel | Firecrawl | OpenRouter | Native | | -------------------- | ------------------- | ----------- | --------------- | ----------- | ---------------- | | **Domain filtering** | Yes | Yes | Yes | Yes | Varies | | **Token truncation** | Yes | Yes | Yes | Yes | No | | **API key** | Server-side or BYOK | Server-side | BYOK (your key) | Server-side | Provider-handled | | **Hard limit** | None | None | None | 50/request | 50/request | ### Firecrawl (BYOK) Firecrawl uses your own API key. To set it up: 1. Go to your [OpenRouter plugin settings](https://openrouter.ai/settings/plugins) and configure your Firecrawl API key 2. Your Firecrawl account is billed separately from OpenRouter ### Hard Limits To prevent runaway costs: * **Exa engine**: No hard limit (billed via API credits) * **Parallel engine**: No hard limit (billed via API credits) * **Firecrawl engine**: No hard limit (uses your Firecrawl credits) * **OpenRouter/native engines**: Hard limit of 50 fetches per request ## Domain Filtering Restrict which domains can be fetched using `allowed_domains` and `blocked_domains`: ```json lines theme={null} { "type": "openrouter:web_fetch", "parameters": { "allowed_domains": ["docs.example.com", "api.example.com"], "blocked_domains": ["internal.example.com"] } } ``` When `allowed_domains` is set, only URLs from those domains will be fetched. When `blocked_domains` is set, URLs from those domains will be rejected. ## Content Truncation Use `max_content_tokens` to limit the amount of content returned: ```json lines theme={null} { "type": "openrouter:web_fetch", "parameters": { "max_content_tokens": 50000 } } ``` Content exceeding this limit is truncated. This is useful for controlling context window usage when fetching large pages. ## Works with the Responses API The web fetch server tool also works with the Responses API: ## Response Format When the model calls the web fetch tool, it receives a response like: ```json lines theme={null} { "url": "https://example.com/article", "title": "Article Title", "content": "The full text content of the page...", "status": "completed", "retrieved_at": "2025-07-15T14:30:00.000Z" } ``` If the fetch fails, the response includes an error: ```json lines theme={null} { "url": "https://example.com/404", "status": "failed", "error": "HTTP 404: Page not found" } ``` ## Pricing | Engine | Pricing | | -------------- | ----------------------------------------------------------- | | **Exa** | \$1 per 1,000 fetches | | **Parallel** | \$1 per 1,000 fetches | | **Firecrawl** | Uses your Firecrawl credits directly (no OpenRouter charge) | | **OpenRouter** | Free | | **Native** | Passed through from the provider | All pricing is in addition to standard LLM token costs for processing the fetched content. ## Next Steps * [Server Tools Overview](/docs/guides/features/server-tools). Learn about server tools * [Web Search](/docs/guides/features/server-tools/web-search). Search the web for real-time information * [Datetime](/docs/guides/features/server-tools/datetime). Get the current date and time * [Tool Calling](/docs/guides/features/tool-calling). Learn about user-defined tool calling