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

# For Coding Agents

> Single-page TinyFish context for Claude, Codex, Cursor, and other coding agents

This page is the shortest high-signal context dump for coding agents integrating TinyFish. **Always use the official SDKs** — they handle authentication, SSE streaming, retries, and typed responses so you don't have to.

<Note>
  For complete API reference in a single file, use [llms-full.txt](https://docs.tinyfish.ai/llms-full.txt) (218KB, includes all code examples). Note that `llms.txt` is just an index — agents should use `llms-full.txt` for full context.
</Note>

## MCP Server (Recommended for AI Assistants)

If you're running inside an MCP-compatible host (Codex, Claude Code, OpenCode, Command Code, Claude Desktop, Cursor, Windsurf, ChatGPT), connect via MCP instead of the REST API. Most hosts sign in with OAuth and need no API key management; Command Code connects with a TinyFish API key.

<Tabs>
  <Tab title="Codex">
    ```bash theme={null}
    codex mcp add tinyfish --url https://agent.tinyfish.ai/mcp
    ```
  </Tab>

  <Tab title="Claude Code">
    ```bash theme={null}
    npx -y install-mcp@latest https://agent.tinyfish.ai/mcp --client claude-code
    ```
  </Tab>

  <Tab title="OpenCode">
    ```bash theme={null}
    opencode mcp add tinyfish --url https://agent.tinyfish.ai/mcp
    ```
  </Tab>

  <Tab title="Command Code">
    ```bash theme={null}
    npx -y @tiny-fish/cli@latest connect command-code
    ```
  </Tab>

  <Tab title="ChatGPT">
    ```text theme={null}
    https://agent.tinyfish.ai/mcp/chatgpt
    ```
  </Tab>
</Tabs>

See the [MCP Integration guide](/mcp-integration) for all supported clients and available tools.

## Install the SDK

<CodeGroup>
  ```bash Python theme={null}
  pip install -U tinyfish
  ```

  ```bash TypeScript theme={null}
  npm install @tiny-fish/sdk@latest
  ```
</CodeGroup>

| API              | Typical Latency    | Suggested Timeout |
| ---------------- | ------------------ | ----------------- |
| Agent (sync)     | 15-60s             | 120s              |
| Agent (SSE)      | 15-60s (streaming) | N/A (SSE)         |
| Search           | 1-3s               | 10s               |
| Fetch            | 1-20s              | 150s              |
| Browser (create) | 10-30s             | 60s               |

*Fetch: backend timeout is 110s per URL; requests are also subject to a 120s CDN ceiling. Set client timeout to 150s to receive timeout errors cleanly.*

## Authentication

Set your API key (get one from [agent.tinyfish.ai/api-keys](https://agent.tinyfish.ai/api-keys)):

```bash theme={null}
export TINYFISH_API_KEY="your_api_key_here"
```

Both SDKs read `TINYFISH_API_KEY` from the environment automatically. See [Authentication](/authentication) for more details.

## Choose the Right TinyFish API

| API     | Use it when                                                         | Docs                                    |
| ------- | ------------------------------------------------------------------- | --------------------------------------- |
| Agent   | You want TinyFish to execute a goal on a real website               | [Agent reference](/agent-api/reference) |
| Search  | You want ranked web results for a query                             | [Search overview](/search-api)          |
| Fetch   | You want extracted page content from one or more URLs               | [Fetch overview](/fetch-api)            |
| Browser | You want a remote browser session for direct Playwright/CDP control | [Browser overview](/browser-api)        |

### Quick Decision Tree

* **Need data from a URL?** -- Agent API (goal-based extraction) or Fetch API (raw page content)
* **Need search results?** -- Search API
* **Need browser control?** -- Browser API (direct Playwright/CDP access)
* **Need logged-in state across recurring runs?** -- Create a [Browser Context Profile](/agent-api/browser-context-profiles), then run with `use_profile: true`

## Authenticated or Recurring Runs

When a task should reuse a login session, use **Browser Context Profiles** first. Do not make the agent log in from scratch every run unless the task explicitly needs a fresh browser. Browser Context Profiles are saved browser state for a site or account. They are different from `browser_profile: "lite" | "stealth"`, which only chooses the browser runtime mode.

<Steps>
  <Step title="Create and set up a profile">
    Use the [Browser Context Profiles API](/agent-api/browser-context-profiles) to create a profile, start a setup session, connect to `cdp_url` with Playwright/Puppeteer/CDP, sign in, and save with `session_id`. The dashboard setup UI is a manual helper.
  </Step>

  <Step title="Run with saved state">
    Pass `use_profile: true` to use the default profile, or add `profile_id` for a specific profile.
  </Step>

  <Step title="Repair stale sessions with Vault">
    For long-lived workflows, pair profiles with `use_vault: true` so TinyFish can sign in again when cookies expire.
  </Step>
</Steps>

<CodeGroup>
  ```python Python theme={null}
  result = client.agent.run(
      url="https://app.example.com/dashboard",
      goal="Summarize the account health dashboard.",
      use_profile=True,
      use_vault=True,
  )
  ```

  ```typescript TypeScript theme={null}
  const run = await client.agent.run({
    url: "https://app.example.com/dashboard",
    goal: "Summarize the account health dashboard.",
    use_profile: true,
    use_vault: true,
  });
  ```
</CodeGroup>

`use_profile: true` uses the default Browser Context Profile. Use `profile_id` when the user names a specific Browser Context Profile; `profile_id` requires `use_profile: true`:

<CodeGroup>
  ```python Python theme={null}
  result = client.agent.run(
      url="https://app.example.com/dashboard",
      goal="Download the latest invoice.",
      use_profile=True,
      profile_id="prof_abc123def4567890",
  )
  ```

  ```typescript TypeScript theme={null}
  const run = await client.agent.run({
    url: "https://app.example.com/dashboard",
    goal: "Download the latest invoice.",
    use_profile: true,
    profile_id: "prof_abc123def4567890",
  });
  ```
</CodeGroup>

## SDK Examples

### Agent — Streaming (Recommended)

<CodeGroup>
  ```python Python theme={null}
  from tinyfish import TinyFish, CompleteEvent

  client = TinyFish()

  with client.agent.stream(
      url="https://scrapeme.live/shop",
      goal="Extract the first 2 product names and prices. Return as JSON.",
  ) as stream:
      for event in stream:
          if isinstance(event, CompleteEvent):
              print(event.result_json)
  ```

  ```typescript TypeScript theme={null}
  import { TinyFish } from "@tiny-fish/sdk";

  const client = new TinyFish();

  const stream = await client.agent.stream({
    url: "https://scrapeme.live/shop",
    goal: "Extract the first 2 product names and prices. Return as JSON.",
  });

  for await (const event of stream) {
    if (event.type === "COMPLETE") {
      console.log(event.result);
    }
  }
  ```
</CodeGroup>

### Agent — Synchronous

<CodeGroup>
  ```python Python theme={null}
  from tinyfish import TinyFish, RunStatus

  client = TinyFish()

  result = client.agent.run(
      url="https://scrapeme.live/shop",
      goal="Extract the first 2 product names and prices. Return as JSON.",
  )
  if result.status == RunStatus.COMPLETED:
      print(result.result)
  ```

  ```typescript TypeScript theme={null}
  import { TinyFish, RunStatus } from "@tiny-fish/sdk";

  const client = new TinyFish();

  const run = await client.agent.run({
    url: "https://scrapeme.live/shop",
    goal: "Extract the first 2 product names and prices. Return as JSON.",
  });

  if (run.status === RunStatus.COMPLETED) {
    console.log(run.result);
  }
  ```
</CodeGroup>

### Search

<CodeGroup>
  ```python Python theme={null}
  result = client.search.query("web automation tools", location="US", language="en")
  print(result)
  ```

  ```typescript TypeScript theme={null}
  const result = await client.search.query({
    query: "web automation tools",
    location: "US",
    language: "en",
  });
  console.log(result);
  ```
</CodeGroup>

Use `recency_minutes` for a freshness window, `after_date` / `before_date` for calendar date filters, and `domain_type` for content category:

* `recency_minutes`: integer `1..5256000`
* `after_date` / `before_date`: `YYYY-MM-DD`
* `domain_type`: `"web"` (default) | `"news"` | `"research_paper"`
* `pub_year_min` / `pub_year_max`: integer `0..9999`, inclusive; only supported for `domain_type=research_paper`
* do not combine `recency_minutes` with date filters
* if both dates are present, `after_date <= before_date`
* if both pub\_year bounds are present, `pub_year_min <= pub_year_max`
* `after_date`, `before_date`, and `recency_minutes` are not supported for `domain_type=research_paper` — use `pub_year_min` / `pub_year_max` instead

### Fetch

<CodeGroup>
  ```python Python theme={null}
  result = client.fetch.get_contents(urls=["https://www.tinyfish.ai/"])
  print(result)
  ```

  ```typescript TypeScript theme={null}
  const result = await client.fetch.getContents({
    urls: ["https://www.tinyfish.ai/"],
  });
  console.log(result);
  ```
</CodeGroup>

Omit `ttl` for the default cache behavior. Add `ttl` only when freshness matters: set it to `0` when you want a live fetch, or to a positive number of seconds to accept cached entries younger than that window.

### Anti-Detection Mode

For sites with bot protection, add stealth mode and a proxy:

<CodeGroup>
  ```python Python theme={null}
  from tinyfish import TinyFish, BrowserProfile, ProxyConfig, ProxyCountryCode

  client = TinyFish()

  result = client.agent.run(
      url="https://protected-site.com",
      goal="Extract pricing data. Return as JSON.",
      browser_profile=BrowserProfile.STEALTH,
      proxy_config=ProxyConfig(enabled=True, country_code=ProxyCountryCode.US),
  )
  ```

  ```typescript TypeScript theme={null}
  import { TinyFish, BrowserProfile, ProxyCountryCode } from "@tiny-fish/sdk";

  const client = new TinyFish();

  const run = await client.agent.run({
    url: "https://protected-site.com",
    goal: "Extract pricing data. Return as JSON.",
    browser_profile: BrowserProfile.STEALTH,
    proxy_config: {
      enabled: true,
      country_code: ProxyCountryCode.US,
    },
  });
  ```
</CodeGroup>

## Expected Latency

| API              | Typical Latency    | Suggested Timeout |
| ---------------- | ------------------ | ----------------- |
| Agent (sync)     | 15-60s             | 120s              |
| Agent (SSE)      | 15-60s (streaming) | N/A (SSE)         |
| Search           | 1-3s               | 10s               |
| Fetch            | 1-20s              | 150s              |
| Browser (create) | 10-30s             | 60s               |

## Prompting

Goal quality determines success rate. Vague goals like "get the data" fail; crafted goals with explicit fields, output format, and edge-case handling succeed consistently.

<Tip>
  See the full [Prompting Guide](/prompting-guide) for tested patterns, templates, and examples.
</Tip>

## Common Gotchas

1. **Browser API session creation takes 10-30s** -- set `timeout=60` on your HTTP client.
2. **TypeScript needs `"type": "module"`** in `package.json` for top-level `await`, or wrap code in `async function main() { ... }; main()`.
3. **`COMPLETED` status does not mean the goal succeeded** -- always check `result_json` for failure signals like "captcha", "blocked", or "access denied".
4. **Fetch API has a 110s per-URL backend timeout** — requests are also subject to a 120s CDN ceiling for the full batch. Set your client timeout to at least 150s.

<Accordion title="Raw API Endpoints (cURL)">
  If you can't use the SDKs, here are the raw endpoints. All use the `X-API-Key` header for authentication.

  ### Agent

  ```bash theme={null}
  curl -N -X POST https://agent.tinyfish.ai/v1/automation/run-sse \
    -H "X-API-Key: $TINYFISH_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "url": "https://scrapeme.live/shop",
      "goal": "Extract the first 2 product names and prices. Return JSON."
    }'
  ```

  ### Search

  ```bash theme={null}
  curl "https://api.search.tinyfish.ai?query=web+automation+tools&location=US&language=en" \
    -H "X-API-Key: $TINYFISH_API_KEY"
  ```

  ### Fetch

  ```bash theme={null}
  curl -X POST https://api.fetch.tinyfish.ai \
    -H "X-API-Key: $TINYFISH_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"urls": ["https://www.tinyfish.ai/"]}'
  ```

  ### Browser

  ```bash theme={null}
  curl -X POST https://api.browser.tinyfish.ai \
    -H "X-API-Key: $TINYFISH_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"url": "https://www.tinyfish.ai"}'
  ```
</Accordion>

## What to Read Next

<CardGroup cols={2}>
  <Card title="Agent reference" icon="sparkles" href="/agent-api/reference">
    Goal-based automation, endpoint choice, runs, profiles, and proxies
  </Card>

  <Card title="Authentication" icon="key" href="/authentication">
    API key setup and troubleshooting
  </Card>

  <Card title="Search overview" icon="magnifying-glass" href="/search-api">
    Search query parameters and result shape
  </Card>

  <Card title="Fetch overview" icon="bolt" href="/fetch-api">
    Fetch multiple URLs and choose output formats
  </Card>

  <Card title="Browser overview" icon="browser" href="/browser-api">
    Create a remote browser session and connect via CDP
  </Card>

  <Card title="Examples" icon="code" href="/examples/scraping">
    Copy-paste examples for common workflows
  </Card>

  <Card title="llms-full.txt" icon="file-lines" href="https://docs.tinyfish.ai/llms-full.txt">
    Complete API reference in a single file (218KB)
  </Card>
</CardGroup>
