# TinyFish

Ranked web sources in normalized search, with separate native search, fetch, browser, and agent operations.

Canonical: https://searchsdk.dev/docs/providers/tinyfish
Markdown: https://searchsdk.dev/docs/providers/tinyfish.md

<a id="overview"></a>

## Normalized search

> **TypeScript reference**
> The API names, code and policy behavior in this article describe the TypeScript SDK. See [your language guide](https://searchsdk.dev/docs/sdks) for its supported surface and limits.

Normalized search requests page zero and `domain_type=web`. It preserves result titles, links, and snippets in order. Position is not a relevance score. Unreported usage remains `null`.

**tinyfish-search.ts · server**

```typescript
import { createSearch } from '@belweave/search-sdk';
import { tinyfish } from '@belweave/search-sdk/tinyfish';

const apiKey = process.env.TINYFISH_API_KEY;
if (!apiKey) throw new Error('TINYFISH_API_KEY is required');

const client = createSearch({ provider: tinyfish({ apiKey }) });
const response = await client.web.search({
  query: 'SQLite write concurrency',
  limit: 5,
});
console.log(response.results, response.attempts);
```

The normalized adapter performs one request without a native count parameter or automatic pagination. Provider totals are not a promise that the SDK can return the requested number. Native search options and browser execution are separate operations.

100 include / 100 exclude under a conservative SDK policy; this is not a verified native maximum.

<a id="native-client"></a>

## Provider-native client

**tinyfish-native.ts · server**

```typescript
import { createTinyfishClient } from '@belweave/search-sdk/native-tinyfish';

const apiKey = process.env.TINYFISH_API_KEY;
if (!apiKey) throw new Error('TINYFISH_API_KEY is required');

const client = createTinyfishClient({ apiKey, timeoutMs: 10_000 });
const response = await client.search({ query: { query: 'SQLite write concurrency', domain_type: 'web', page: 0 } });
console.log(response.data, response.metadata);
```

Read provider data from `response.data` and sanitized transport details from `response.metadata`. Native TypeScript response types are not runtime schema validation. Preserve the operation's native response and source identities.

<a id="operations"></a>

## Native operation inventory

Methods available on this native client. Paths are relative to each operation's fixed base; a provider may use more than one origin. Eligible operations retry only when you opt into a client retry policy.

| Method | HTTP / relative path | Response / retry eligibility |
| --- | --- | --- |
| `runSse` | `POST /v1/automation/run-sse` | SSE stream · no automatic retry |
| `run` | `POST /v1/automation/run` | json · no automatic retry |
| `runAsync` | `POST /v1/automation/run-async` | json · no automatic retry |
| `runBatch` | `POST /v1/automation/run-batch` | json · no automatic retry |
| `listRuns` | `GET /v1/runs` | json · eligible |
| `batchGetRuns` | `POST /v1/runs/batch` | json · no automatic retry |
| `batchCancelRuns` | `POST /v1/runs/batch/cancel` | json · no automatic retry |
| `getRunById` | `GET /v1/runs/{id}` | json · eligible |
| `cancelRunById` | `POST /v1/runs/{id}/cancel` | json · no automatic retry |
| `getStepScreenshot` | `GET /v1/runs/{id}/steps/{stepId}/screenshot` | bytes · eligible |
| `getStepHtml` | `GET /v1/runs/{id}/steps/{stepId}/html` | text · eligible |
| `listBrowserContextProfiles` | `GET /v1/profiles` | json · eligible |
| `createBrowserContextProfile` | `POST /v1/profiles` | json · no automatic retry |
| `getBrowserContextProfile` | `GET /v1/profiles/{profileId}` | json · eligible |
| `updateBrowserContextProfile` | `PATCH /v1/profiles/{profileId}` | json · no automatic retry |
| `deleteBrowserContextProfile` | `DELETE /v1/profiles/{profileId}` | json · no automatic retry |
| `createBrowserContextProfileSetupSession` | `POST /v1/profiles/{profileId}/setup-session` | json · no automatic retry |
| `cancelBrowserContextProfileSetupSession` | `POST /v1/profiles/{profileId}/setup-session/cancel` | json · no automatic retry |
| `saveBrowserContextProfileSetupSession` | `POST /v1/profiles/{profileId}/save` | json · no automatic retry |
| `uploadBrowserContextProfileState` | `POST /v1/profiles/{profileId}/upload` | json · no automatic retry |
| `deleteBrowserContextProfileDomain` | `DELETE /v1/profiles/{profileId}/domains/{domain}` | json · no automatic retry |
| `connectVault` | `POST /v1/vault/connections` | json · no automatic retry |
| `listVaultConnections` | `GET /v1/vault/connections` | json · eligible |
| `disconnectVault` | `DELETE /v1/vault/connections/{connectionId}` | json · no automatic retry |
| `listVaultItems` | `GET /v1/vault/items` | json · eligible |
| `syncVaultItems` | `POST /v1/vault/items/sync` | json · no automatic retry |
| `getWallet` | `GET /v1/wallet` | json · eligible |
| `topUpWallet` | `POST /v1/wallet/top-up` | json · no automatic retry |
| `search` | `GET /` | json · eligible |
| `listSearchUsage` | `GET /usage` | json · eligible |
| `fetchUrls` | `POST /` | json · no automatic retry |
| `listFetchUsage` | `GET /usage` | json · eligible |
| `createBrowserSession` | `POST /` | json · no automatic retry |
| `listBrowserUsage` | `GET /usage` | json · eligible |
| `deleteBrowserSession` | `DELETE /{sessionId}` | text · no automatic retry |
| `createMonitor` | `POST /v1/monitors` | json · no automatic retry |
| `listMonitors` | `GET /v1/monitors` | json · eligible |
| `getMonitor` | `GET /v1/monitors/{id}` | json · eligible |
| `updateMonitor` | `PATCH /v1/monitors/{id}` | json · no automatic retry |
| `deleteMonitor` | `DELETE /v1/monitors/{id}` | json · no automatic retry |
| `runMonitor` | `POST /v1/monitors/{id}/runs` | json · no automatic retry |
| `runResearch` | `POST /v1/automation/run-research` | SSE stream · no automatic retry |
| `startResearchAsync` | `POST /v1/automation/run-research-async` | json · no automatic retry |
| `streamResearchEvents` | `GET /v1/research-run/{research_run_id}/events` | SSE stream · no automatic retry |
| `listResearchRuns` | `GET /v1/research-run` | json · eligible |
| `getResearchRun` | `GET /v1/research-run/{research_run_id}` | json · eligible |
| `cancelResearchRun` | `POST /v1/research-run/{research_run_id}/cancel` | json · no automatic retry |

<a id="lifecycle"></a>

## Limits and operation lifecycle

- Pass `signal` and per-call `timeoutMs` on native request input when needed.
- Persist a returned job identifier before explicitly reading or polling the same job. Native clients do not automatically poll.
- SSE data is incremental provider event text. Parse and validate terminal or error events according to the provider contract; there is no reconnect or replay.
- Native operations may create, delete, ingest, or incur charges. A successful HTTP response is not proof that a remote job completed.

<a id="sources"></a>

## Official sources

Use the official reference for current schemas, account access, and operation-specific requirements.

- [Search reference](https://docs.tinyfish.ai/search-api/reference)
- [Search examples](https://docs.tinyfish.ai/search-api/examples)
- [Full documentation index](https://docs.tinyfish.ai/llms.txt)

- [Native request and response reference](https://searchsdk.dev/docs/api/native-transport)
- [All providers](https://searchsdk.dev/docs/providers)
