> ## 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.

# Limits and safety

> The caps that bound every Titan MCP call, the URL safety checks applied before work starts, and how crawls stay inside their boundaries.

Agents are good at asking for more than they need. Titan bounds every call so a loose prompt cannot turn into an unbounded crawl or an unbounded bill.

## Caps

| Limit                            |            Value | Applies to                      |
| -------------------------------- | ---------------: | ------------------------------- |
| Search results per call          |              100 | `titan_search.max_results`      |
| URLs per fetch                   |              100 | `titan_fetch.urls`              |
| Characters per fetched page      | 12,000 (default) | `titan_fetch.max_chars_per_url` |
| Crawl pages                      |              100 | `titan_crawl.max_pages`         |
| Crawl depth                      |                3 | `titan_crawl.max_depth`         |
| Characters per crawled page      |  8,000 (default) | `titan_crawl.content_max_chars` |
| Synchronous wait                 |       30 seconds | `timeout_seconds` on any tool   |
| Records per `titan_get_run` page |            1,000 | `titan_get_run.limit`           |
| URLs per template run            |              100 | `titan_run_template.urls`       |

Exceeding a hard cap returns `limit_exceeded` **before** any run starts, so it costs nothing:

```json theme={null}
{
  "code": "limit_exceeded",
  "message": "max_pages exceeds hard cap of 100",
  "retryable": false
}
```

Some values clamp rather than fail—`max_results` above 100 is reduced to 100, and `timeout_seconds` above 30 is reduced to 30.

## URL safety

Every URL is validated and normalized before work begins. Rejected:

| Blocked                  | Examples                                        |
| ------------------------ | ----------------------------------------------- |
| Non-HTTP schemes         | `file://`, `ftp://`, `data:`, `javascript:`     |
| Localhost and loopback   | `localhost`, `127.0.0.1`, `::1`                 |
| Private IP ranges        | `10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16` |
| Link-local addresses     | `169.254.0.0/16`                                |
| Cloud metadata endpoints | `169.254.169.254` and equivalents               |

Rejections return `unsafe_url` and cost nothing. In `titan_fetch`, individual bad URLs land in `failed[]` while the rest of the batch proceeds; if **every** URL is rejected, the call fails and starts no run.

### Redirects are re-checked

A public URL that redirects to a private address is stopped at the redirect. Every hop passes the same checks as the original, so a redirect chain cannot be used to reach something the first URL could not.

## Crawl boundaries

Two boundaries are enforced independently of your parameters:

**Same origin.** Every URL a crawl returns is on the seed host. Cross-origin URLs are filtered out at the edge, even if a script produced them, and reported:

```json theme={null}
{
  "warnings": [
    { "code": "cross_origin_dropped", "message": "3 cross-origin records dropped at MCP edge" }
  ]
}
```

Dropped records are not billed.

**robots.txt.** Honored by default via `respect_robots_txt: true`.

## No arbitrary code

The MCP server does not accept user-supplied scripts. Extraction runs from Titan-curated templates only, and `titan_run_template` is restricted to the eight-template allowlist. An agent cannot be prompted into executing code you did not intend, because there is no path to execute code at all.

Browser cookies and credentials are likewise not accepted—agent tool calls fetch public web content.

## Rate limits

The Titan control plane applies request-rate limits per caller. If your agent runs into them, back off—the platform limiter returns `429` with reset headers.

Individual providers also rate-limit. A blocked search returns `provider_rate_limited`, which is retryable with backoff, or you can switch `search_provider`. Search providers do not fall back automatically; that choice stays yours.

See [Rate limits](/docs/about-platform/rate-limits) for the platform limits.

## Choosing limits deliberately

| Goal                                | Setting                                                    |
| ----------------------------------- | ---------------------------------------------------------- |
| Triage many pages cheaply           | `max_chars_per_url: 2000`, `only_main_content: true`       |
| Understand a site before reading it | `mode: "map"`, `max_depth: 1`                              |
| Stay inside one section             | `include_patterns` scoped to a path prefix                 |
| Keep a crawl bounded                | Leave `max_pages` at 25 and raise only if coverage is thin |
| Avoid oversized responses           | Paginate `titan_get_run` rather than setting `limit: 1000` |

## What is not covered

These limits are the agent-facing contract. Worker-side throughput, proxy fairness, and queue depth also shape how fast a run completes, but they are operational concerns rather than limits your agent can hit directly.

## Next steps

* [Errors and warnings](/docs/mcp/errors-and-warnings) — how limit and safety failures surface
* [Credits and usage](/docs/mcp/credits-and-usage) — why rejected work is free
* [Rate limits](/docs/about-platform/rate-limits) — platform request limits
