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.
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.
La surveillance nécessite des instantanés conservés et des diffs. Elle n’est pas disponible pour les équipes Zero Data Retention.
Créez un moniteur de scrape pour une ou plusieurs URL spécifiques :
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)
Créez un moniteur de crawl pour comparer chaque page découverte lors d’un crawl à chaque vérification :
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)
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 :
{
"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 :
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
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.
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.
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 :
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 :
{
"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"
}
}
Les planifications peuvent être définies au format cron ou sous forme de texte simple en langage naturel.
{
"schedule": {
"cron": "*/30 * * * *",
"timezone": "UTC"
}
}
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.
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.
{
"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 :
{
"type": "crawl",
"url": "https://example.com/docs",
"crawlOptions": {
"limit": 100,
"includePaths": ["/docs"]
},
"scrapeOptions": {
"formats": ["markdown"]
}
}
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.
Mode markdown (par défaut)
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 :
{
"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": []
}
]
}
]
}
}
}
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.
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)
Le payload du diff ressemble à ceci : les clés sont des chemins JSON dans l’extraction, et chaque valeur est une paire {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"]
}
]
}
}
}
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.
Mode mixte (JSON + git-diff)
Si vous voulez les deux représentations — le diff structuré champ par champ et le diff unifié Markdown brut — passez les deux modes :
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 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 :
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" }
]
}
}
}
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é.
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.
{
"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 :
{
"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 :
{
"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.
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.
{
"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.
Résultats des vérifications
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.
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 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.
Mode Markdown
Mode JSON
Mode mixte
{
"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" }
]
}
}
}
]
}
}