DeepSeek Search API permite buscar páginas web desde una aplicación y recibir resultados estructurados con títulos, enlaces, resúmenes y otros datos de las fuentes. Se llama mediante POST https://api.deepseek.com/v1/tools/search, con una clave de DeepSeek y un cuerpo JSON.
El endpoint devuelve material para consultar, mostrar o enviar después a un modelo. La solicitud de Search no requiere elegir un modelo de generación. Si necesitas una respuesta redactada a partir de las fuentes, añade ese paso a tu aplicación.
Esta guía explica la API oficial de Search, cómo usarla con Python, cuándo conviene recuperar una página con Fetch y cómo calcular los costos de ambas operaciones.
Search, Fetch y web_search: cuál necesitas
| Opción | Qué recibe y devuelve | Cuándo usarla |
|---|---|---|
| Search API | Recibe query y devuelve una lista results. | Quieres descubrir fuentes a partir de una consulta. |
| Fetch API | Recibe una URL y devuelve título y contenido en Markdown. | Ya conoces la página que necesitas leer. |
| web_search en Responses | La herramienta busca durante una solicitud de generación y aporta resultados al contexto del modelo. | Quieres usar la integración de búsqueda documentada para Responses. |
Search y Fetch son endpoints JSON independientes. Sus esquemas no incluyen un parámetro model. En cambio, la herramienta integrada web_search de Responses está documentada para deepseek-v4-pro y se ignora con deepseek-flash, según su tabla de compatibilidad. Esa restricción no convierte al modelo Pro en un requisito del endpoint independiente de Search.
Para un buscador dentro de tu aplicación, comienza con Search. Si el usuario ya proporciona una URL concreta, puedes acudir directamente a Fetch. La elección depende de si necesitas encontrar una fuente o recuperar una que ya identificaste.

Cómo hacer una búsqueda con Python
Prepara el entorno y la clave
Necesitas una clave de la plataforma oficial de DeepSeek y Python 3.10 o superior, de acuerdo con las versiones que admite actualmente Requests. Desde la carpeta de tu proyecto, crea un entorno virtual:
python -m venv .venv
Actívalo, instala Requests y configura la clave en la misma terminal donde ejecutarás el programa. En macOS o Linux:
source .venv/bin/activate
python -m pip install requests
export DEEPSEEK_API_KEY="TU_CLAVE_DEEPSEEK"
En Windows PowerShell:
.venv\Scripts\Activate.ps1
python -m pip install requests
$env:DEEPSEEK_API_KEY="TU_CLAVE_DEEPSEEK"
Sustituye el valor de ejemplo por tu clave. El programa la leerá desde el entorno. Mantén esta llamada en tu aplicación o servidor, con la credencial fuera del código público.
Ejemplo completo: una solicitud y sus resultados
Guarda el siguiente archivo como buscar_deepseek.py. Valida la consulta, envía un único Search y muestra las fuentes recibidas. No abre las páginas ni llama a un modelo:
"""Consulta DeepSeek Search una vez y muestra sus fuentes, sin generar respuestas."""
import argparse
import os
import sys
from urllib.parse import urlsplit
import requests
from requests.adapters import HTTPAdapter
def valid_result(item):
if not isinstance(item, dict):
return False
if not all(isinstance(item.get(field), str) for field in ("title", "url", "snippet")):
return False
if any(char.isspace() or ord(char) < 32 or ord(char) == 127 for char in item["url"]):
return False
try:
url = urlsplit(item["url"])
port = url.port
return (url.scheme in ("http", "https") and bool(url.hostname)
and url.username is None and url.password is None
and (port is None or 1 <= port <= 65535))
except ValueError:
return False
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("query", help="Consulta entre comillas: de 1 a 128 caracteres.")
parser.add_argument("--count", type=int, default=5, help="Resultados solicitados: 1–50.")
args = parser.parse_args()
query = args.query.strip()
if not 1 <= len(query) <= 128:
parser.error("La consulta debe contener de 1 a 128 caracteres y no estar vacía.")
if not 1 <= args.count <= 50:
parser.error("--count debe estar entre 1 y 50.")
key = os.environ.get("DEEPSEEK_API_KEY", "").strip()
if not key:
parser.error("Falta la variable DEEPSEEK_API_KEY.")
try:
with requests.Session() as session:
session.mount("https://", HTTPAdapter(max_retries=0))
with session.post(
"https://api.deepseek.com/v1/tools/search",
headers={"Authorization": f"Bearer {key}", "Content-Type": "application/json"},
json={"query": query, "count": args.count, "need_content": False},
timeout=(5, 30), allow_redirects=False,
) as response:
if response.status_code != 200:
print(f"Error HTTP: {response.status_code}.", file=sys.stderr)
return 1
data = response.json()
except requests.exceptions.JSONDecodeError:
print("Respuesta inválida: JSONDecodeError.", file=sys.stderr)
return 1
except requests.exceptions.RequestException as error:
print(f"Error de red: {type(error).__name__}.", file=sys.stderr)
return 1
results = data.get("results") if isinstance(data, dict) else None
if not isinstance(results, list) or not all(valid_result(item) for item in results):
print("La respuesta tiene un formato de resultados inválido.", file=sys.stderr)
return 1
if not results:
print("No se encontraron resultados para esta consulta.")
return 0
for number, item in enumerate(results, start=1):
print(f"\n{number}. {item['title'] or 'Sin título'}")
print(item["url"])
print(item["snippet"] or "Sin descripción disponible.")
return 0
if __name__ == "__main__":
raise SystemExit(main())
Para buscar documentación en español, ejecuta:
python buscar_deepseek.py "entornos virtuales Python site:docs.python.org lang:es" --count 5
El programa muestra los títulos, las URLs y los fragmentos que realmente devuelva la API. Puede haber menos resultados de los solicitados. Si recibe results: [], informa que no hubo coincidencias; si falta el campo o su estructura es incorrecta, lo trata como un problema de formato.
La llamada envía Authorization: Bearer y Content-Type: application/json. El ejemplo utiliza cinco resultados y desactiva reintentos automáticos para que una ejecución no multiplique las solicitudes.
El timeout elegido es de cinco segundos para conexión y treinta para lectura. Es una configuración del ejemplo. Como explica la documentación de Requests, esos valores no representan un plazo máximo garantizado para toda la operación.
Parámetros y operadores para afinar la búsqueda
Qué puedes enviar en el cuerpo JSON
La referencia de Search documenta estos campos:
| Parámetro | Uso y límites |
|---|---|
query | Obligatorio: de 1 a 128 caracteres Unicode; no puede contener solo espacios. |
count | Entero de 1 a 50. Si lo omites, se solicitan 10 resultados. |
ori_question | Pregunta original opcional, también de 1 a 128 caracteres. null equivale a omitirla. |
localization | Dirección IP opcional para localizar los resultados; su valor predeterminado es una cadena vacía. |
need_content | Booleano, false por defecto. Solicita contenido de las páginas cuando se establece en true. |

ori_question ayuda a aportar la pregunta que originó la búsqueda, pero no evita el límite de longitud. Si el usuario escribe una pregunta extensa, tu aplicación debe convertirla en una consulta breve y útil antes de enviarla.
localization espera una IP, no un valor como es o MX. Para filtrar por idioma, utiliza lang: dentro de query. Los campos desconocidos del cuerpo se ignoran: un HTTP 200 no confirma que un filtro inventado haya tenido efecto.
Ejemplos de consultas en español y filtros por fuente
Los operadores forman parte de la cadena query y cuentan para su longitud total. Estos ejemplos utilizan la sintaxis publicada por DeepSeek:
| Objetivo | Ejemplo de query |
|---|---|
| Buscar en español | entornos virtuales Python lang:es |
| Limitar la búsqueda a documentación oficial | venv site:docs.python.org lang:es |
| Permitir dos sitios | DeepSeek site:api-docs.deepseek.com OR site:github.com |
| Buscar una frase exacta | Python "gestores de contexto" lang:es |
| Acotar por fechas de publicación | DeepSeek Search API after:2026-10-01 before:2026-11-01 |
| Excluir un término | Python tutorial -video lang:es |
También puedes excluir sitios con -site: o frases con -"frase". Si una consulta devuelve una lista vacía, simplifica los filtros de forma controlada: primero revisa la frase y el sitio, después el idioma o las fechas. Cambiar una condición a la vez permite identificar cuál estaba limitando la búsqueda.
Cómo interpretar results y elegir una fuente
Una respuesta válida contiene una lista results. Antes de mostrar una respuesta al usuario o pasar contenido a un modelo, distingue los campos que vas a utilizar:
| Campo | Uso práctico |
|---|---|
title y url | Identificar la fuente y conservar un enlace comprobable. |
snippet | Mostrar un fragmento breve relacionado con la consulta. |
summary | Evaluar un resumen más amplio antes de recuperar o procesar la página. |
content | Leer el contenido disponible de la página. Puede estar vacío. |
date, site_name y site_icon | Añadir metadatos cuando estén disponibles; pueden ser null. |

La fecha documentada corresponde a publicación en UTC con formato RFC 3339. Si es desconocida, conserva esa ausencia. Sustituirla por la fecha de tu consulta haría parecer reciente una fuente cuya antigüedad no conoces.
La referencia de resultados incluye rerank_score, de 0 a 3, y authority, de 0 a 4, con -1 para autoridad desconocida. Son señales de clasificación del proveedor. Úsalas para priorizar la revisión junto con el dominio, la fecha y la relación con la pregunta; no demuestran por sí solas que una afirmación sea correcta.
Cuando necesites citar un pasaje literalmente o comprobar un dato importante, revisa el contenido de la fuente. Conserva la URL junto con el texto utilizado. Un resumen de Search sirve para seleccionar material, pero no debe presentarse automáticamente como una cita literal de la página.
Cuándo usar need_content y cuándo llamar a Fetch
| Lo que necesitas | Ruta adecuada |
|---|---|
| Títulos, enlaces y fragmentos | Search con need_content: false. |
| Resúmenes para elegir fuentes | Revisa summary en los resultados de Search. |
| Texto de páginas dentro de la búsqueda | Solicita need_content: true y comprueba si content tiene contenido. |
| Una página cuya URL ya conoces | Llama directamente a Fetch. |
| Leer solo algunas fuentes encontradas | Selecciona sus URLs y usa Fetch cuando necesites recuperar su contenido. |
Con need_content: false, content está vacío por definición. Con true, también puede quedar vacío si no está disponible. Si el texto recibido ya cubre lo que necesitas, puedes utilizarlo sin realizar otra recuperación. Si necesitas más contenido, Fetch es una operación adicional, sujeta a disponibilidad y a las políticas de acceso del sitio.
Ejemplo de Fetch con una URL conocida
Fetch utiliza POST https://api.deepseek.com/v1/tools/fetch y recibe url. La dirección debe usar HTTP o HTTPS, incluir un host, tener como máximo 8 192 caracteres y no contener usuario ni contraseña, según la referencia oficial de Fetch.
En una terminal compatible con Bash y con curl instalado, puedes consultar esta URL de documentación después de configurar la clave:
curl --request POST --fail --silent --show-error \
--connect-timeout 5 --max-time 30 \
"https://api.deepseek.com/v1/tools/fetch" \
-H "Authorization: Bearer $DEEPSEEK_API_KEY" \
-H "Content-Type: application/json" \
--data '{"url":"https://api-docs.deepseek.com/api/search/"}'
Este comando realiza un Fetch independiente del ejemplo Python. La respuesta documentada contiene title y content en Markdown. El título puede estar vacío. Guarda también la URL que enviaste, porque esos dos campos no sustituyen el registro de la fuente.

Que una URL aparezca en Search no garantiza que Fetch pueda extraerla. Una página inaccesible, bloqueada o con contenido no extraíble puede requerir que elijas otra fuente. Comprueba el resultado antes de incorporarlo a una respuesta.
Precios, facturación y límites de Search y Fetch
Qué solicitudes se cobran
La tabla oficial de precios publica estas tarifas en dólares estadounidenses (USD):
| Operación | Precio por 1 000 solicitudes exitosas | Equivalente por solicitud exitosa |
|---|---|---|
| Search | $0.75 | $0.00075 |
| Fetch | $0.75 | $0.00075 |

La regla de facturación exige HTTP 200 y un resultado: una lista results no vacía en Search o contenido de página en Fetch. Los fallos, las búsquedas vacías y los timeouts del servicio no se facturan. count cambia cuántos resultados solicitas, no el precio de esa búsqueda.
Las llamadas a Search y Fetch realizadas al usar la API de DeepSeek desde DeepSeek Harness, Claude Code o Codex también se cobran por solicitud exitosa, según la documentación actual. Una instrucción a un agente puede desencadenar varias búsquedas y lecturas.
Ejemplo hipotético del costo de una tarea
Supón 1 000 tareas, cada una con un Search y dos Fetch, y que todas esas operaciones devuelven datos facturables:
- 1 000 búsquedas: $0.75.
- 2 000 recuperaciones de páginas: $1.50.
- Total de Search y Fetch: $2.25.
Es un cálculo ilustrativo, no un resultado observado ni una tarifa plana por tarea. Si después envías el material a un modelo para redactar una respuesta, añade su consumo de tokens. El número de resultados solicitados tampoco indica cuántas páginas necesitas recuperar: selecciona las que aporten información útil.
Cuántas solicitudes admite la cuenta
La guía vigente establece límites independientes de 100 solicitudes por segundo para Search y 25 para Fetch. Se calculan por cuenta, compartidos entre sus claves API, y son distintos de los límites de concurrencia de los modelos. Fetch tiene además un límite por dominio cuyo valor no se especifica en esa guía.
Controla Search y Fetch por separado en la cola de tu aplicación. Crear más claves dentro de la misma cuenta no amplía estos límites. Si aparece HTTP 429, reduce el ritmo y evita que varios procesos reintenten al mismo tiempo.
Errores frecuentes y reintentos
Utiliza los errores específicos de Search y Fetch para decidir el siguiente paso:
| Estado | Qué revisar | Acción |
|---|---|---|
400 o 413 | Encabezados, JSON, valores de campos o tamaño del cuerpo. | Corrige la solicitud; revisa longitudes, tipos y cantidad de resultados. |
401 | Clave ausente o inválida. | Comprueba la variable de entorno y la clave de DeepSeek sin imprimirla. |
402 | Saldo insuficiente. | Revisa el saldo antes de volver a enviar la operación. |
403 o 404 en Fetch | Rechazo por política de seguridad o imposibilidad de obtener contenido utilizable. | Verifica la URL y considera otra fuente accesible. |
429 | Límite de QPS de Search, Fetch o dominio. | Reduce solicitudes concurrentes o su frecuencia y aplica una espera. |
408, 500 o 504 | Timeout de lectura del cuerpo, error interno o timeout de un servicio dependiente. | Reintenta con espera y un número limitado de intentos. |
DeepSeek recomienda esperar y reintentar ante 408, 429 y errores 5xx. En una aplicación, define un límite de intentos y una espera creciente para evitar multiplicar tráfico durante un problema. El ejemplo Python deja los reintentos desactivados para que puedas observar una sola solicitud.
Un timeout local de Requests significa que tu cliente dejó de esperar; no demuestra por sí solo que el servidor no haya completado la operación. Por eso, no asumas que todos los reintentos después de un timeout local serán gratuitos.
Si recibes HTTP 200 con results: [], la búsqueda terminó sin coincidencias. Revisa la consulta o informa esa ausencia al usuario. No conviertas una lista vacía en una respuesta inventada ni ocultes un formato de respuesta inválido como si fuera una búsqueda sin resultados.
Cómo integrar las fuentes en un agente o flujo RAG
Para generar una respuesta respaldada por páginas recuperadas, organiza el proceso en pasos observables:
- Busca. Convierte la pregunta en una consulta breve y conserva los resultados y sus URLs.
- Selecciona. Revisa pertinencia, fecha y procedencia; descarta duplicados y fuentes que no respondan a la pregunta.
- Recupera lo necesario. Usa el contenido ya disponible o Fetch para las páginas elegidas.
- Genera y comprueba. Envía al modelo los fragmentos relevantes con sus referencias, pide que identifique la falta de evidencia y revisa que las citas correspondan a las fuentes utilizadas.
Mantén separadas las instrucciones de tu aplicación y el texto recuperado. Conserva la asociación entre cada fragmento y su URL, para poder mostrar enlaces comprobables y rastrear qué información respaldó la respuesta.
Si eliges la búsqueda integrada de Responses, su documentación de uso de herramientas expone usage.server_tool_use.tool_search y tool_fetch. Esos valores cuentan operaciones, no tokens. Úsalos junto con el consumo del modelo para medir el costo del flujo completo, en vez de asumir que cada turno contiene una sola búsqueda.
Verificación documental: 10 de noviembre de 2026. Se revisaron las fuentes oficiales enlazadas, la sintaxis de los ejemplos y el cálculo de costos. No se ejecutaron solicitudes autenticadas a DeepSeek Search o Fetch ni se presentan resultados de búsqueda simulados como reales.

