CrawlForge MCP
Herramienta BásicaHandles de resultado1 credit

read_result

Lea un resultado que era demasiado grande para devolverse en línea. Cuando el JSON de una herramienta supera max_inline_chars, su respuesta incluye un preview, un result_handle y truncated: true; pase ese handle aquí para recortar el texto, buscar en él, recorrerlo por líneas o leer una sola ruta JSON, sin volver a descargar la página ni pagar de nuevo el precio de la herramienta.

Casos de uso

Encontrar la sección que necesita

Ejecute un search con un encabezado o una frase y después un slice desde el offset de la coincidencia: dos llamadas que leen una sección de una página larga en lugar del resultado entero.

Recorrer textos largos

lines devuelve una ventana de líneas con has_more, de modo que un documento markdown grande se lee en ventanas que su contexto puede contener.

Extraer un solo campo de un JSON grande

json_path lee una única ruta de un resultado almacenado de crawl_deep, batch_scrape o deep_research, o del cuerpo analizado de un fetch_url en JSON.

Nunca volver a descargar

El resultado almacenado es el que ya pagó. Leerlo cuesta 1 credit por llamada; volver a ejecutar la herramienta cuesta su precio completo y vuelve a visitar el sitio.

Endpoint

POST/api/v1/tools/read_result
Auth Required
1 req/s en el plan Free
1 credit

Parameters

handle procede de una respuesta con truncated: true: esta herramienta nunca descarga una página, solo lee un resultado que usted ya tiene. Un handle caduca 1 hora después de almacenarse el resultado.
NameTypeRequiredDefaultDescription
handle
stringRequired-
El `result_handle` de una respuesta truncada (`res_` seguido de un UUID). Solo puede leerlo la cuenta que lo creó, durante 1 hora.
Example: res_9f2c1e6a-4b7d-4c3e-8a5f-1d2e3f4a5b6c
operation
stringRequired-
`slice` devuelve un rango de caracteres de la vista de texto; `search` busca una subcadena literal sin distinguir mayúsculas (nunca una expresión regular) y devuelve cada coincidencia con contexto; `lines` devuelve una ventana de líneas; `json_path` lee una ruta del JSON almacenado.
Example: search
offset
numberOptional0
`slice`: primer carácter que se devuelve. `lines`: índice de la primera línea que se devuelve.
Example: 18240
length
numberOptional10000
`slice`: número de caracteres que se devuelven (10.000 por defecto). `lines`: número de líneas que se devuelven (200 por defecto, 5.000 como máximo).
Example: 4000
query
stringOptional-
Solo para `search`, y obligatorio ahí: el texto literal que se busca, sin distinguir mayúsculas.
Example: rate limits
max_matches
numberOptional20
`search`: número máximo de coincidencias devueltas, 1-100. `truncated: true` en la respuesta indica que hubo más coincidencias de las devueltas.
Example: 5
path
stringOptional-
Solo para `json_path`, y obligatorio ahí: claves con puntos e índices de array, en forma de puntos o de corchetes (`pages.0.url` o `pages[0].url`); sin comodines, filtros ni rangos. Se lee del objeto de resultado almacenado, o del cuerpo analizado cuando el texto almacenado es JSON, como el cuerpo de un `fetch_url`.
Example: pages.0.url
max_inline_chars
numberOptional40000
Cantidad máxima de texto que se devuelve en línea, de 1.000 a 10.000.000 caracteres; cada operación limita ahí el texto que devuelve. En `json_path`, un `value` mayor llega como `value: null` con un `preview`, `truncated: true` y un aviso para acotar la ruta.
Example: 40000

Operaciones

Cada respuesta incluye handle, tool, operation, view, view_path, total_chars y expires_at, seguidos de los campos de la operación solicitada.

slice
Un rango de caracteres de la vista de texto: offset, length, text y has_more. Por defecto, los primeros 10.000 caracteres.
search
Coincidencia literal de subcadena sin distinguir mayúsculas, nunca una expresión regular: query, matches (cada una con offset, length, context_offset y context, 200 caracteres a cada lado), total_matches y truncated.
lines
Una ventana de líneas: first_line, line_count, total_lines, char_offset, lines y has_more. offset es el índice de la primera línea y length el número de líneas (200 por defecto, 5.000 como máximo).
json_path
Una ruta del objeto de resultado almacenado: path, value y value_chars. Por encima de max_inline_chars, el valor se sustituye por value: null, un preview y truncated: true, con un aviso para acotar la ruta.

Dónde vive un resultado almacenado

En la API REST, un resultado almacenado es un valor por cuenta que se conserva 1 hora y que solo puede leer la cuenta que lo creó. En el servidor MCP autoalojado, el almacén está en su propia máquina, en ~/.crawlforge/results/ (TTL de 1 hora, LRU de 200 MB), y no se sube nada. Las respuestas de error nunca se almacenan, y los trabajos de batch_scrape comparten el mismo almacén.

Ejemplos de solicitud

cURL

terminalBash
# 1. A scrape whose JSON exceeded max_inline_chars (default 40,000) came back
#    with a preview instead of the markdown:
#      "truncated": true,
#      "result_handle": "res_9f2c1e6a-4b7d-4c3e-8a5f-1d2e3f4a5b6c",
#      "total_chars": 182406

# 2. Search the stored result for the section you need (1 credit)
curl -X POST https://crawlforge.dev/api/v1/tools/read_result \
  -H "X-API-Key: cf_test_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "handle": "res_9f2c1e6a-4b7d-4c3e-8a5f-1d2e3f4a5b6c",
    "operation": "search",
    "query": "rate limits",
    "max_matches": 5
  }'

# 3. Read the section at the first match offset (1 credit) — no second fetch
curl -X POST https://crawlforge.dev/api/v1/tools/read_result \
  -H "X-API-Key: cf_test_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "handle": "res_9f2c1e6a-4b7d-4c3e-8a5f-1d2e3f4a5b6c",
    "operation": "slice",
    "offset": 18240,
    "length": 4000
  }'

TypeScript

readResult.tsTypescript
// npm install crawlforge-sdk
import { CrawlForge } from 'crawlforge-sdk';

const client = new CrawlForge({ apiKey: process.env.CRAWLFORGE_API_KEY });

// 1. Scrape a long page. Over max_inline_chars (default 40,000 characters of
//    JSON) the markdown is replaced by a preview and a result_handle.
const page = await client.scrape({
  url: 'https://example.com/docs/api',
  formats: ['markdown'],
});

// page.data is untyped in crawlforge-sdk 0.1 — a truncated result carries the
// handle fields shown in the cURL tab instead of the markdown.
const scraped = page.data as
  | { truncated: true; result_handle: string; total_chars: number }
  | { truncated?: false; formats: { markdown: string } };

if (scraped.truncated) {
  const { result_handle, total_chars } = scraped;
  console.log('Stored ' + total_chars + ' characters as ' + result_handle);

  // 2. Search the stored markdown for the section you need (1 credit).
  const found = await client.readResult({
    handle: result_handle,
    operation: 'search',
    query: 'rate limits',
    max_matches: 5,
  });

  // result.data is untyped in crawlforge-sdk 0.1 — its shape is the Response Example below.
  const { matches } = found.data as { matches: { offset: number }[] };

  // 3. Slice from the first match offset (1 credit) — no second fetch.
  const [first] = matches;
  if (first) {
    const section = await client.readResult({
      handle: result_handle,
      operation: 'slice',
      offset: first.offset,
      length: 4000,
    });
    const { text, has_more } = section.data as { text: string; has_more: boolean };
    console.log(text);
    console.log('More after this slice:', has_more);
  }
} else {
  console.log(scraped.formats.markdown); // small enough to arrive inline
}

Python

read_result.pyPython
# pip install crawlforge
from crawlforge import CrawlForge

client = CrawlForge()  # reads CRAWLFORGE_API_KEY

# 1. Scrape a long page. Over max_inline_chars (default 40,000 characters of
#    JSON) the markdown is replaced by a preview and a result_handle.
page = client.scrape(url='https://example.com/docs/api', formats=['markdown'])

# result.data is a plain dict — its shape is the Response Example below.
if page.data.get('truncated'):
    handle = page.data['result_handle']
    print(f"Stored {page.data['total_chars']} characters as {handle}")

    # 2. Search the stored markdown for the section you need (1 credit).
    found = client.read_result(
        handle=handle,
        operation='search',
        query='rate limits',
        max_matches=5,
    )

    # 3. Slice from the first match offset (1 credit) - no second fetch.
    if found.data['matches']:
        first = found.data['matches'][0]
        section = client.read_result(
            handle=handle,
            operation='slice',
            offset=first['offset'],
            length=4000,
        )
        print(section.data['text'])
        print('More after this slice:', section.data['has_more'])
else:
    print(page.data['formats']['markdown'])  # small enough to arrive inline

Ejemplo de respuesta

200 OK42ms
{
"success": true,
"data": {
"handle": "res_9f2c1e6a-4b7d-4c3e-8a5f-1d2e3f4a5b6c",
"tool": "scrape",
"operation": "search",
"view": "text",
"view_path": "markdown",
"total_chars": 182406,
"expires_at": "2026-09-05T15:42:10.000Z",
"query": "rate limits",
"matches": [
{
"offset": 18240,
"length": 11,
"context_offset": 18040,
"context": "…request. Every plan is metered per API key.\n\n## Rate limits\n\nEach key may make one request per second on the Free plan…"
},
{
"offset": 61377,
"length": 11,
"context_offset": 61177,
"context": "…returns 429 with a Retry-After header; see the rate limits table above for the per-plan ceilings…"
}
],
"total_matches": 2,
"truncated": false
},
"credits_used": 1,
"credits_remaining": 998,
"processing_time": 42
}
Field Descriptions
data.handleEl handle que envió, devuelto tal cual
data.toolLa herramienta que produjo el resultado almacenado
data.view`text` cuando la operación leyó la vista de texto (el markdown en scrape, el cuerpo en fetch_url); `json` en `json_path`
data.view_pathQué campo del resultado original es la vista de texto
data.total_charsTamaño de la vista de texto almacenada, en caracteres
data.expires_atCuándo se elimina el resultado almacenado: 1 hora después de almacenarse
data.matchesUna entrada por coincidencia: `offset` y `length` indexan la vista de texto; `context` lleva hasta 200 caracteres a cada lado, empezando en `context_offset`
data.total_matchesCuántas coincidencias existen en total; `truncated` es true cuando hubo más de las que `max_matches` permitía
credits_usedCredits descontados por esta solicitud (1 por lectura)
credits_remainingSu saldo de credits restante

Manejo de errores

Entrada no válida (400 Bad Request)

Falta handle, operation no es slice, search, lines ni json_path, se envió search sin query o json_path sin path, o max_matches queda fuera del rango 1-100 (VALIDATION_ERROR).

Ruta no encontrada (400 Bad Request)

json_path no pudo resolver path (PATH_NOT_FOUND); el error nombra las claves disponibles en el punto donde se detuvo. No se descuentan credits.

Resultado no encontrado (404 Not Found)

Handle de resultado desconocido o caducado (RESULT_NOT_FOUND): los resultados se conservan 1 hora y solo puede leerlos la cuenta que los creó. No se descuentan credits.

Almacenamiento no disponible (503 Service Unavailable)

No se pudo acceder al almacén de resultados (STORAGE_UNAVAILABLE). Reintente en breve; no se cobra nada por una lectura que no se completó.

Credits insuficientes (402 Payment Required)

Su cuenta no tiene suficientes credits. Compre más credits o mejore su plan.

Límite de velocidad superado (429 Too Many Requests)

Ha superado el límite de velocidad de su plan. Espere un momento o mejore su plan para obtener límites más altos.

Consejo profesional: search y después slice en el offset de la coincidencia leen una sección por 2 credits. Recorrer el resultado entero en trozos de 10.000 caracteres cuesta 1 credit por trozo, y volver a ejecutar la herramienta cuesta su precio completo más otra visita al sitio.

Coste en credits

1 credit
1 credit por solicitud
Cada solicitud de read_result cuesta 1 credit, sea cual sea la operación y cuanto devuelva. La extracción en sí ya la facturó la herramienta que almacenó el resultado.

Plan Free: 1,000 credits por única vez = 1.000 solicitudes

Plan Hobby: 5.000 credits/mes = 5.000 solicitudes (19 USD/mes)

Plan Professional: 50.000 credits/mes = 50.000 solicitudes (99 USD/mes)

Plan Business: 250.000 credits/mes = 250.000 solicitudes (399 USD/mes)

Herramientas relacionadas

scrape
La fuente habitual de un result_handle: max_inline_chars fija cuánto llega en línea (2 credits)
crawl_deep
Los rastreos multipágina son los resultados más grandes; json_path lee una página del rastreo almacenado (4 credits)
fetch_url
Un cuerpo JSON que supera el límite en línea también se almacena; json_path lee su cuerpo analizado (1 credit)
get_batch_results
Recorre un trabajo de batch_scrape; los resultados almacenados del lote comparten el mismo almacén de 1 hora (1 credit)
¿Listo para probar read_result? Regístrese gratis y obtenga 1.000 credits para empezar a construir.

Pie de página

CrawlForge MCP

Web scraping empresarial para agentes de IA. 30 herramientas MCP especializadas diseñadas para desarrolladores modernos que crean sistemas inteligentes.

Producto

  • Funciones
  • Playground
  • Precios
  • Casos de uso
  • Integraciones
  • Alternativas
  • Registro de cambios

Recursos

  • Primeros pasos
  • Referencia de la API
  • Plantillas
  • Guías
  • Blog
  • Glosario
  • Preguntas frecuentes
  • Mapa del sitio

Desarrolladores

  • Protocolo MCP
  • Claude Desktop
  • Cursor IDE
  • LangChain
  • LlamaIndex

Empresa

  • Acerca de
  • Contacto
  • Privacidad
  • Términos
  • Uso aceptable
  • Seguridad
  • Cookies

Mantente al día

Recibe las últimas novedades sobre nuevas herramientas y funciones.

Creado con Next.js y el protocolo MCP

© 2025-2026 CrawlForge. Todos los derechos reservados.