# Official SDKs

> Use the official TypeScript and Python clients for typed requests, errors, retries, batches, and deepcrawl polling.

Canonical URL: https://s1.dev/docs/integrations/sdks

The official SDKs are the shortest path for application code that calls
Search1API repeatedly. They cover every endpoint in the public OpenAPI contract
and add language-native configuration, typed responses, error classes, safe
retries, and deepcrawl polling.

Use [MCP](https://s1.dev/docs/integrations/mcp) when an AI client should call Search1API as a tool.
Use an SDK when your own TypeScript or Python application makes the calls.
For AI SDK agents, use the [Search1API tools package](https://s1.dev/docs/integrations/vercel-ai-sdk)
to add search, news, and webpage reading directly to the agent's tool set.

## TypeScript

```bash
npm install @search1api/client
```

```ts
import { Search1API } from '@search1api/client';

const client = new Search1API({
  apiKey: process.env.SEARCH1API_API_KEY,
});

const response = await client.search('latest AI agent frameworks', {
  maxResults: 10,
  crawlResults: 3,
});

for (const result of response.results) {
  console.log(result.title, result.link);
}
```

The TypeScript package supports Node.js 18+ and other runtimes with a
standards-compatible `fetch` implementation.

[View the TypeScript SDK source on GitHub](https://github.com/superagents-lab/search1api-js).

## Python

```bash
pip install search1api
```

```python
from search1api import Search1API

client = Search1API()  # reads SEARCH1API_API_KEY
response = client.search(
    "latest AI agent frameworks",
    max_results=10,
    crawl_results=3,
)

for result in response["results"]:
    print(result["title"], result["link"])
```

An asynchronous client exposes the same operations:

```python
from search1api import AsyncSearch1API

async with AsyncSearch1API() as client:
    response = await client.search("latest AI agent frameworks")
```

[View the Python SDK source on GitHub](https://github.com/superagents-lab/search1api-python).

## Ask

`ask` sends a natural-language request to [`POST /ask`](https://s1.dev/docs/basic/ask) and lets
Search1API choose the engines and time window. It returns at most 10 results
ranked by relevance, and `intent` reports what was searched. A completed
request costs 5 credits, and the default timeout for `ask` is 45 seconds.

```ts
const answer = await client.ask(
  'What are developers saying about Bun 1.3 this month?'
);

console.log(answer.intent.sources, answer.intent.time_range);
for (const result of answer.results) {
  console.log(result.relevance, result.source, result.title, result.link);
}
```

```python
answer = client.ask("What are developers saying about Bun 1.3 this month?")

print(answer["intent"]["sources"], answer["intent"]["time_range"])
for result in answer["results"]:
    print(result["relevance"], result["source"], result["title"], result["link"])
```

Use `search` when you already know which engine and keywords you want.

## Maps

`maps` sends a query to [`POST /maps`](https://s1.dev/docs/basic/maps) and returns one Google Maps
page of up to 20 places. Each place has a name, place ID, and Maps link, plus
address, phone, website, rating, review count, coordinates, and opening hours
when available. A completed page costs 3 credits; `page` 2 to 6 requires
`location`.

```ts
const places = await client.maps('coffee shops', {
  location: { latitude: 40.7455, longitude: -74.0083, zoom: 15 },
  maxResults: 10,
});

for (const place of places.results) {
  console.log(place.name, place.rating, place.address);
}
```

```python
places = client.maps(
    "coffee shops",
    location={"latitude": 40.7455, "longitude": -74.0083, "zoom": 15},
    max_results=10,
)

for place in places["results"]:
    print(place["name"], place.get("rating"), place.get("address"))
```

Maps needs `@search1api/client` or `search1api` 0.5.0 or later.

## Binary Screenshot responses

The Screenshot API returns image bytes rather than a JSON object. Both SDKs
preserve the response content type and request ID alongside the binary body.

```ts
import { writeFile } from 'node:fs/promises';

const screenshot = await client.screenshot('https://example.com', {
  format: 'png',
  fullPage: true,
});

await writeFile('screenshot.png', screenshot.data);
console.log(screenshot.contentType, screenshot.requestId);
```

```python
from pathlib import Path

screenshot = client.screenshot(
    "https://example.com",
    format="png",
    full_page=True,
)

Path("screenshot.png").write_bytes(screenshot["data"])
print(screenshot["content_type"], screenshot.get("request_id"))
```

## Deepcrawl without hand-written polling

Both SDKs provide a convenience method that starts the task and waits until it
completes.

```ts
const result = await client.deepcrawl('https://example.com', { type: 'all' });
console.log(result.zipUrl);
```

```python
result = client.deepcrawl("https://example.com", type="all")
print(result["zipUrl"])
```

From version 0.6.0, both SDKs accept the scope and format options. With
`format: 'json'` the completed task carries the pages; without it the result
stays a ZIP behind `zipUrl`.

```ts
const result = await client.deepcrawl('https://hono.dev/docs/', {
  maxPages: 20,
  includePaths: ['/docs/'],
  format: 'json',
});
for (const page of result.pages ?? []) {
  console.log(page.url, page.title);
}
```

```python
result = client.deepcrawl(
    "https://hono.dev/docs/",
    max_pages=20,
    include_paths=["/docs/"],
    format="json",
)
for page in result.get("pages", []):
    print(page["url"], page["title"])
```

`pages` is left out when the result is larger than 5 MB; download `resultUrl`
instead. See [Deepcrawl](https://s1.dev/docs/advanced/deepcrawl) for the path rule syntax.

Use the separate start, status, and wait methods when the task ID needs to be
persisted by your application.

## Errors, retries, and timeouts

The SDKs expose separate errors for authentication (`401`), payment or credits
(`402`), validation (`400`/`422`), not found (`404`), rate limits (`429`), and
server failures. The status code and parsed response body remain available on
the error.

Requests use a 30-second timeout and retry `429` and transient `5xx` responses
twice by default. Authentication, payment, and validation errors are never
retried. Starting a deepcrawl task is also not retried automatically because a
lost response could otherwise create and charge a duplicate task, and
`feedback` is not retried because a retry could file a duplicate report.
Configure the defaults on the client when your workload needs a different
policy.

## API coverage

The first-party clients support search and news (single and batch), ask, maps, crawl
(single and batch), Screenshot, sitemap, trending, extract, deepcrawl,
feedback, usage, and health. The generated OpenAPI types are also exported from
the TypeScript package for applications that need the exact wire-level
contract.