Sin KYC — sin ID, sin selfie, sin documentos. Paga con criptomonedas: BTC, USDT, USDC, ETH, SOL, LTC
Idioma: Español
Obtén una clave API

Docs · Python

Ejemplos en Python: buscar, lanzar consultas en paralelo, responder con citas

Tres scripts cubren lo que necesitan la mayoría de los agentes en Python: una búsqueda con requests, muchas búsquedas a la vez con httpx y un semáforo, y un bucle corto que entrega las fuentes a un modelo de lenguaje y recibe una respuesta con citas numeradas.

Última actualización: · 5 min de lectura

Respuesta rápida

¿Cómo llamo a una API de búsqueda web para agentes de IA desde Python?

Haz un POST de la consulta a https://llmwebsearch.com/api/v1/search con requests o httpx y una clave Bearer. LLMWebSearch devuelve resultados ordenados con las 3 mejores páginas en Markdown, que puedes numerar y pasar a cualquier LLM para que responda con citas. Una búsqueda cuesta 1 crédito, desde 1,20 US$/1K búsquedas en octubre de 2026. Python 3.9+ y sin SDK. Sin KYC; paga con criptomonedas.

Lo que necesitas

Python3.9 o superior
Paquetesrequests para el script simple, httpx para el asíncrono
ClaveLLMWEBSEARCH_API_KEY en tu entorno
Para el bucle de respuestasCualquier endpoint de chat compatible con OpenAI: LLM_BASE_URL, LLM_API_KEY, LLM_MODEL
FacturaciónUn crédito paga una búsqueda: hasta 20 resultados clasificados, con las páginas de los 3 primeros leídas y devueltas como Markdown. Leer de 4 a 10 páginas pasa a 2 créditos. Una llamada que termina en error no cuesta nada

¿Cómo hago una búsqueda con requests?

Construye un cuerpo JSON con q y las opciones que necesites, haz el POST y recorre results. Revisa content_status antes de tocar content: solo los resultados marcados con ok llevan el texto de la página. El script de abajo guarda cada página leída como un archivo Markdown con el nombre de su posición, y la URL de origen en la primera línea.

search_once.py
import os
import pathlib

import requests

resp = requests.post(
    "https://llmwebsearch.com/api/v1/search",
    headers={"Authorization": "Bearer " + os.environ["LLMWEBSEARCH_API_KEY"]},
    json={"q": "how to size a postgres connection pool", "max_results": 5, "read": 3},
    timeout=60,
)
resp.raise_for_status()
data = resp.json()
out = pathlib.Path("sources")
out.mkdir(exist_ok=True)
for r in data["results"]:
    if r["content_status"] != "ok":
        print("skip", r["position"], r["content_status"], r["url"])
        continue
    path = out / f"{r['position']:02d}.md"
    path.write_text("Source: " + r["url"] + "\n\n" + r["content"], encoding="utf-8")
    print("saved", path, r["word_count"], "words")
print("credits used:", data["credits_used"])

¿Cómo hago muchas búsquedas a la vez?

Usa httpx.AsyncClient y un asyncio.Semaphore. El semáforo limita cuántas llamadas hay en curso, lo que te mantiene por debajo del límite por minuto de tu cuenta y reparte la carga. De cuatro a ocho llamadas simultáneas van bien para la mayoría de los agentes de investigación. Cada cuenta tiene un límite de llamadas por minuto, que se muestra en el panel; pídelo a soporte y se puede aumentar.

El ejemplo envía una búsqueda por subpregunta, un paso típico de un agente de investigación, y recoge las URLs de las páginas que se leyeron. Cada llamada es independiente: un fallo no detiene a las demás.

many_searches.py
import asyncio
import os

import httpx

API = "https://llmwebsearch.com/api/v1/search"
HEADERS = {"Authorization": "Bearer " + os.environ["LLMWEBSEARCH_API_KEY"]}
QUESTIONS = [
    "what is connection pooling in postgres",
    "recommended pool size per cpu core",
    "pgbouncer transaction mode limitations",
    "connection pool exhaustion symptoms",
]


async def search(client, sem, q):
    async with sem:
        resp = await client.post(API, json={"q": q, "read": 2, "max_chars": 4000})
        if resp.status_code != 200:
            return q, resp.json().get("error", {}).get("code"), []
        data = resp.json()
        read = [r["url"] for r in data["results"] if r["content_status"] == "ok"]
        return q, "ok", read


async def main():
    sem = asyncio.Semaphore(4)
    async with httpx.AsyncClient(headers=HEADERS, timeout=60) as client:
        for q, status, urls in await asyncio.gather(*(search(client, sem, q) for q in QUESTIONS)):
            print(status, q, urls)


asyncio.run(main())

¿Cómo obtengo una respuesta con citas de cualquier LLM?

Primero busca y después da al modelo fuentes numeradas y pídele que las cite. La API devuelve fuentes, no una respuesta redactada: tu propio modelo lee las páginas, escribe la respuesta y cita las URL, así eliges tú el modelo y el estilo de cita. El bucle de abajo funciona con cualquier endpoint de chat que hable el formato chat/completions compatible con OpenAI; configura su dirección, su clave y su modelo en tres variables de entorno.

Mantén el contexto bajo control. El script recorta cada fuente para que el total quede dentro de un presupuesto de unos 6,000 tokens, contando aproximadamente cuatro caracteres por token. Un resultado sin contenido se pasa como su snippet, etiquetado como tal, para que el modelo no finja que leyó la página.

answer_with_citations.py
import os

import requests

SEARCH = "https://llmwebsearch.com/api/v1/search"
KEY = os.environ["LLMWEBSEARCH_API_KEY"]
BUDGET_CHARS = 6000 * 4  # about 6,000 tokens of sources


def sources_for(question):
    resp = requests.post(SEARCH, headers={"Authorization": "Bearer " + KEY},
                         json={"q": question, "max_results": 5, "read": 3}, timeout=60)
    resp.raise_for_status()
    results = resp.json()["results"]
    share = BUDGET_CHARS // max(len(results), 1)
    blocks = []
    for i, r in enumerate(results, start=1):
        if r["content_status"] == "ok":
            body = r["content"][:share]
        else:
            body = "(snippet only) " + r["snippet"]
        blocks.append(f"[{i}] {r['title']} - {r['url']}\n{body}")
    return "\n\n".join(blocks)


def answer(question):
    prompt = ("Answer the question using only the sources below. "
              "Cite them as [1], [2] and so on. Say so if the sources do not answer it.\n\n"
              + sources_for(question) + "\n\nQuestion: " + question)
    resp = requests.post(
        os.environ["LLM_BASE_URL"].rstrip("/") + "/chat/completions",
        headers={"Authorization": "Bearer " + os.environ["LLM_API_KEY"]},
        json={"model": os.environ["LLM_MODEL"], "messages": [{"role": "user", "content": prompt}]},
        timeout=120,
    )
    resp.raise_for_status()
    return resp.json()["choices"][0]["message"]["content"]


print(answer("How should I size a Postgres connection pool?"))

¿Cuánto texto debería enviar al modelo?

El mínimo que responda a la pregunta. Tres páginas recortadas a 2,000 tokens cada una suelen superar a diez páginas completas: el modelo se centra mejor y cada respuesta cuesta menos. Baja max_chars en la propia búsqueda cuando sepas que vas a recortar, para que viajen menos datos.

Recortar desde el principio de la página funciona para la mayoría de los artículos, porque lo principal suele ir primero. Para páginas de referencia largas, divide el contenido por encabezados y quédate con las secciones cuyos títulos coincidan con la pregunta.

¿Qué debe hacer el código cuando falta una página?

Sigue adelante con las otras fuentes. Una página marcada con blocked_by_robots, blocked_by_site_policy o target_refused no se leerá en un segundo intento, así que no insistas en bucle. Una página fetch_timeout o fetch_failed puede funcionar más tarde con https://llmwebsearch.com/api/v1/extract.

Los errores HTTP son distintos: 429, 502 y 504 merecen un reintento con una pausa creciente. La página de errores tiene un helper de reintento listo.

Python: preguntas frecuentes

¿Hay un paquete pip para LLMWebSearch?

No. La API es HTTPS y JSON sin más, así que con requests o httpx tienes suficiente. Los scripts de esta página son la integración: cópialos en tu proyecto y adáptalos.

¿Puedo usar estos scripts con un modelo local?

Sí. Cualquier servidor que exponga una ruta chat/completions compatible con OpenAI funciona con el bucle de citas: configura LLM_BASE_URL con su dirección y LLM_MODEL con el nombre del modelo que espera.

¿Cómo cuento los créditos desde Python?

Suma credits_used de cada respuesta, o llama a GET https://llmwebsearch.com/api/v1/credits antes y después de un trabajo; esa llamada es gratuita.

Desde 1,20 US$/1K búsquedas · sin KYC

Obtén una clave API