Python SDK

typesearch — the official client for Python, sync and async.

pip install typesearch

Python 3.9+. Built on httpx and pydantic: every response is a typed model, and unknown fields from a newer API are kept instead of breaking your code.

Create a client

from typesearch import Typesearch

ts = Typesearch()  # reads TYPESEARCH_API_KEY
ArgumentDefault
api_keyTYPESEARCH_API_KEYYour key.
base_urlhttps://api.typesearch.aiOr TYPESEARCH_BASE_URL.
timeout70.0Seconds before a request is aborted. A deep search can take about a minute.
max_retries2Retries on connection errors, 429 rate_limited and 5xx.
default_headersHeaders sent with every request.
http_clientYour own httpx.Client (or httpx.AsyncClient for async), for proxies or tests.

Use it as a context manager to close connections when you are done: with Typesearch() as ts: ….

res = ts.search(
    "el dólar",
    mode="normal",
    max_results=10,
    include_domains=["infobae.com", "lanacion.com.ar"],
    published_after="2026-09-20",
    highlights=True,
)

for r in res.results:
    print(f"{r.score:.2f}", r.title, r.highlights[:1])

Keyword arguments have the same names as the HTTP API. Dates accept strings or datetime.date / datetime.datetime. days=None searches the whole index; leaving days out keeps the default of 7.

Several queries at once:

res = ts.search(["el dólar", "el FMI"], mode="fast")
for group in res.groups or []:
    print(group.query, group.total)

Stream

with ts.search_stream("el dólar", mode="deep") as stream:
    for event in stream:
        if event.type == "step":
            print("·", event.step.text)
        elif event.type == "partial":
            render(event.response.results)
        elif event.type == "result":
            render(event.response.results)

# Or only the final result
final = ts.search_stream("el dólar").final_response()

An error event is raised as an APIError.

Similar and contents

similar = ts.similar("https://www.lanacion.com.ar/economia/…", exclude_domains=["lanacion.com.ar"])

pages = ts.contents(["https://www.infobae.com/economia/…"], query="el dólar")
# Create the job and wait for it
res = ts.site_search_and_wait("lanacion.com.ar", "el dólar", mode="normal")

# Or handle the job yourself
job = ts.site_search("lanacion.com.ar", "el dólar")
done = ts.jobs.wait(job.id, poll_interval=2, timeout=120)

jobs.wait() raises JobFailedError if the job fails.

Async

AsyncTypesearch has the same methods, awaitable:

import asyncio
from typesearch import AsyncTypesearch

async def main():
    async with AsyncTypesearch() as ts:
        res = await ts.search("el dólar", mode="fast")
        async for event in ts.search_stream("el FMI"):
            ...

asyncio.run(main())

Errors

Every error subclasses TypesearchError. API errors are APIError subclasses with status, code, request_id and, for invalid requests, errors per field.

ClassWhen
BadRequestError400
AuthenticationError401
BudgetError402 — max_tokens too small
PermissionDeniedError403
NotFoundError404
RateLimitError429 — with retry_after
InternalServerError5xx
APIConnectionError · APITimeoutErrorNo response, or too slow
JobFailedErrorA live site search job failed
from typesearch import APIError, BadRequestError, RateLimitError

try:
    ts.search("x")
except BadRequestError as e:
    print(e.code, e.errors)
except RateLimitError as e:
    print(e.code, e.retry_after)
except APIError as e:
    print(e.status, e.code, e.request_id)

Retries

Connection errors, 429 rate_limited and 5xx are retried with exponential backoff and jitter, honouring Retry-After; quota_exceeded never is. Set max_retries=0 to handle them yourself.

On this page