Saltar al contenido principal
Seguimiento de cambios El seguimiento de cambios compara el contenido actual de una página con el de la última vez que la extrajiste con scraping. Añade changeTracking a tu array de formats para detectar si una página es nueva, no ha cambiado o se ha modificado y, opcionalmente, obtener un diff estructurado de lo que cambió.
  • Funciona con /scrape, /crawl y /batch/scrape
  • Dos modos de diff: git-diff para cambios a nivel de línea y json para comparación a nivel de campo
  • Acotado a tu equipo y, opcionalmente, a una etiqueta que especifiques

Cómo funciona

Cada extracción con changeTracking habilitado almacena una captura y la compara con la captura anterior para esa URL.
ExtracciónResultado
Primera vezchangeStatus: "new" (no existe una versión anterior)
Contenido sin cambioschangeStatus: "same"
Contenido modificadochangeStatus: "changed" (datos de diff disponibles)
Página eliminadachangeStatus: "removed"
La respuesta incluye estos campos en el objeto changeTracking:
CampoTipoDescripción
previousScrapeAtstring | nullMarca de tiempo de la extracción anterior (null en la primera extracción)
changeStatusstring"new", "same", "changed" o "removed"
visibilitystring"visible" (detectable a través de enlaces/sitemap) o "hidden" (la URL funciona pero ya no está enlazada)
diffobject | undefinedDiff a nivel de línea (solo presente en modo git-diff cuando el estado es "changed")
jsonobject | undefinedComparación a nivel de campo (solo presente en modo json cuando el estado es "changed")

Uso básico

Incluye tanto markdown como changeTracking en el array formats. El formato markdown es obligatorio porque el seguimiento de cambios compara las páginas según su contenido en markdown.
from firecrawl import Firecrawl

firecrawl = Firecrawl(api_key="fc-YOUR-API-KEY")

result = firecrawl.scrape(
    "https://example.com/pricing",
    formats=["markdown", "changeTracking"]
)

print(result.changeTracking)

Respuesta

En el primer scraping, changeStatus es "new" y previousScrapeAt es null:
{
  "success": true,
  "data": {
    "markdown": "# Pricing\n\nStarter: $9/mo\nPro: $29/mo...",
    "changeTracking": {
      "previousScrapeAt": null,
      "changeStatus": "new",
      "visibility": "visible"
    }
  }
}
En scrapes posteriores, changeStatus indica si el contenido ha cambiado:
{
  "success": true,
  "data": {
    "markdown": "# Pricing\n\nStarter: $12/mo\nPro: $39/mo...",
    "changeTracking": {
      "previousScrapeAt": "2025-06-01T10:00:00.000+00:00",
      "changeStatus": "changed",
      "visibility": "visible"
    }
  }
}

Modo git-diff

El modo git-diff retorna cambios línea por línea en un formato similar a git diff. Pasa un objeto dentro del array formats con modes: ["git-diff"]:
result = firecrawl.scrape(
    "https://example.com/pricing",
    formats=[
        "markdown",
        {
            "type": "changeTracking",
            "modes": ["git-diff"]
        }
    ]
)

if result.changeTracking.changeStatus == "changed":
    print(result.changeTracking.diff.text)

Respuesta

El objeto diff contiene tanto un diff en texto plano como una representación JSON estructurada:
{
  "changeTracking": {
    "previousScrapeAt": "2025-06-01T10:00:00.000+00:00",
    "changeStatus": "changed",
    "visibility": "visible",
    "diff": {
      "text": "@@ -1,3 +1,3 @@\n # Pricing\n-Starter: $9/mo\n-Pro: $29/mo\n+Starter: $12/mo\n+Pro: $39/mo",
      "json": {
        "files": [{
          "chunks": [{
            "content": "@@ -1,3 +1,3 @@",
            "changes": [
              { "type": "normal", "content": "# Pricing" },
              { "type": "del", "ln": 2, "content": "Starter: $9/mo" },
              { "type": "del", "ln": 3, "content": "Pro: $29/mo" },
              { "type": "add", "ln": 2, "content": "Starter: $12/mo" },
              { "type": "add", "ln": 3, "content": "Pro: $39/mo" }
            ]
          }]
        }]
      }
    }
  }
}
El objeto estructurado diff.json contiene:
  • files: matriz de archivos modificados (generalmente uno por página web)
  • chunks: secciones de cambios dentro de un archivo
  • changes: cambios de líneas individuales con type ("add", "del" o "normal"), número de línea (ln) y content

modo JSON

El modo json extrae campos específicos tanto de la versión actual como de la versión anterior de la página usando un esquema que defines. Esto es útil para hacer un seguimiento de cambios en datos estructurados como precios, niveles de stock o metadatos sin tener que analizar un diff completo. Pasa modes: ["json"] con un schema que defina los campos a extraer:
result = firecrawl.scrape(
    "https://example.com/product/widget",
    formats=[
        "markdown",
        {
            "type": "changeTracking",
            "modes": ["json"],
            "schema": {
                "type": "object",
                "properties": {
                    "price": { "type": "string" },
                    "availability": { "type": "string" }
                }
            }
        }
    ]
)

if result.changeTracking.changeStatus == "changed":
    changes = result.changeTracking.json
    print(f"Price: {changes['price']['previous']}{changes['price']['current']}")

Respuesta

Cada campo del esquema se devuelve con valores previous y current:
{
  "changeTracking": {
    "previousScrapeAt": "2025-06-05T08:00:00.000+00:00",
    "changeStatus": "changed",
    "visibility": "visible",
    "json": {
      "price": {
        "previous": "$19.99",
        "current": "$24.99"
      },
      "availability": {
        "previous": "In Stock",
        "current": "In Stock"
      }
    }
  }
}
También puedes proporcionar un prompt opcional para guiar la extracción mediante el LLM junto con el esquema.
El modo JSON usa extracción con LLM y cuesta 5 créditos por página. El seguimiento básico de cambios y el modo git-diff no tienen costo adicional.

Uso de etiquetas

De forma predeterminada, el seguimiento de cambios se compara con el scrape más reciente de la misma URL realizado por tu equipo. Las etiquetas te permiten mantener historiales de seguimiento independientes para la misma URL, lo cual es útil cuando supervisas la misma página en diferentes intervalos o en distintos contextos.
# Monitoreo por hora (comparado con el último scrape con etiqueta "hourly")
result = firecrawl.scrape(
    "https://example.com/pricing",
    formats=[
        "markdown",
        { "type": "changeTracking", "tag": "hourly" }
    ]
)

# Resumen diario (comparado con el último scrape con etiqueta "daily")
result = firecrawl.scrape(
    "https://example.com/pricing",
    formats=[
        "markdown",
        { "type": "changeTracking", "tag": "daily" }
    ]
)

Rastreo con seguimiento de cambios

Añade seguimiento de cambios a las operaciones de rastreo para supervisar un sitio completo en busca de cambios. Pasa el formato changeTracking dentro de scrapeOptions:
result = firecrawl.crawl(
    "https://example.com",
    limit=50,
    scrape_options={
        "formats": ["markdown", "changeTracking"]
    }
)

for page in result.data:
    status = page.changeTracking.changeStatus
    url = page.metadata.url
    print(f"{url}: {status}")

Extracción por lotes con seguimiento de cambios

Usa batch scrape para supervisar un conjunto específico de URL:
result = firecrawl.batch_scrape(
    [
        "https://example.com/pricing",
        "https://example.com/product/widget",
        "https://example.com/blog/latest"
    ],
    formats=["markdown", {"type": "changeTracking", "modes": ["git-diff"]}]
)

Programar el seguimiento de cambios

El seguimiento de cambios es más útil cuando haces scraping a intervalos regulares. Puedes automatizarlo con cron, planificadores en la nube o herramientas de orquestación de flujos de trabajo.

Tarea cron

Crea un script que haga scraping de una URL y notifique cuando haya cambios:
check-pricing.sh
#!/bin/bash
RESPONSE=$(curl -s -X POST "https://api.firecrawl.dev/v2/scrape" \
  -H "Authorization: Bearer $FIRECRAWL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://competitor.com/pricing",
    "formats": [
      "markdown",
      {
        "type": "changeTracking",
        "modes": ["json"],
        "schema": {
          "type": "object",
          "properties": {
            "starter_price": { "type": "string" },
            "pro_price": { "type": "string" }
          }
        }
      }
    ]
  }')

STATUS=$(echo "$RESPONSE" | jq -r '.data.changeTracking.changeStatus')

if [ "$STATUS" = "changed" ]; then
  echo "$RESPONSE" | jq '.data.changeTracking.json'
  # Envía alerta por correo electrónico, Slack, etc.
fi
Programa la tarea con crontab -e:
0 */6 * * * /path/to/check-pricing.sh >> /var/log/price-monitor.log 2>&1
ProgramaciónExpresión
Cada hora0 * * * *
Cada 6 horas0 */6 * * *
Todos los días a las 09:000 9 * * *
Todos los lunes a las 08:000 8 * * 1

Planificadores en la nube y sin servidor

  • AWS: regla de EventBridge que invoca una función Lambda
  • GCP: Cloud Scheduler que invoca una Cloud Function
  • Vercel / Netlify: funciones serverless activadas mediante cron
  • GitHub Actions: flujos de trabajo programados con los desencadenadores schedule y cron

Automatización de flujos de trabajo

Plataformas sin código como n8n, Zapier y Make pueden llamar periódicamente a la API de Firecrawl y enrutar los resultados a Slack, correo electrónico o bases de datos. Consulta las guías sobre automatización de flujos de trabajo.

Webhooks

Para operaciones asíncronas como crawl y batch scrape, usa webhooks para recibir resultados de seguimientoDeCambios a medida que llegan en lugar de hacer polling.
job = firecrawl.start_crawl(
    "https://example.com",
    limit=50,
    scrape_options={
        "formats": [
            "markdown",
            {"type": "changeTracking", "modes": ["git-diff"]}
        ]
    },
    webhook={
        "url": "https://your-server.com/firecrawl-webhook",
        "headers": {"Authorization": "Bearer your-webhook-secret"},
        "events": ["crawl.page", "crawl.completed"]
    }
)
El payload del evento crawl.page incluye el objeto changeTracking para cada página:
{
  "success": true,
  "type": "crawl.page",
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "data": [{
    "markdown": "# Pricing\n\nStarter: $12/mo...",
    "metadata": {
      "title": "Pricing",
      "url": "https://example.com/pricing",
      "statusCode": 200
    },
    "changeTracking": {
      "previousScrapeAt": "2025-06-05T12:00:00.000+00:00",
      "changeStatus": "changed",
      "visibility": "visible",
      "diff": {
        "text": "@@ -2,1 +2,1 @@\n-Starter: $9/mo\n+Starter: $12/mo"
      }
    }
  }]
}
Para más detalles sobre la configuración de webhooks (encabezados, metadatos, eventos, reintentos, verificación de firma), consulta la documentación de webhooks.

Referencia de configuración

El conjunto completo de opciones disponibles al pasar un objeto de formato seguimientoDeCambios:
ParameterTypeDefaultDescription
typestring(required)Debe ser "changeTracking"
modesstring[][]Modos de diff a habilitar: "git-diff", "json" o ambos
schemaobject(none)JSON Schema para la comparación a nivel de campo (requerido para el modo json)
promptstring(none)Prompt personalizado para guiar la extracción del LLM (usado con el modo json)
tagstringnullIdentificador independiente para el historial de seguimiento

Modelos de datos

interface ChangeTrackingResult {
  previousScrapeAt: string | null;
  changeStatus: "new" | "same" | "changed" | "removed";
  visibility: "visible" | "hidden";
  diff?: {
    text: string;
    json: {
      files: Array<{
        from: string | null;
        to: string | null;
        chunks: Array<{
          content: string;
          changes: Array<{
            type: "add" | "del" | "normal";
            ln?: number;
            ln1?: number;
            ln2?: number;
            content: string;
          }>;
        }>;
      }>;
    };
  };
  json?: Record<string, { previous: any; current: any }>;
}

Detalles importantes

El formato markdown siempre debe incluirse junto con changeTracking. El seguimiento de cambios compara las páginas mediante su contenido en markdown.
  • Alcance: Las comparaciones se limitan a tu equipo. La primera extracción de cualquier URL devuelve "new", incluso si otros usuarios ya la han extraído.
  • Coincidencia de URL: Las extracciones anteriores se asocian por la URL de origen exacta, el ID de equipo, el formato markdown y la tag. Mantén las URLs consistentes entre extracciones.
  • Consistencia de parámetros: Usar configuraciones diferentes de includeTags, excludeTags u onlyMainContent en extracciones de la misma URL produce comparaciones poco fiables.
  • Algoritmo de comparación: El algoritmo es resistente a cambios en espacios en blanco y en el orden del contenido. Se ignoran las URLs de origen de iframes para manejar la aleatorización de captcha/antibot.
  • Caché: Las solicitudes con changeTracking omiten la caché del índice. Se ignora el parámetro maxAge.
  • Manejo de errores: Supervisa el campo warning en las respuestas y contempla el caso en que el objeto changeTracking pueda estar ausente (esto puede ocurrir si la consulta a la base de datos para la extracción previa excede el tiempo de espera).

Facturación

ModoCosto
Seguimiento básico de cambiosSin costo adicional (créditos de scraping estándar)
Modo git-diffSin costo adicional
Modo json5 créditos por página