> ## Documentation Index
> Fetch the complete documentation index at: https://firecrawl-research-index-life-sciences-docs.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Monitoring

> Programmez des scrapes et des crawls récurrents, détectez les changements de contenu et recevez des notifications par webhook ou e-mail

Le monitoring Firecrawl détecte quand le contenu d’un site web change et vous en informe par webhook ou e-mail. Les moniteurs Firecrawl exécutent régulièrement des scrapes ou des crawls et comparent chaque résultat au dernier instantané conservé. Utilisez les moniteurs pour suivre des pages produit, de la documentation, des blogs, des journaux des modifications, des sites concurrents ou toute autre page où les changements sont importants.

Chaque vérification enregistre, pour chaque page, un résultat `same`, `new`, `changed`, `removed` ou `error`. Vous pouvez recevoir un webhook dès qu’une page surveillée a fini d’être traitée, un webhook pour chaque vérification terminée, des récapitulatifs par e-mail lorsque des changements ou des erreurs surviennent, ou n’importe quelle combinaison de ces notifications.

<div id="create-a-monitor">
  ## Créer un moniteur
</div>

Créez un moniteur de scrape pour une ou plusieurs URL spécifiques :

<CodeGroup>
  ```python Python theme={null}
  from firecrawl import Firecrawl

  firecrawl = Firecrawl(
    # Aucune clé API requise pour démarrer — ajoutez-en une pour des limites de débit plus élevées :
    # 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)
  ```

  ```js Node theme={null}
  import Firecrawl from "@mendable/firecrawl-js";

  const firecrawl = new Firecrawl({
    // Aucune clé API requise pour démarrer — ajoutez-en une pour des limites de débit plus élevées :
    // apiKey: "fc-YOUR-API-KEY",
  });

  const monitor = await firecrawl.createMonitor({
    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.",
    notification: {
      email: {
        enabled: true,
        recipients: ["alerts@example.com"],
        includeDiffs: true,
      },
    },
    targets: [
      {
        type: "scrape",
        urls: ["https://news.ycombinator.com"],
      },
    ],
  });

  console.log(monitor.id);
  ```

  ```bash cURL theme={null}
  curl -s -X POST "https://api.firecrawl.dev/v2/monitor" \
    -H "Authorization: Bearer $FIRECRAWL_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "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.",
      "notification": {
        "email": {
          "enabled": true,
          "recipients": ["alerts@example.com"],
          "includeDiffs": true
        }
      },
      "targets": [
        {
          "type": "scrape",
          "urls": ["https://news.ycombinator.com"]
        }
      ]
    }'
  ```
</CodeGroup>

Créez un moniteur de crawl pour comparer chaque page découverte lors d’un crawl à chaque vérification :

<CodeGroup>
  ```python Python theme={null}
  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)
  ```

  ```js Node theme={null}
  import Firecrawl from "@mendable/firecrawl-js";

  const firecrawl = new Firecrawl({ apiKey: "fc-YOUR-API-KEY" });

  const monitor = await firecrawl.createMonitor({
    name: "Docs monitor",
    schedule: { cron: "7-59/15 * * * *", timezone: "UTC" },
    webhook: {
      url: "https://example.com/webhooks/firecrawl",
      events: ["monitor.page", "monitor.check.completed"],
    },
    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,
        },
      },
    ],
  });

  console.log(monitor.id);
  ```

  ```bash cURL theme={null}
  curl -s -X POST "https://api.firecrawl.dev/v2/monitor" \
    -H "Authorization: Bearer $FIRECRAWL_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "Docs monitor",
      "schedule": {
        "cron": "7-59/15 * * * *",
        "timezone": "UTC"
      },
      "webhook": {
        "url": "https://example.com/webhooks/firecrawl",
        "events": ["monitor.page", "monitor.check.completed"]
      },
      "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
          }
        }
      ]
    }'
  ```
</CodeGroup>

Chaque appel de création renvoie le nouveau moniteur avec son cron normalisé, son `nextRunAt` calculé et `estimatedCreditsPerMonth`. Lorsque l’évaluation est activée, `estimatedCreditsPerMonth` est une estimation maximale, car les crédits d’évaluation ne sont facturés que pour les pages modifiées effectivement évaluées :

```json Response theme={null}
{
  "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"
  }
}
```

Vous pouvez également créer des moniteurs depuis la CLI Firecrawl :

```bash CLI theme={null}
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
```

<div id="goals-and-judging">
  ## Objectifs et évaluation
</div>

Ajoutez un `goal` en langage clair si vous souhaitez être alerté uniquement en cas de changements significatifs. Si `goal` est présent et que `judgeEnabled` est omis, Firecrawl active automatiquement l’évaluation. L’évaluation s’exécute sur les pages modifiées et renvoie un `judgment` avec `meaningful`, `confidence`, `reason` et `meaningfulChanges`.

Utilisez `judgeEnabled: false` si vous souhaitez enregistrer un objectif sans encore évaluer les changements. L’évaluation ne s’exécute que lorsque le moniteur comporte à la fois `judgeEnabled` et un `goal` non vide.

<Note>
  Chaque vérification facture toujours les scrapes ou crawls sous-jacents. Si l’évaluation est activée, elle ajoute 1 crédit pour chaque page modifiée qu’elle valide. Les vérifications sans page modifiée n’utilisent pas de crédits d’évaluation.
</Note>

Les bons objectifs sont courts et explicites : indiquez ce qui doit déclencher une alerte, précisez tout critère de portée comme top N, prix, type de poste, entreprise, région, sujet, état ou entité, et n’incluez des exclusions que lorsqu’elles font partie de l’intention. Si l’objectif est large, laissez-le large ; par exemple, "any change" ne doit pas ajouter de filtres antiparasite qui masqueraient des changements.

Par exemple, un moniteur avec cet objectif :

```text theme={null}
Alerter lorsqu'un nouvel article Hacker News lié à l'IA entre dans le top 10. Ignorer les modifications d'articles qui ne concernent pas l'IA. Ne pas alerter pour les modifications en dehors du top 10.
```

pourrait produire un webhook `monitor.page` comme celui-ci lorsqu’un article correspondant entre dans le champ défini :

```json monitor.page theme={null}
{
  "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"
  }
}
```

<div id="schedules">
  ## Planifications
</div>

Les planifications peuvent être définies au format cron ou sous forme de texte simple en langage naturel.

<CodeGroup>
  ```json Cron theme={null}
  {
    "schedule": {
      "cron": "*/30 * * * *",
      "timezone": "UTC"
    }
  }
  ```

  ```json Text theme={null}
  {
    "schedule": {
      "text": "every 30 minutes",
      "timezone": "UTC"
    }
  }
  ```
</CodeGroup>

Exemples pris en charge en langage naturel :

* `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`

L'intervalle minimal est de 15 minutes. Les réponses de l'API renvoient toujours l'expression cron normalisée. Pour les planifications en texte libre, `timezone` détermine quand des expressions comme `daily at 9am` s'exécutent. Les planifications en texte libre sont réparties selon l'identifiant du moniteur avant d'être converties en cron, afin que de nombreux moniteurs ne s'exécutent pas tous au même instant.

<div id="targets">
  ## Cibles
</div>

Les moniteurs prennent en charge deux types de cibles :

* `scrape` : exécute un scraping par URL dans `urls`.
* `crawl` : exécute un crawl complet pour `url` à chaque vérification, puis compare toutes les pages découvertes.

Chaque moniteur accepte de 1 à 50 cibles. `retentionDays` vaut par défaut `30` et peut être défini jusqu’à `365`.

Les options de scraping de chaque cible sont transmises aux tâches de scraping sous-jacentes. Pour les scrapes déclenchés par le moniteur, `maxAge` vaut par défaut `0`, de sorte que chaque vérification lance un nouveau scraping, sauf si vous définissez explicitement une autre valeur pour `maxAge`.

```json Scrape target theme={null}
{
  "type": "scrape",
  "urls": ["https://example.com/pricing"],
  "scrapeOptions": {
    "formats": ["markdown"],
    "maxAge": 0
  }
}
```

Pour les cibles de crawl, utilisez `crawlOptions` pour le comportement du crawl et `scrapeOptions` pour le scraping de chaque page :

```json Crawl target theme={null}
{
  "type": "crawl",
  "url": "https://example.com/docs",
  "crawlOptions": {
    "limit": 100,
    "includePaths": ["/docs"]
  },
  "scrapeOptions": {
    "formats": ["markdown"]
  }
}
```

<div id="change-tracking">
  ## Suivi des modifications
</div>

Par défaut, Firecrawl calcule les différences dans le markdown de chaque page et indique `same`, `changed`, `new`, `removed` ou `error`. Si vous souhaitez détecter des modifications dans des **champs structurés précis** (prix, titre, indicateur de disponibilité, éléments d’une liste, etc.), activez le suivi des modifications en mode JSON en ajoutant le format `suiviDesModifications` avec `modes: ["json"]` aux `scrapeOptions` de la cible.

<div id="markdown-mode-default">
  ### Mode markdown (par défaut)
</div>

Lorsque `scrapeOptions.formats` vaut simplement `["markdown"]`, chaque page modifiée dans la réponse de vérification inclut un diff textuel unifié ainsi qu’un AST au format [parseDiff](https://github.com/sergeyt/parse-diff) :

```json Markdown-mode diff theme={null}
{
  "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": []
            }
          ]
        }
      ]
    }
  }
}
```

<div id="json-mode">
  ### mode JSON
</div>

Transmettez un format `changeTracking` avec `modes: ["json"]`, ainsi qu’un schéma JSON (ou un `prompt`) décrivant les champs qui vous intéressent. Firecrawl extrait ce JSON à chaque vérification et génère un **diff par champ** indexé par le chemin du champ, ainsi qu’un `snapshot.json` contenant l’extraction complète actuelle, afin que les consommateurs n’aient pas à récupérer à nouveau le scrape sous-jacent.

<CodeGroup>
  ```python Python theme={null}
  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)
  ```

  ```js Node theme={null}
  import Firecrawl from "@mendable/firecrawl-js";
  import { z } from "zod";

  const firecrawl = new Firecrawl({ apiKey: "fc-YOUR-API-KEY" });

  const pricingSchema = z.object({
    plans: z.array(
      z.object({
        name: z.string(),
        price: z.string(),
        features: z.array(z.string()),
      }),
    ),
  });

  const monitor = await firecrawl.createMonitor({
    name: "Pricing monitor",
    schedule: { text: "hourly", timezone: "UTC" },
    goal: "Notify me when a pricing tier, price, or headline feature changes",
    notification: {
      email: {
        enabled: true,
        recipients: ["alerts@example.com"],
        includeDiffs: true,
      },
    },
    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: pricingSchema,
            },
          ],
        },
      },
    ],
  });

  console.log(monitor.id);
  ```

  ```bash cURL theme={null}
  curl -s -X POST "https://api.firecrawl.dev/v2/monitor" \
    -H "Authorization: Bearer $FIRECRAWL_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "Pricing monitor",
      "schedule": {
        "text": "hourly",
        "timezone": "UTC"
      },
      "goal": "Notify me when a pricing tier, price, or headline feature changes",
      "notification": {
        "email": {
          "enabled": true,
          "recipients": ["alerts@example.com"],
          "includeDiffs": true
        }
      },
      "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": {
                  "type": "object",
                  "properties": {
                    "plans": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "name": { "type": "string" },
                          "price": { "type": "string" },
                          "features": {
                            "type": "array",
                            "items": { "type": "string" }
                          }
                        }
                      }
                    }
                  }
                }
              }
            ]
          }
        }
      ]
    }'
  ```
</CodeGroup>

Le payload du diff ressemble à ceci : les clés sont des chemins JSON dans l’extraction, et chaque valeur est une paire `{previous, current}` :

```json JSON-mode diff theme={null}
{
  "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"]
        }
      ]
    }
  }
}
```

<Note>
  Même si aucun champ suivi n’a changé, mais que le markdown environnant a changé, les moniteurs en mode JSON continuent de signaler `same`, sauf si vous activez aussi git-diff (voir le mode mixte ci-dessous). Le diff se concentre uniquement sur les champs de votre schéma.
</Note>

<div id="mixed-mode-json-git-diff">
  ### Mode mixte (JSON + git-diff)
</div>

Si vous voulez les deux représentations — le diff structuré champ par champ **et** le diff unifié Markdown brut — passez les deux modes :

```json Mixed target (JSON + git-diff) theme={null}
{
  "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 réponse de vérification contient alors à la fois `diff.text` (sidecar Markdown) et `diff.json` (diff champ par champ), ainsi que l'extraction `snapshot.json` :

```json Mixed-mode diff (JSON + git-diff) theme={null}
{
  "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" }
      ]
    }
  }
}
```

Une page en mode mixte est marquée comme `changed` dès que **l'une ou l'autre** de ces deux représentations a changé.

<div id="notifications">
  ## Notifications
</div>

<div id="webhooks">
  ### Webhooks
</div>

Lorsqu'un moniteur dispose d'un `webhook`, Firecrawl peut envoyer deux événements de moniteur :

* `monitor.page` : envoyé à mesure que chaque scrape surveillé se termine dans le worker de scrape.
* `monitor.check.completed` : envoyé une fois la vérification complète consolidée. Inclut l'état de la vérification et des totaux récapitulatifs. Utilisez les événements `monitor.page` ou l'API de vérification du moniteur pour obtenir des résultats au niveau des pages.

`monitor.page` inclut `isMeaningful` et `judgment` lorsque l'évaluation des changements significatifs a été exécutée pour une page modifiée.

```json Webhook config theme={null}
{
  "webhook": {
    "url": "https://example.com/webhooks/firecrawl",
    "headers": {
      "Authorization": "Bearer your-secret"
    },
    "metadata": {
      "environment": "production"
    },
    "events": ["monitor.page", "monitor.check.completed"]
  }
}
```

payload de `monitor.page` :

```json monitor.page theme={null}
{
  "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"
  }
}
```

payload de `monitor.check.completed` :

```json monitor.check.completed theme={null}
{
  "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` vaut `true` lorsque la vérification s'est terminée sans erreur de page. Il vaut `false` pour les vérifications en échec ou partielles, et `error` contient la raison de l'échec lorsqu'elle est disponible.

<div id="email">
  ### E-mail
</div>

Les résumés par e-mail ne sont envoyés que lorsqu'une vérification comporte des pages modifiées, nouvelles, supprimées ou en erreur.

```json Email config theme={null}
{
  "notification": {
    "email": {
      "enabled": true,
      "recipients": ["alerts@example.com"],
      "includeDiffs": true
    }
  }
}
```

Lorsqu'un moniteur a un objectif et que l'évaluation est activée, les résumés par e-mail donnent la priorité aux pages modifiées pertinentes. Si toutes les pages modifiées sont considérées comme du bruit et qu'il n'y a aucune page nouvelle, supprimée ou en erreur, l'e-mail n'est pas envoyé.

Si `recipients` est omis, Firecrawl envoie les e-mails aux membres de l'équipe autorisés à recevoir les e-mails d'alerte système.
Vous pouvez configurer jusqu'à 25 destinataires spécifiés explicitement.

<div id="recipient-confirmation-process">
  #### Processus de confirmation du destinataire
</div>

Lorsqu’un nouveau destinataire est ajouté à un moniteur, Firecrawl lui envoie un e-mail contenant un lien de confirmation. Cela garantit qu’il accepte explicitement de recevoir des notifications pour ce moniteur. Si le destinataire est déjà membre de l’équipe, aucune confirmation n’est requise.

<div id="check-results">
  ## Résultats des vérifications
</div>

Utilisez `GET /v2/monitor/{monitorId}/checks` pour lister les vérifications, et `GET /v2/monitor/{monitorId}/checks/{checkId}` pour consulter le détail d’une vérification. Les SDKs gèrent automatiquement la pagination par défaut.

<CodeGroup>
  ```python Python theme={null}
  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)
  ```

  ```js Node theme={null}
  import Firecrawl from "@mendable/firecrawl-js";

  const firecrawl = new Firecrawl({ apiKey: "fc-YOUR-API-KEY" });

  const check = await firecrawl.getMonitorCheck(monitorId, checkId, {
    limit: 25,
    status: "changed",
  });

  for (const page of check.pages) {
    console.log(page.url, page.status);

    if (page.judgment) {
      console.log(page.judgment.meaningful, page.judgment.reason);
    }

    if (page.diff?.text) {
      console.log(page.diff.text);
    }

    if (page.snapshot?.json) {
      console.log(page.snapshot.json);
    }
  }
  ```

  ```bash cURL theme={null}
  curl "https://api.firecrawl.dev/v2/monitor/$MONITOR_ID/checks/$CHECK_ID?limit=25&status=changed" \
    -H "Authorization: Bearer $FIRECRAWL_API_KEY"
  ```
</CodeGroup>

La liste des vérifications peut être filtrée selon le `status` de la vérification : `queued`, `running`, `completed`, `failed`, `partial` ou `skipped_overlap`.

La réponse détaillée d’une vérification inclut `estimatedCredits`, `actualCredits`, des compteurs récapitulatifs et un tableau `pages` paginé. `estimatedCredits` correspond au plafond réservé pour la vérification ; `actualCredits` correspond au montant final facturé une fois que Firecrawl sait combien de pages ont changé et ont nécessité une analyse. Utilisez l’URL `next` au niveau racine pour récupérer la page de résultats suivante, conformément à la pagination du crawl. Vous pouvez filtrer les pages par `status` : `same`, `new`, `changed`, `removed` ou `error`. Chaque page modifiée inclut des données `diff` inline ; les pages des moniteurs en mode JSON incluent également un `snapshot` avec l’extraction actuelle.

<Tabs>
  <Tab title="Mode Markdown">
    ```json Markdown-mode response theme={null}
    {
      "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"
      }
    }
    ```
  </Tab>

  <Tab title="Mode JSON">
    ```json JSON-mode response theme={null}
    {
      "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"]
                  }
                ]
              }
            }
          }
        ]
      }
    }
    ```
  </Tab>

  <Tab title="Mode mixte">
    ```json Mixed-mode response (JSON + git-diff) theme={null}
    {
      "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" }
                ]
              }
            }
          }
        ]
      }
    }
    ```
  </Tab>
</Tabs>

<div id="pricing">
  ## Tarification
</div>

Les moniteurs n'entraînent pas de frais distincts par moniteur. Chaque vérification consomme les crédits du scrape ou du crawl sous-jacent qu'elle exécute, plus un crédit optionnel par page modifiée lorsque l'évaluation des changements significatifs est activée.

| Composant                                                  | Crédits                                                            |
| ---------------------------------------------------------- | ------------------------------------------------------------------ |
| Moniteur de scrape                                         | 1 crédit par URL et par vérification                               |
| Moniteur de crawl                                          | 1 crédit par page découverte et par vérification                   |
| Évaluation des changements significatifs activée           | 1 crédit supplémentaire par page modifiée validée par l'évaluateur |
| Options de format (JSON, PDF, question, mode avancé, etc.) | Identique à un [scrape](/fr/features/scrape) autonome              |

<div id="api-reference">
  ## Référence de l’API
</div>

* [Créer un moniteur](/fr/api-reference/endpoint/monitor-create)
* [Lister les moniteurs](/fr/api-reference/endpoint/monitor-list)
* [Obtenir un moniteur](/fr/api-reference/endpoint/monitor-get)
* [Mettre à jour un moniteur](/fr/api-reference/endpoint/monitor-update)
* [Supprimer un moniteur](/fr/api-reference/endpoint/monitor-delete)
* [Exécuter un moniteur](/fr/api-reference/endpoint/monitor-run)
* [Lister les vérifications du moniteur](/fr/api-reference/endpoint/monitor-checks-list)
* [Obtenir une vérification du moniteur](/fr/api-reference/endpoint/monitor-check-get)
* [Payload du webhook de page du moniteur](/fr/api-reference/endpoint/webhook-monitor-page)
* [Payload du webhook de vérification du moniteur terminé](/fr/api-reference/endpoint/webhook-monitor-check-completed)
