Documentation Index
Fetch the complete documentation index at: https://docs.firecrawl.dev/llms.txt
Use this file to discover all available pages before exploring further.
Los monitores de Firecrawl ejecutan scrapes o crawls recurrentes y comparan cada resultado con la última instantánea retenida. Usa los monitores para supervisar páginas de producto, documentación, blogs, registros de cambios, sitios de la competencia o cualquier página donde sea importante detectar cambios.
Cada comprobación registra resultados por página como same, new, changed, removed o error. Puedes recibir un webhook cuando termine cada página supervisada, un webhook por cada comprobación completada, resúmenes por correo electrónico cuando haya cambios o errores, o cualquier combinación de estas notificaciones.
La supervisión requiere instantáneas retenidas y diferencias. No está disponible para equipos con retención de datos cero.
Crea un monitor de scraping para una o más URL específicas:
from firecrawl import Firecrawl
firecrawl = Firecrawl(api_key="fc-YOUR-API-KEY")
monitor = firecrawl.create_monitor(
name="Hacker News AI monitor",
schedule={"text": "every 30 minutes", "timezone": "UTC"},
goal=(
"Alert when a new Hacker News story related to AI enters the top 10. "
"Ignore changes to stories that are not about AI. "
"Do not alert on changes outside the top 10."
),
targets=[
{
"type": "scrape",
"urls": ["https://news.ycombinator.com"],
}
],
notification={
"email": {
"enabled": True,
"recipients": ["alerts@example.com"],
"includeDiffs": True,
}
},
)
print(monitor.id)
Crea un monitor de rastreo para comparar los cambios en cada página descubierta durante un rastreo en cada comprobación:
from firecrawl import Firecrawl
firecrawl = Firecrawl(api_key="fc-YOUR-API-KEY")
monitor = firecrawl.create_monitor(
name="Docs monitor",
schedule={"cron": "7-59/15 * * * *", "timezone": "UTC"},
goal="Notify me when docs pages add, remove, or materially change API behavior",
targets=[
{
"type": "crawl",
"url": "https://example.com/docs",
"crawlOptions": {
"limit": 100,
"maxDiscoveryDepth": 3,
},
}
],
webhook={
"url": "https://example.com/webhooks/firecrawl",
"events": ["monitor.page", "monitor.check.completed"],
},
)
print(monitor.id)
Cada llamada de creación devuelve el nuevo monitor con su cron normalizado, nextRunAt calculado y estimatedCreditsPerMonth. Cuando la evaluación está habilitada, estimatedCreditsPerMonth es una estimación de cota superior porque los créditos de evaluación solo se cobran por las páginas modificadas que realmente se evalúan:
{
"success": true,
"data": {
"id": "019df960-06e7-7383-9d89-82c0113dc31a",
"name": "Hacker News AI monitor",
"status": "active",
"schedule": {
"cron": "*/30 * * * *",
"timezone": "UTC"
},
"nextRunAt": "2026-05-17T16:00:00.000Z",
"lastRunAt": null,
"currentCheckId": null,
"goal": "Alert when a new Hacker News story related to AI enters the top 10. Ignore changes to stories that are not about AI. Do not alert on changes outside the top 10.",
"judgeEnabled": true,
"targets": [
{
"id": "019df960-09bb-7c11-8001-1f12f50ab1c2",
"type": "scrape",
"urls": ["https://news.ycombinator.com"]
}
],
"webhook": null,
"notification": {
"email": {
"enabled": true,
"recipients": ["alerts@example.com"],
"includeDiffs": true
}
},
"retentionDays": 30,
"estimatedCreditsPerMonth": 2880,
"lastCheckSummary": null,
"createdAt": "2026-05-17T15:30:00.000Z",
"updatedAt": "2026-05-17T15:30:00.000Z"
}
}
También puedes crear monitores desde la CLI de Firecrawl:
firecrawl monitor create --name "Hacker News AI" \
--schedule "every 30 minutes" \
--goal "Alert when a new Hacker News story related to AI enters the top 10. Ignore changes to stories that are not about AI. Do not alert on changes outside the top 10." \
--page https://news.ycombinator.com
Añade un goal en lenguaje claro cuando solo quieras recibir alertas por cambios significativos. Si goal está presente y se omite judgeEnabled, Firecrawl habilita la evaluación automáticamente. La evaluación se ejecuta en las páginas que han cambiado y devuelve un judgment con meaningful, confidence, reason y meaningfulChanges.
Usa judgeEnabled: false si quieres guardar un objetivo sin evaluar todavía los cambios. El evaluador solo se ejecuta cuando el monitor tiene tanto judgeEnabled como un goal no vacío.
Cada comprobación siempre consume créditos por las operaciones subyacentes de scraping o rastreo. Si la evaluación está habilitada, el evaluador añade 1 crédito por cada página modificada que valida. Las comprobaciones sin páginas modificadas no usan créditos del evaluador.
Los buenos objetivos son breves y explícitos: indica qué debe activar una alerta, especifica de nuevo cualquier criterio de alcance, como top N, precio, tipo de puesto, empresa, región, tema, estado o entidad, e incluye exclusiones solo cuando formen parte de la intención. Si el objetivo es amplio, mantenlo amplio; por ejemplo, “cualquier cambio” no debería añadir filtros de ruido que oculten cambios.
Por ejemplo, un monitor con este objetivo:
Alerta cuando una nueva historia de Hacker News relacionada con IA entre al top 10. Ignora los cambios en historias que no sean sobre IA. No alertes sobre cambios fuera del top 10.
podría generar un webhook monitor.page como este cuando una historia coincidente pase a estar dentro del alcance:
{
"success": true,
"type": "monitor.page",
"id": "019df960-5f2a-75fb-a98b-bd2d32ca67d4",
"webhookId": "f1e2d3c4-0000-0000-0000-000000000000",
"data": [
{
"monitorId": "019df960-06e7-7383-9d89-82c0113dc31a",
"checkId": "019df960-5f2a-75fb-a98b-bd2d32ca67d4",
"url": "https://news.ycombinator.com",
"status": "changed",
"previousScrapeId": "019df94f-82c3-7e41-81f0-00c72b2d9c52",
"currentScrapeId": "019df960-73ee-7ac2-97a9-fb0e442c21f1",
"error": null,
"isMeaningful": true,
"judgment": {
"meaningful": true,
"confidence": "high",
"reason": "A new AI-related story entered the Hacker News top 10.",
"meaningfulChanges": [
{
"type": "added",
"after": "4. Show HN: Open-source AI coding assistant",
"reason": "This is a new AI-related story inside the top 10."
}
]
},
"diff": {
"text": "--- previous\n+++ current\n@@ -1,5 +1,6 @@\n # Hacker News\n 1. Database internals for beginners\n 2. A new approach to CSS\n 3. Building reliable queues\n+4. Show HN: Open-source AI coding assistant\n"
}
}
],
"metadata": {
"environment": "production"
}
}
Las programaciones pueden proporcionarse en formato cron o como texto simple en lenguaje natural.
{
"schedule": {
"cron": "*/30 * * * *",
"timezone": "UTC"
}
}
Ejemplos compatibles de lenguaje natural:
every 30 minutes
every 15 minutes starting at :07
hourly
every 2 hours
daily
daily at 9:00
daily at 9am
daily at 5:30 PM
weekly
El intervalo mínimo es de 15 minutos. Las respuestas de la API siempre devuelven la expresión cron normalizada. En las programaciones de texto, timezone controla cuándo se ejecutan frases como daily at 9am. Las programaciones en texto se distribuyen según el ID del monitor antes de convertirse a cron, para que varios monitores no se ejecuten todos en el mismo instante.
Los monitores admiten dos tipos de objetivo:
scrape: Ejecuta un scrape por cada URL en urls.
crawl: Ejecuta un crawl completo para url en cada comprobación y luego compara las diferencias entre todas las páginas descubiertas.
Cada monitor acepta entre 1 y 50 objetivos. retentionDays tiene un valor predeterminado de 30 y puede establecerse en hasta 365.
Las opciones de scrape del objetivo se pasan a los trabajos de scrape subyacentes. Los scrapes activados por el monitor establecen maxAge en 0 de forma predeterminada, por lo que cada comprobación realiza un scrape nuevo, a menos que establezcas explícitamente un maxAge distinto.
{
"type": "scrape",
"urls": ["https://example.com/pricing"],
"scrapeOptions": {
"formats": ["markdown"],
"maxAge": 0
}
}
Para los objetivos de crawl, usa crawlOptions para el comportamiento del crawl y scrapeOptions para el scrape de cada página:
{
"type": "crawl",
"url": "https://example.com/docs",
"crawlOptions": {
"limit": 100,
"includePaths": ["/docs"]
},
"scrapeOptions": {
"formats": ["markdown"]
}
}
De forma predeterminada, Firecrawl compara el markdown de cada página e informa same, changed, new, removed o error. Si quieres detectar cambios en campos estructurados específicos (precio, encabezado, indicador de disponibilidad, elementos de una lista, etc.), habilita el seguimiento de cambios en modo JSON añadiendo un formato changeTracking con modes: ["json"] a scrapeOptions del objetivo.
Modo Markdown (predeterminado)
Cuando scrapeOptions.formats es solo ["markdown"], cada página con cambios en la respuesta de check incluye un diff de texto unificado y un AST al estilo de parseDiff:
{
"diff": {
"text": "--- previous\n+++ current\n@@ -1,3 +1,3 @@\n # Pricing\n-Starter — $19/mo\n+Starter — $24/mo\n",
"json": {
"files": [
{
"from": "previous",
"to": "current",
"chunks": [
{
"content": "@@ -1,3 +1,3 @@",
"changes": []
}
]
}
]
}
}
}
Pasa un formato changeTracking con modes: ["json"] junto con un esquema JSON (o un prompt) que describa los campos que te interesan. Firecrawl extrae ese JSON en cada comprobación y genera un diff por campo con claves basadas en la ruta del campo, además de un snapshot.json con la extracción actual completa para que los consumidores no tengan que volver a obtener el scraping original.
from firecrawl import Firecrawl
from pydantic import BaseModel
from typing import List
firecrawl = Firecrawl(api_key="fc-YOUR-API-KEY")
class Plan(BaseModel):
name: str
price: str
features: List[str]
class Pricing(BaseModel):
plans: List[Plan]
monitor = firecrawl.create_monitor(
name="Pricing monitor",
schedule={"text": "hourly", "timezone": "UTC"},
goal="Notify me when a pricing tier, price, or headline feature changes",
targets=[
{
"type": "scrape",
"urls": ["https://example.com/pricing"],
"scrapeOptions": {
"formats": [
{
"type": "changeTracking",
"modes": ["json"],
"prompt": "Extract pricing tiers and headline features for each plan.",
"schema": Pricing.model_json_schema(),
}
]
},
}
],
notification={
"email": {
"enabled": True,
"recipients": ["alerts@example.com"],
"includeDiffs": True,
}
},
)
print(monitor.id)
La carga útil del diff se ve así: las claves son rutas JSON dentro de la extracción, y cada valor es un par {previous, current}:
{
"diff": {
"json": {
"plans[0].price": {
"previous": "$19/mo",
"current": "$24/mo"
},
"plans[1].features[2]": {
"previous": "10 GB storage",
"current": "25 GB storage"
}
}
},
"snapshot": {
"json": {
"plans": [
{
"name": "Starter",
"price": "$24/mo",
"features": ["Up to 3 users", "Basic analytics", "Email support"]
},
{
"name": "Pro",
"price": "$49/mo",
"features": ["Unlimited users", "Advanced analytics", "25 GB storage"]
}
]
}
}
}
Aunque no cambie ningún campo supervisado, si el markdown circundante sí cambia, los monitores en modo JSON seguirán devolviendo same a menos que también habilites git-diff (consulta el modo mixto más abajo). El diff se centra exclusivamente en los campos de tu esquema.
Modo mixto (JSON + git-diff)
Si quieres ambas representaciones — el diff estructurado por campo y el diff unificado sin procesar en markdown — indica ambos modos:
Mixed target (JSON + git-diff)
{
"type": "scrape",
"urls": ["https://example.com/pricing"],
"scrapeOptions": {
"formats": [
{
"type": "changeTracking",
"modes": ["json", "git-diff"],
"prompt": "Extract pricing tiers and headline features for each plan.",
"schema": {
"type": "object",
"properties": {
"plans": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": { "type": "string" },
"price": { "type": "string" }
}
}
}
}
}
}
]
}
}
La respuesta de check contiene entonces tanto diff.text (sidecar de markdown) como diff.json (diff por campo), junto con la extracción snapshot.json:
Mixed-mode diff (JSON + git-diff)
{
"diff": {
"text": "--- previous\n+++ current\n@@ -1,3 +1,3 @@\n # Pricing\n-Starter — $19/mo\n+Starter — $24/mo\n",
"json": {
"plans[0].price": {
"previous": "$19/mo",
"current": "$24/mo"
}
}
},
"snapshot": {
"json": {
"plans": [
{ "name": "Starter", "price": "$24/mo" },
{ "name": "Pro", "price": "$49/mo" }
]
}
}
}
Una página en modo mixto informa changed siempre que cualquiera de las dos representaciones haya cambiado.
Cuando un monitor tiene un webhook, Firecrawl puede enviar dos eventos del monitor:
monitor.page: Se envía a medida que finaliza cada scraping supervisado en el worker de scraping.
monitor.check.completed: Se envía después de que se consolida la comprobación completa. Incluye el estado de la comprobación y los recuentos de resumen. Usa los eventos monitor.page o la API de comprobación del monitor para obtener resultados a nivel de página.
monitor.page incluye isMeaningful y judgment cuando se ejecuta la evaluación de cambios significativos en una página modificada.
{
"webhook": {
"url": "https://example.com/webhooks/firecrawl",
"headers": {
"Authorization": "Bearer your-secret"
},
"metadata": {
"environment": "production"
},
"events": ["monitor.page", "monitor.check.completed"]
}
}
Carga útil de monitor.page:
{
"success": true,
"type": "monitor.page",
"id": "019df960-5f2a-75fb-a98b-bd2d32ca67d4",
"webhookId": "f1e2d3c4-0000-0000-0000-000000000000",
"data": [
{
"monitorId": "019df960-06e7-7383-9d89-82c0113dc31a",
"checkId": "019df960-5f2a-75fb-a98b-bd2d32ca67d4",
"url": "https://example.com/blog",
"status": "changed",
"previousScrapeId": "019df94f-82c3-7e41-81f0-00c72b2d9c52",
"currentScrapeId": "019df960-73ee-7ac2-97a9-fb0e442c21f1",
"error": null,
"isMeaningful": true,
"judgment": {
"meaningful": true,
"confidence": "high",
"reason": "The page headline changed to announce a new release cadence.",
"meaningfulChanges": [
{
"type": "changed",
"before": "Welcome to our weekly update.",
"after": "Welcome to our weekly update — now with daily releases!",
"reason": "The headline changed in a way that matches the monitor goal."
}
]
},
"diff": {
"text": "--- previous\n+++ current\n@@ -1,3 +1,3 @@\n # Latest posts\n-Welcome to our weekly update.\n+Welcome to our weekly update — now with daily releases!\n"
}
}
],
"metadata": {
"environment": "production"
}
}
Carga útil de monitor.check.completed:
{
"success": true,
"type": "monitor.check.completed",
"id": "019df960-5f2a-75fb-a98b-bd2d32ca67d4",
"webhookId": "f1e2d3c4-0001-0000-0000-000000000000",
"data": [
{
"monitorId": "019df960-06e7-7383-9d89-82c0113dc31a",
"checkId": "019df960-5f2a-75fb-a98b-bd2d32ca67d4",
"status": "completed",
"summary": {
"totalPages": 2,
"same": 1,
"changed": 1,
"new": 0,
"removed": 0,
"error": 0
}
}
],
"metadata": {
"environment": "production"
}
}
success es true cuando la comprobación se completa sin errores de página. Es false en comprobaciones fallidas o parciales, y error contiene el motivo del fallo cuando está disponible.
Los resúmenes por correo electrónico se envían solo cuando una comprobación tiene páginas modificadas, nuevas, eliminadas o con errores.
{
"notification": {
"email": {
"enabled": true,
"recipients": ["alerts@example.com"],
"includeDiffs": true
}
}
}
Cuando un monitor tiene un objetivo y la evaluación está habilitada, los resúmenes por correo electrónico priorizan las páginas modificadas relevantes. Si todas las páginas modificadas se consideran ruido y no hay páginas nuevas, eliminadas o con errores, el correo electrónico no se envía.
Si se omite recipients, Firecrawl envía correos a los miembros del equipo que pueden recibir correos electrónicos de alerta del sistema.
Puedes configurar hasta 25 destinatarios explícitos.
Resultados de comprobaciones
Usa GET /v2/monitor/{monitorId}/checks para listar comprobaciones y GET /v2/monitor/{monitorId}/checks/{checkId} para inspeccionar una comprobación. Los SDKs aplican paginación automática de forma predeterminada.
from firecrawl import Firecrawl
firecrawl = Firecrawl(api_key="fc-YOUR-API-KEY")
check = firecrawl.get_monitor_check(monitor_id, check_id, limit=25, status="changed")
for page in check.pages:
print(page.url, page.status)
if page.judgment:
print(page.judgment.meaningful, page.judgment.reason)
if page.diff and page.diff.text:
print(page.diff.text)
if page.snapshot and page.snapshot.json:
print(page.snapshot.json)
La lista de comprobaciones se puede filtrar por el status de la comprobación: queued, running, completed, failed, partial o skipped_overlap.
La respuesta de detalle de la comprobación incluye estimatedCredits, actualCredits, conteos resumidos y un array paginado de pages. estimatedCredits es la reserva máxima para la comprobación; actualCredits es el importe final cobrado una vez que Firecrawl sabe cuántas páginas cambiaron y requirieron evaluación. Usa la URL next de nivel superior para obtener la siguiente página de resultados, igual que en la paginación del rastreo. Puedes filtrar páginas por status: same, new, changed, removed o error. Cada página modificada incluye datos diff integrados; las páginas de monitores en modo JSON también incluyen un snapshot con la extracción actual.
Modo Markdown
Modo JSON
Modo mixto
{
"success": true,
"next": "https://api.firecrawl.dev/v2/monitor/019df960-06e7-7383-9d89-82c0113dc31a/checks/019df960-5f2a-75fb-a98b-bd2d32ca67d4?skip=25&limit=25",
"data": {
"id": "019df960-5f2a-75fb-a98b-bd2d32ca67d4",
"monitorId": "019df960-06e7-7383-9d89-82c0113dc31a",
"status": "completed",
"estimatedCredits": 2,
"actualCredits": 2,
"summary": {
"totalPages": 1,
"same": 0,
"changed": 1,
"new": 0,
"removed": 0,
"error": 0
},
"pages": [
{
"id": "019df960-7708-7c62-a5dc-6206f16ac122",
"targetId": "019df960-09bb-7c11-8001-1f12f50ab1c2",
"url": "https://example.com/blog",
"status": "changed",
"previousScrapeId": "019df94f-82c3-7e41-81f0-00c72b2d9c52",
"currentScrapeId": "019df960-73ee-7ac2-97a9-fb0e442c21f1",
"statusCode": 200,
"error": null,
"metadata": {
"title": "Example Blog",
"creditsUsed": 1
},
"judgment": {
"meaningful": true,
"confidence": "high",
"reason": "The page headline changed to announce a new release cadence.",
"meaningfulChanges": [
{
"type": "changed",
"before": "Welcome to our weekly update.",
"after": "Welcome to our weekly update — now with daily releases!",
"reason": "The headline changed in a way that matches the monitor goal."
}
]
},
"createdAt": "2026-05-17T15:35:00.000Z",
"diff": {
"text": "--- previous\n+++ current\n@@ -1,3 +1,3 @@\n # Latest posts\n-Welcome to our weekly update.\n+Welcome to our weekly update — now with daily releases!\n",
"json": {
"files": [
{
"from": "previous",
"to": "current",
"chunks": []
}
]
}
}
}
],
"next": "https://api.firecrawl.dev/v2/monitor/019df960-06e7-7383-9d89-82c0113dc31a/checks/019df960-5f2a-75fb-a98b-bd2d32ca67d4?skip=25&limit=25"
}
}
{
"success": true,
"data": {
"id": "019df960-5f2a-75fb-a98b-bd2d32ca67d4",
"monitorId": "019df960-06e7-7383-9d89-82c0113dc31a",
"status": "completed",
"estimatedCredits": 2,
"actualCredits": 2,
"summary": {
"totalPages": 1,
"same": 0,
"changed": 1,
"new": 0,
"removed": 0,
"error": 0
},
"pages": [
{
"id": "019df960-7708-7c62-a5dc-6206f16ac122",
"targetId": "019df960-09bb-7c11-8001-1f12f50ab1c2",
"url": "https://example.com/pricing",
"status": "changed",
"previousScrapeId": "019df94f-82c3-7e41-81f0-00c72b2d9c52",
"currentScrapeId": "019df960-73ee-7ac2-97a9-fb0e442c21f1",
"statusCode": 200,
"error": null,
"metadata": {
"title": "Pricing",
"creditsUsed": 1
},
"judgment": {
"meaningful": true,
"confidence": "high",
"reason": "The Starter plan price and Pro storage limit changed.",
"meaningfulChanges": [
{
"type": "changed",
"before": "$19/mo",
"after": "$24/mo",
"reason": "The Starter plan price changed."
},
{
"type": "changed",
"before": "10 GB storage",
"after": "25 GB storage",
"reason": "The Pro storage limit changed."
}
]
},
"createdAt": "2026-05-17T15:35:00.000Z",
"diff": {
"json": {
"plans[0].price": {
"previous": "$19/mo",
"current": "$24/mo"
},
"plans[1].features[2]": {
"previous": "10 GB storage",
"current": "25 GB storage"
}
}
},
"snapshot": {
"json": {
"plans": [
{
"name": "Starter",
"price": "$24/mo",
"features": ["Up to 3 users", "Basic analytics", "Email support"]
},
{
"name": "Pro",
"price": "$49/mo",
"features": ["Unlimited users", "Advanced analytics", "25 GB storage"]
}
]
}
}
}
]
}
}
Mixed-mode response (JSON + git-diff)
{
"success": true,
"data": {
"id": "019df960-5f2a-75fb-a98b-bd2d32ca67d4",
"monitorId": "019df960-06e7-7383-9d89-82c0113dc31a",
"status": "completed",
"estimatedCredits": 2,
"actualCredits": 2,
"summary": {
"totalPages": 1,
"same": 0,
"changed": 1,
"new": 0,
"removed": 0,
"error": 0
},
"pages": [
{
"id": "019df960-7708-7c62-a5dc-6206f16ac122",
"targetId": "019df960-09bb-7c11-8001-1f12f50ab1c2",
"url": "https://example.com/pricing",
"status": "changed",
"previousScrapeId": "019df94f-82c3-7e41-81f0-00c72b2d9c52",
"currentScrapeId": "019df960-73ee-7ac2-97a9-fb0e442c21f1",
"statusCode": 200,
"error": null,
"metadata": {
"title": "Pricing",
"creditsUsed": 1
},
"judgment": {
"meaningful": true,
"confidence": "high",
"reason": "The Starter plan price changed.",
"meaningfulChanges": [
{
"type": "changed",
"before": "Starter — $19/mo",
"after": "Starter — $24/mo",
"reason": "The Starter plan price changed."
}
]
},
"createdAt": "2026-05-17T15:35:00.000Z",
"diff": {
"text": "--- previous\n+++ current\n@@ -1,3 +1,3 @@\n # Pricing\n-Starter — $19/mo\n+Starter — $24/mo\n",
"json": {
"plans[0].price": {
"previous": "$19/mo",
"current": "$24/mo"
}
}
},
"snapshot": {
"json": {
"plans": [
{ "name": "Starter", "price": "$24/mo" },
{ "name": "Pro", "price": "$49/mo" }
]
}
}
}
]
}
}