SDK de Python

typesearch, el cliente oficial para Python, sincrónico y asíncrono.

pip install typesearch

Python 3.9+. Hecho sobre httpx y pydantic: cada respuesta es un modelo tipado, y los campos nuevos de una API más reciente se conservan en vez de romper tu código.

Crea un cliente

from typesearch import Typesearch

ts = Typesearch()  # lee TYPESEARCH_API_KEY
ArgumentoPor defecto
api_keyTYPESEARCH_API_KEYTu key.
base_urlhttps://api.typesearch.aiO TYPESEARCH_BASE_URL.
timeout70.0Segundos antes de cortar un pedido. Una búsqueda deep puede tardar cerca de un minuto.
max_retries2Reintentos ante errores de conexión, 429 rate_limited y 5xx.
default_headersEncabezados que van en cada pedido.
http_clientTu propio httpx.Client (o httpx.AsyncClient en asíncrono), para proxies o pruebas.

Úsalo como context manager para cerrar las conexiones al terminar: with Typesearch() as ts: ….

Buscar

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])

Los argumentos se llaman igual que en la API HTTP. Las fechas aceptan texto o datetime.date / datetime.datetime. days=None busca en todo el índice; si no pasas days, queda el valor por defecto de 7.

Varias consultas a la vez:

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

Streaming

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":
            mostrar(event.response.results)
        elif event.type == "result":
            mostrar(event.response.results)

# O sólo el resultado final
final = ts.search_stream("el dólar").final_response()

Un evento error se lanza como APIError.

Similares y contenidos

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

paginas = ts.contents(["https://www.infobae.com/economia/…"], query="el dólar")

Búsqueda en un sitio en vivo

# Crea el trabajo y espera el resultado
res = ts.site_search_and_wait("lanacion.com.ar", "el dólar", mode="normal")

# O maneja el trabajo tú
job = ts.site_search("lanacion.com.ar", "el dólar")
listo = ts.jobs.wait(job.id, poll_interval=2, timeout=120)

jobs.wait() lanza JobFailedError si el trabajo falla.

Asíncrono

AsyncTypesearch tiene los mismos métodos, con await:

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())

Errores

Todos los errores heredan de TypesearchError. Los de la API son subclases de APIError con status, code, request_id y, en pedidos inválidos, errors por campo.

ClaseCuándo
BadRequestError400
AuthenticationError401
BudgetError402: max_tokens demasiado bajo
PermissionDeniedError403
NotFoundError404
RateLimitError429, con retry_after
InternalServerError5xx
APIConnectionError · APITimeoutErrorSin respuesta, o demasiado lenta
JobFailedErrorFalló un trabajo de búsqueda en sitio
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)

Reintentos

Los errores de conexión, 429 rate_limited y 5xx se reintentan con espera exponencial y aleatoria, respetando Retry-After; quota_exceeded nunca. Usa max_retries=0 para manejarlos tú.

En esta página