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

# titan_search

> Discover web URLs for a query across major search platforms, with structured search operators and normalized organic results.

Use `titan_search` when your agent has a question but not the URLs. It returns **metadata-only** organic results—ranked URLs, titles, and snippets. To read the pages, follow up with [`titan_fetch`](/docs/mcp/tools/titan-fetch).

**Required scope:** `mcp:search`

## Parameters

<ParamField body="query" type="string" required>
  The search query. Raw search operators you type here (`"exact phrase"`, `-excluded`, `OR`) are passed through to the provider.
</ParamField>

<ParamField body="search_provider" type="string">
  Identifier of the search platform to query. Call [`titan_list_templates`](/docs/mcp/tools/titan-list-templates) with `action_type: "search"` to see the platforms available to your account. Defaults to the platform default when omitted.

  Selection is explicit—there is no automatic fallback to a different platform if one fails.
</ParamField>

<ParamField body="max_results" type="integer" default="10">
  Results to return, up to 100. Requesting more than you will read wastes time, not credits: search bills per run, not per result.
</ParamField>

<ParamField body="operator_mode" type="string" default="raw_and_structured">
  How to combine `query` with the structured fields below.

  * `raw` — send `query` untouched, ignore structured fields
  * `structured` — build the query from structured fields only
  * `raw_and_structured` — combine both
</ParamField>

<ParamField body="include_domains" type="string[]">
  Restrict results to these domains. Compiles to `site:` operators.
</ParamField>

<ParamField body="exclude_domains" type="string[]">
  Remove these domains from results. Compiles to `-site:` operators.
</ParamField>

<ParamField body="file_types" type="string[]">
  Restrict to file extensions, for example `["pdf"]`. Compiles to `filetype:`.
</ParamField>

<ParamField body="title_terms" type="string[]">
  Require terms in the page title. Compiles to `intitle:`.
</ParamField>

<ParamField body="url_terms" type="string[]">
  Require terms in the URL. Compiles to `inurl:`.
</ParamField>

<ParamField body="country" type="string">
  Two-letter country code for regional results, for example `us` or `de`.
</ParamField>

<ParamField body="language" type="string">
  Language code for results, for example `en` or `fr`.
</ParamField>

<ParamField body="freshness" type="string">
  Recency filter: `any`, `day`, `week`, `month`, or `year`.
</ParamField>

<ParamField body="wait_for_completion" type="boolean" default="true">
  Wait for results inside the call. Set `false` to receive a `run_id` immediately.
</ParamField>

<ParamField body="timeout_seconds" type="integer" default="30">
  Seconds to wait, capped at 30.
</ParamField>

<ParamField body="idempotency_key" type="string">
  Deduplicate repeated calls for 24 hours. See [Idempotency and retries](/docs/mcp/idempotency-and-retries).
</ParamField>

## Operator support

Search platforms differ in which operators they accept. Unsupported fields are **dropped, not rejected**—your search still runs, and each dropped field is reported in `warnings` with code `operator_unsupported` naming exactly what was removed.

Quoted phrases, `-term` exclusions, `OR` alternation, `include_domains`, and `exclude_domains` work everywhere. Support for `file_types`, `title_terms`, `url_terms`, `country`, `language`, and `freshness` varies.

<Tip>
  If your query depends on a specific operator, run it once and check `warnings`. An empty `warnings` array means every field you sent was applied.
</Tip>

## Example

Find recent PDFs on a specific domain:

```json theme={null}
{
  "query": "annual report",
  "search_provider": "brave",
  "max_results": 10,
  "include_domains": ["sec.gov"],
  "file_types": ["pdf"],
  "freshness": "year"
}
```

## Response

```json theme={null}
{
  "run_id": "9f1c2e84-5b3a-4d7e-8c19-2a6f0b4d7e31",
  "status": "completed",
  "results": [
    {
      "url": "https://www.sec.gov/files/annual-report-2026.pdf",
      "final_url": "https://www.sec.gov/files/annual-report-2026.pdf",
      "display_url": "sec.gov › files",
      "title": "Annual Report 2026",
      "snippet": "The agency's fiscal year results and outlook...",
      "rank": 1,
      "source": "brave",
      "search_provider": "brave",
      "target_platform": "brave",
      "query": "annual report filetype:pdf site:sec.gov",
      "result_type": "organic",
      "retrieved_at": "2026-07-27T09:14:22Z",
      "metadata": {}
    }
  ],
  "usage": {
    "backend_execution_id": "9f1c2e84-5b3a-4d7e-8c19-2a6f0b4d7e31",
    "billing_unit": "successful_delivery",
    "records_returned": 10,
    "records_available": 10,
    "credits_estimated": 1,
    "billing_status": "billable"
  },
  "warnings": [],
  "request_id": "req_8f3a1c9e2b7d4056"
}
```

### Result fields

| Field             | Meaning                                                    |
| ----------------- | ---------------------------------------------------------- |
| `url`             | The result URL                                             |
| `final_url`       | Canonical URL after redirects, when different              |
| `display_url`     | Breadcrumb-style URL as the provider displays it           |
| `title`           | Result title                                               |
| `snippet`         | Provider-supplied summary text                             |
| `rank`            | Position in the result list, starting at 1                 |
| `search_provider` | Provider that returned it                                  |
| `query`           | The compiled query actually sent, after operator expansion |
| `result_type`     | `organic` or `ad`                                          |
| `retrieved_at`    | RFC 3339 timestamp                                         |
| `metadata`        | Provider-specific extras                                   |

<Note>
  Inspect `query` in the response to see exactly how your structured fields compiled. That is the fastest way to debug a search that returned nothing useful.
</Note>

## Credits

**One credit per search run**, regardless of how many results you request. A search that completes and confidently returns zero organic results is still billable—it delivered a valid answer. A search that is blocked, rate-limited, or times out with no records is not billed.

See [Credits and usage](/docs/mcp/credits-and-usage).

## Warnings you may see

| Code                   | Meaning                                                     |
| ---------------------- | ----------------------------------------------------------- |
| `operator_unsupported` | A field was dropped for this provider; the search still ran |
| `provider_no_results`  | The search completed with zero organic results              |
| `next_step`            | The run outlived the wait window; call `titan_get_run`      |

## Common patterns

**Narrow to a source you trust**

```json theme={null}
{ "query": "changelog", "include_domains": ["kubernetes.io"], "freshness": "month" }
```

**Exclude noise**

```json theme={null}
{ "query": "postgres tuning", "exclude_domains": ["pinterest.com", "quora.com"] }
```

**Find documents, not pages**

```json theme={null}
{ "query": "security whitepaper", "file_types": ["pdf"], "search_provider": "brave" }
```

## Next steps

* [titan\_fetch](/docs/mcp/tools/titan-fetch) — read the pages you discovered
* [Research agent example](/docs/mcp/examples/research-agent) — search and fetch as one pipeline
* [Errors and warnings](/docs/mcp/errors-and-warnings)
