browser_ session
Una sola página del navegador que conservas a lo largo de varias llamadas a la API. Abre una sesión, toma un snapshot para ver qué ofrece la página, actúa sobre las referencias que ese snapshot te devolvió, vuelve a mirar: y paga el inicio de sesión una vez, no una vez por llamada.
Casos de uso
Inicia sesión una vez y lee muchas páginas
Inicia sesión en la primera llamada y luego navega y lee detrás del muro de inicio de sesión mientras dure la sesión, sin repetir el login cada vez
Explora una aplicación desconocida
Toma un snapshot de una página que nunca has visto, lee sus elementos interactivos en la respuesta y actúa sobre ellos en la llamada siguiente en lugar de adivinar selectores CSS
Bucles de agente
Dale a un agente un bucle de mirar y actuar: el árbol del snapshot es la observación, las referencias son el espacio de acciones y el siguiente snapshot es la retroalimentación
Asistentes de varios pasos
Recorre un proceso de compra o de alta paso a paso, una llamada por paso, comprobando en qué se ha convertido la página antes de elegir la acción siguiente
Depurar una cadena que falla
Cuando una cadena de acciones de un solo disparo falla por un selector adivinado, abre una sesión y recórrela paso a paso, tomando una captura de pantalla entre pasos
Leer después de la interacción
Extrae markdown, HTML, texto o metadatos del DOM en vivo tal como queda después de todo lo que la sesión ha pulsado
Endpoint
/api/v1/tools/browser_sessionParameters
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
operation | string | Required | - | Qué paso de la sesión realiza esta llamada: `open`, `snapshot`, `act`, `read`, `screenshot`, `close` o `list`. Todas las operaciones salvo `open` y `list` necesitan `session_id`. La operación también fija el precio: consulta **Operaciones y lo que cuestan** más abajo. Example: snapshot |
session_id | string | Optional | - | El id que devolvió `operation: "open"`, que se envía en cada llamada posterior de la sesión. Lo necesitan `snapshot`, `act`, `read`, `screenshot` y `close`. Un id desconocido, caducado, ya cerrado o perteneciente a otra cuenta devuelven todos lo mismo, «Session not found»: los ids no son enumerables, así que el error nunca te dice cuál de los cuatro casos fue. Example: 9f2c1e6a-4b7d-4c3e-8a5f-1d2e3f4a5b6c |
url | string | Optional | - | La página en la que se abre la sesión. La exige `open` y las demás operaciones la ignoran: una vez que la sesión existe, la mueves con una acción `navigate` dentro de `act`. La URL pasa el control SSRF y el robots.txt del destino antes de lanzar ningún navegador, igual que cada navegación dentro de la sesión. Example: https://app.example.com/login |
stealth | boolean | Optional | false | Solo en `open`. Ejecuta la sesión en el motor sigiloso de Chromium con su perfil `medium` en lugar del grupo de navegadores estándar. Tarda más en arrancar y renderiza JavaScript, no resuelve desafíos. La sesión conserva este ajuste durante toda su vida. Example: false |
ttl | number | Optional | 600 | Solo en `open`. Cuánto puede vivir la sesión como máximo, en segundos (30-3600). La sesión se cierra con este reloj sin importar qué estés haciendo, así que ajústalo al trabajo previsto. Example: 600 |
activity_ttl | number | Optional | 300 | Solo en `open`. Cuánto puede permanecer inactiva la sesión entre llamadas, en segundos (10-3600). Cada operación reinicia este reloj; el reloj que venza primero cierra la sesión y libera su página. Example: 300 |
viewport | object | Optional | - | Solo en `open`. La ventana del navegador en la que corre la sesión: `{ width, height }`, con ancho 800-1920 y alto 600-1080. Si lo omites se usa el tamaño propio del grupo de navegadores. Example: {"width": 1440, "height": 900} |
timeout | number | Optional | 30000 | Presupuesto de tiempo, en milisegundos, para el trabajo de navegador de esta llamada (10000-120000): la primera navegación en `open`, la cadena de acciones en `act`. Mantenlo dentro de la ventana REST de ~25s. Example: 30000 |
respect_robots | boolean | Optional | true | Respeta el robots.txt del sitio de destino. Si lo omites, se aplica el valor predeterminado conforme (`true`): una URL que robots.txt no permita a `CrawlForge` se rechaza antes de abrir el navegador y este endpoint no cobra nada por ello, y cada acción `navigate` dentro de `act` se comprueba igual. Se aplica a la llamada en la que se envía y la sesión nunca lo recuerda, así que una anulación hay que repetirla con la misma deliberación con que se hizo. Ponlo en `false` solo para destinos con los que tengas tu propio acuerdo: la anulación queda registrada en tu API key. Example: true |
interactive_only | boolean | Optional | true | Solo en `snapshot`. Enumera únicamente los elementos que aceptan el puntero o el teclado, que son los que reciben una referencia. Ponlo en false para enumerar también encabezados y regiones (landmarks): útil para orientarte en la página, aunque esos nodos nunca reciben referencia. Example: true |
max_nodes | number | Optional | 200 | Solo en `snapshot`. Limita cuántos nodos enumera el árbol (1-1000); con el valor predeterminado de `interactive_only`, eso es una referencia por nodo. El resultado indica `truncated: true` cuando ese límite detuvo el recorrido. Example: 200 |
actions | array | Optional | - | Solo en `act`. De 1 a 20 acciones de navegador que se ejecutan sobre la página que ya tiene la sesión, con el mismo vocabulario que admite [scrape_with_actions](/docs/api-reference/tools/scrape-with-actions) — `wait`, `click`, `type`, `press`, `scroll`, `screenshot`, `select`, `hover`, `navigate`, `snapshot` — junto a sus campos específicos según el tipo. Apunta `selector` a una referencia `@e1` del último snapshot de la sesión en lugar de a un selector CSS adivinado. `executeJavaScript` se rechaza en la API alojada: el script se ejecutaría en un navegador de nuestra infraestructura, no en tu máquina. Example: [{"type": "type", "selector": "@e1", "text": "user@example.com"}, {"type": "click", "selector": "@e3"}] |
continue_on_error | boolean | Optional | false | Solo en `act`. Continúa ejecutando las acciones restantes cuando una falla, en lugar de detener la cadena. Los resultados por acción indican cuáles se ejecutaron. Example: false |
formats | array | Optional | ["markdown"] | Solo en `read`. Qué extraer de la página tal como está en este momento: `markdown`, `html`, `text`, `json` (título, metadatos y datos estructurados). El contenido sale del DOM en vivo, así que refleja las cookies de la sesión y todo lo que ha pulsado, no una nueva descarga de la URL. Example: ["markdown", "json"] |
full_page | boolean | Optional | false | Solo en `screenshot`. Captura toda la página desplazable en lugar de solo el área visible. Example: false |
format | string | Optional | png | Solo en `screenshot`. Formato de imagen: `png` o `jpeg`. Example: png |
quality | number | Optional | 80 | Solo en `screenshot`. Calidad JPEG, 0-100. PNG la ignora. Example: 80 |
selector | string | Optional | - | Solo en `screenshot`. Captura un único elemento en lugar de la página: un selector CSS o una referencia `@e1` del último snapshot de la sesión. Example: @e2 |
max_inline_chars | number | Optional | 40000 | Solo para `snapshot`, `act` y `read`, las operaciones que devuelven contenido de la página. Tamaño máximo del resultado que se devuelve en línea, en caracteres de su JSON (de 1.000 a 10.000.000). Por encima, la respuesta incluye `preview`, `result_handle`, `total_chars`, `truncated: true` y `expires_at`, y [read_result](/docs/api-reference/tools/read-result) lee el resto por 1 credit por llamada; los campos que se miden son `content.markdown`, `content.text`, `content.html` y `snapshot.tree`. Los resultados almacenados se conservan 1 hora. La sesión no se ve afectada: la página sigue abierta y la siguiente operación la ve entera. Example: 40000 |
redact_pii | boolean | object | Optional | false | Solo para `snapshot`, `act` y `read`; las demás operaciones devuelven datos de control y no se tocan. Elimina los datos personales del texto que devuelve esta llamada, antes de que el resultado se almacene o se envíe de vuelta: para eso existe, para una página con la sesión iniciada cuyo `tree` y contenido extraído llevan los datos del titular de la cuenta. `true` es la forma abreviada de `{ mode: "fast" }`: las cuatro clases de expresiones regulares, etiquetadas. Siempre que pidas redacción, la respuesta lleva `redaction: { entities, count, mode }` dentro de `data`, incluso cuando no hubo coincidencias (`count: 0`), de modo que «no se encontró nada» nunca se confunde con «se ignoró el parámetro». La redacción se ejecuta **antes** de almacenar el resultado, así que un resultado grande que se lea después con [read_result](/docs/api-reference/tools/read-result) ya viene redactado. Dos límites deliberados: las direcciones (`url`, `link`, `href`, `canonical_url`) nunca se redactan, y los contadores derivados del texto (`content_length`, `word_count`, `character_count`) lo describen tal como se extrajo, antes de la redacción. Example: true |
Operaciones y lo que cuestan
Cada llamada se cobra según su propia operation, así que una mirada barata no paga el precio de un open caro. Nada se ejecuta gratis: close y list siguen costando 1 credit cada uno.
url y devuelve un sessionId junto con los dos relojes de caducidad. Es la operación más cara porque es la que arranca un navegador: estrictamente más trabajo que un scrape de un solo disparo.@e1, @e2, … en orden del documento. Es la mitad de «mirar» del bucle, y es a lo que apunta la llamada siguiente.scrape porque es la misma extracción de contenido.crawlforge://screenshot/{id} en lugar de base64 en línea, y este endpoint REST reenvía ese URI sin resolverlo, así que por ahora los bytes solo se pueden leer desde el CrawlForge MCP server.Cuánto vive una sesión y cuántas puedes tener
Una sesión vive en la memoria del backend de ejecución, en una sola instancia. No sobrevive a un redespliegue ni al reinicio de una instancia, así que trata un sessionId como algo efímero y cuenta con que la próxima llamada responda «Session not found»: vuelve a abrirla y sigue. Las sesiones son efímeras por diseño: ttl (predeterminado 600s, rango 30-3600) es el reloj absoluto, activity_ttl (predeterminado 300s, rango 10-3600) el de inactividad, y el que venza primero cierra la sesión. Una API key REST solo puede tener una sesión a la vez. Un segundo open mientras una sigue viva se rechaza con un error con nombre, no se pone en cola: una plaza de sesión se libera dentro de varios minutos, así que esperar se limitaría a dejar la llamada colgada. El backend alojado mantiene tres sesiones en total entre todos los clientes, que es por lo que el límite por clave es una: haz close cuando termines en lugar de dejar que corra el TTL, y la siguiente apertura es tuya.
Apuntar a elementos por referencia
Un snapshot coloca una referencia estable en cada elemento interactivo que encuentra, y la sesión conserva esas referencias mientras conserve la página: por eso el bucle es abrir, hacer snapshot, actuar sobre @e1 / @e2 en una llamada aparte y volver a hacer snapshot. En eso consiste una sesión: una cadena de un solo disparo tiene que nombrar sus selectores antes de haber visto la página. Una referencia solo es válida en el documento del que se tomó su snapshot: cualquier navegación —una acción navigate o un clic que carga otra página— invalida todas las referencias, y usar una obsoleta falla de forma ruidosa con un error que te pide tomar un snapshot nuevo, nunca pulsando en silencio lo que no era.
¿browser_session o scrape_with_actions?
Ambas manejan un navegador real y admiten el mismo vocabulario de acciones. La diferencia está en si ya sabes qué aspecto tiene la página.
open, snapshot, act, act, read, close— cuesta 9 credits frente a los 5 de una cadena de un solo disparo con muchas más probabilidades de fallar por un selector adivinado.Aquí no hay inicios de sesión persistentes
Las cookies y el localStorage de una sesión nacen y mueren con ella. Esta API no tiene ningún parámetro de perfil ni forma de guardar un navegador con la sesión iniciada para la próxima vez, así que el inicio de sesión hay que repetirlo cada vez que abras una. Los perfiles de inicio de sesión guardados son una función posterior y restringida al uso local: no planifiques un flujo alojado contando con ellos.
Ejemplos de solicitud
# 1. Open the session (3 credits). The id comes back as data.sessionId.
curl -X POST https://crawlforge.dev/api/v1/tools/browser_session \
-H "X-API-Key: cf_test_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"operation": "open",
"url": "https://app.example.com/login",
"ttl": 600
}'
# {"success": true, "data": {"sessionId": "9f2c1e6a-4b7d-4c3e-8a5f-1d2e3f4a5b6c", ...}}
# 2. Look at the page before touching it (1 credit).
curl -X POST https://crawlforge.dev/api/v1/tools/browser_session \
-H "X-API-Key: cf_test_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"operation": "snapshot",
"session_id": "9f2c1e6a-4b7d-4c3e-8a5f-1d2e3f4a5b6c"
}'
# data.snapshot.tree comes back as:
# [document] "Sign in"
# @e1 [textbox] "Email"
# @e2 [textbox] "Password"
# @e3 [button] "Sign in"
# 3. Act on those refs in a SEPARATE call (1 credit). Same page, same cookies.
curl -X POST https://crawlforge.dev/api/v1/tools/browser_session \
-H "X-API-Key: cf_test_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"operation": "act",
"session_id": "9f2c1e6a-4b7d-4c3e-8a5f-1d2e3f4a5b6c",
"actions": [
{"type": "type", "selector": "@e1", "text": "user@example.com"},
{"type": "type", "selector": "@e2", "text": "secret123"},
{"type": "click", "selector": "@e3"},
{"type": "wait", "duration": 1000}
]
}'
# 4. Read the page the login landed on (2 credits).
curl -X POST https://crawlforge.dev/api/v1/tools/browser_session \
-H "X-API-Key: cf_test_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"operation": "read",
"session_id": "9f2c1e6a-4b7d-4c3e-8a5f-1d2e3f4a5b6c",
"formats": ["markdown"]
}'
# 5. Close it rather than waiting for the TTL (1 credit). 8 credits in all.
curl -X POST https://crawlforge.dev/api/v1/tools/browser_session \
-H "X-API-Key: cf_test_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"operation": "close",
"session_id": "9f2c1e6a-4b7d-4c3e-8a5f-1d2e3f4a5b6c"
}'Ejemplo de respuesta
{ "success": true, "data": { "success": true, "operation": "snapshot", "sessionId": "9f2c1e6a-4b7d-4c3e-8a5f-1d2e3f4a5b6c", "url": "https://app.example.com/login", "stealth": false, "expiresAt": 1789459200000, "idleExpiresAt": 1789458900000, "snapshot": { "snapshotId": "a3f19c2d", "url": "https://app.example.com/login", "title": "Sign in", "tree": "[document] \"Sign in\"\n @e1 [textbox] \"Email\"\n @e2 [textbox] \"Password\"\n @e3 [button] \"Sign in\"", "refCount": 3, "nodeCount": 3, "truncated": false, "interactiveOnly": true } }, "credits_used": 1, "credits_remaining": 996, "processing_time": 180}data.operationLa operación que realizó esta llamada: cada respuesta la devuelvedata.sessionIdEnvíalo en cada llamada posterior de la sesióndata.urlDónde está ahora mismo la página de la sesión, que una navegación cambiadata.expiresAtCuándo vence el reloj absoluto `ttl`, en milisegundos desde la época Unixdata.idleExpiresAtCuándo vence el reloj de inactividad `activity_ttl`; cada operación lo adelantadata.snapshot.treeEl árbol de accesibilidad. Cada elemento interactivo lleva la referencia a la que apuntas en la llamada siguientedata.snapshot.refCountCuántos elementos recibieron una referencia en este snapshotdata.snapshot.truncatedTrue cuando `max_nodes` detuvo el recorrido antes del final de la páginacredits_usedCredits descontados por esta llamada: 1 por un snapshot, 3 por un openprocessing_timeTiempo en ms de esta llamada sola, no de la sesiónManejo de errores
Sesión no encontrada (502 TOOL_ERROR)
El session_id es desconocido, ha caducado, ya se cerró o pertenece a otra cuenta: los cuatro casos responden igual, así que los ids no se pueden sondear desde fuera. Las sesiones tampoco sobreviven a un reinicio del backend de ejecución. Abre una nueva y continúa; la llamada fallida no se cobra.
Límite de sesiones alcanzado (502 TOOL_ERROR)
Ya tienes el máximo de una sesión abierta. La llamada se rechaza en lugar de ponerse en cola, porque una plaza de sesión se libera con su TTL dentro de varios minutos. Envía operation: "close" para la sesión que tienes —operation: "list" te dice su id— o espera a su TTL.
Runtime de navegador no configurado (503 TOOL_NOT_AVAILABLE)
Esta herramienta necesita un runtime de automatización de navegador. Cuando el backend de ejecución alojado no está configurado, la llamada devuelve 503 de inmediato y no se cobran credits.
El backend de ejecución agotó el tiempo (504 MCP_UPSTREAM_TIMEOUT)
La navegación o la cadena de acciones superó el presupuesto de tiempo del backend de ejecución. Acorta las esperas, reparte la cadena en dos llamadas act —la sesión sigue ahí— o reinténtalo. Los fallos no se cobran.
Bloqueado por robots.txt (502 TOOL_ERROR)
El robots.txt del destino no permite esta URL a CrawlForge, así que no se lanzó ningún navegador y no se cobró nada. Cada acción navigate dentro de act se comprueba igual, no solo la URL con la que abriste. Establece respect_robots: false para anularlo si tienes tu propio acuerdo con el destino: la anulación queda registrada en tu API key.
Solicitud no válida (400 Bad Request)
A la operación le falta un parámetro que necesita —open sin url, act sin actions, o cualquier operación que no sea open ni list sin session_id— o una acción no pasó su propio esquema. No se cobra nada.
Credits insuficientes (402 Payment Required)
Tu cuenta no tiene credits suficientes para esta operación (hasta 3). Compra más credits o actualiza tu plan.
Límite de tasa excedido (429 Too Many Requests)
Has superado el límite de tasa de tu plan. Espera un momento o actualiza tu plan para obtener límites más altos.
Toma un snapshot después de todo lo que cambie la página, no solo al principio: un clic que navega invalida todas las referencias, y el árbol nuevo cuesta 1 credit. Cuando una sesión solo va a ejecutar una cadena fija, scrape_with_actions sale más barato y en un solo viaje.
Costo en credits
operation, no por herramienta: open 3, read 2, y snapshot, act, screenshot, close y list 1 cada uno. 3 credits es el techo —lo que cuesta open y lo que se cobra por una operación no reconocida—. Un flujo de login y lectura (open, snapshot, act, act, read, close) suma 9 credits.Plan Free: 1,000 credits de prueba por única vez = unas 110 sesiones de login y lectura
Plan Hobby: 5,000 credits/mes = unas 550 sesiones ($19/mo)
Plan Professional: 50,000 credits/mes = unas 5,500 sesiones ($99/mo)
Plan Business: 250,000 credits/mes = unas 27,000 sesiones ($399/mo)
Herramientas relacionadas
¿Listo para probar browser_session? Regístrate gratis y obtén 1,000 credits para empezar a desarrollar.