Change Tracking(変更追跡)は、ページの現在のコンテンツを最後にスクレイプしたときの状態と比較します。ページが新規か、変更なし (unchanged) か、変更あり (modified) かを検出するために changeTracking を formats 配列に追加し、必要に応じて「何が変わったか」の構造化された差分を取得できます。
/scrape、/crawl、/batch/scrape で動作
- 2 つの diff モード: 行単位の変更用
git-diff、フィールド単位の比較用 json
- チームごとにスコープされ、必要に応じて渡したタグごとにもスコープ可能
changeTracking が有効なすべてのスクレイプ実行時にスナップショットが保存され、その URL に対する前回のスナップショットと比較されます。
| Scrape | Result |
|---|
| First time | changeStatus: "new"(前のバージョンが存在しない) |
| Content unchanged | changeStatus: "same"(コンテンツに変更なし) |
| Content modified | changeStatus: "changed"(コンテンツが変更され、差分データあり) |
| Page removed | changeStatus: "removed"(ページが削除された) |
レスポンスには、changeTracking オブジェクト内に次のフィールドが含まれます。
| Field | Type | Description |
|---|
previousScrapeAt | string | null | 前回スクレイプのタイムスタンプ(初回スクレイプ時は null) |
changeStatus | string | "new"、"same"、"changed"、または "removed" |
visibility | string | "visible"(リンクやサイトマップ経由で検出可能)または "hidden"(URL は有効だが、もはやリンクされていない) |
diff | object | undefined | 行レベルの差分(ステータスが "changed" のときに git-diff モードでのみ含まれる) |
json | object | undefined | フィールドレベルの比較(ステータスが "changed" のときに json モードでのみ含まれる) |
formats 配列には markdown と changeTracking の両方を指定します。変更追跡ではページ同士を markdown コンテンツとして比較するため、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)
初回のスクレイプでは、changeStatus は "new"、previousScrapeAt は null になります。
{
"success": true,
"data": {
"markdown": "# Pricing\n\nStarter: $9/mo\nPro: $29/mo...",
"changeTracking": {
"previousScrapeAt": null,
"changeStatus": "new",
"visibility": "visible"
}
}
}
以降のスクレイプでは、changeStatus にコンテンツが変更されたかどうかが反映されます。
{
"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"
}
}
}
git-diff モードは、git diff に似た形式で行単位の変更差分を返します。formats 配列内に 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)
diff オブジェクトには、プレーンテキスト形式の diff と構造化された JSON 表現の両方が含まれます。
{
"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" }
]
}]
}]
}
}
}
}
構造化された diff.json オブジェクトには次の要素が含まれます:
files: 変更されたファイルの配列(通常はウェブページごとに1つ)
chunks: ファイル内の変更箇所を表すセクション
changes: 個々の行ごとの変更。type("add"、"del"、または "normal")、行番号(ln)、および content を含む
json モードは、定義したスキーマを使って、ページの現在のバージョンと前回のバージョンの両方から特定のフィールドを抽出します。これは、ページ全体の差分を解析することなく、価格、在庫レベル、メタデータなどの構造化データの変更を追跡するのに便利です。
抽出するフィールドを定義する schema とともに modes: ["json"] を渡します:
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']}")
スキーマ内の各フィールドは、previous と 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": "在庫あり",
"current": "在庫あり"
}
}
}
}
また、任意の prompt を渡して、スキーマとあわせて LLM による抽出をガイドすることもできます。
JSONモードは LLM 抽出を使用し、1ページあたり5クレジットかかります。基本的な変更追跡と git-diff モードには追加コストは発生しません。
デフォルトでは、変更追跡(change tracking)は、チームによって同じ URL に対して実行された直近のスクレイプ結果と比較します。タグを使うと、同じ URL に対して別々の追跡履歴を維持できます。同じページを異なる間隔や異なるコンテキストで監視したい場合に便利です。
# 毎時監視(直近の「hourly」スクレイプ結果と比較)
result = firecrawl.scrape(
"https://example.com/pricing",
formats=[
"markdown",
{ "type": "changeTracking", "tag": "hourly" }
]
)
# 日次サマリー(直近の「daily」スクレイプ結果と比較)
result = firecrawl.scrape(
"https://example.com/pricing",
formats=[
"markdown",
{ "type": "changeTracking", "tag": "daily" }
]
)
change tracking を利用したクロール
サイト全体の変更を監視するために、クロール処理に change tracking を追加します。scrapeOptions 内で changeTracking フォーマットを指定します。
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}")
changeTracking を使ったバッチスクレイプ
特定の URL 群を監視するには、batch scrape を使用します:
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"]}]
)
変更追跡は、定期的にスクレイピングを行う場合に最も効果を発揮します。cron、クラウドスケジューラ、ワークフローツールなどで自動化できます。
URLをスクレイピングし、変更を検知したらアラートを送るスクリプトを作成します。
#!/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'
# メール、Slackなどでアラートを送信
fi
crontab -e でスケジュールを設定します:
0 */6 * * * /path/to/check-pricing.sh >> /var/log/price-monitor.log 2>&1
| スケジュール | 表現 |
|---|
| 毎時 | 0 * * * * |
| 6時間ごと | 0 */6 * * * |
| 毎日午前9時 | 0 9 * * * |
| 毎週月曜日午前8時 | 0 8 * * 1 |
- AWS: EventBridge ルールによる Lambda 関数のトリガー
- GCP: Cloud Scheduler による Cloud Function のトリガー
- Vercel / Netlify: Cron によってトリガーされるサーバーレス関数
- GitHub Actions:
schedule および cron トリガーによるスケジュールされたワークフロー
n8n、Zapier、Make のようなノーコードプラットフォームから、スケジュール実行で Firecrawl API を呼び出し、結果を Slack、メール、データベースなどに送信できます。ワークフロー自動化ガイドも参照してください。
crawl や batch scrape のような非同期処理では、ポーリングするのではなく webhooks を使用して、到着しだい changeTracking の結果を受け取れます。
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"]
}
)
crawl.page イベントのペイロードには、各ページごとに changeTracking オブジェクトが含まれています。
{
"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"
}
}
}]
}
Webhook の構成の詳細(ヘッダー、メタデータ、イベント、再試行、署名検証)については、Webhook ドキュメントを参照してください。
changeTracking フォーマットオブジェクトを渡すときに利用できるオプション一覧:
| Parameter | Type | Default | Description |
|---|
type | string | (required) | "changeTracking" でなければなりません |
modes | string[] | [] | 有効化する差分モード: "git-diff"、"json"、またはその両方 |
schema | object | (none) | フィールド単位の比較用の JSON Schema(json モードでは必須) |
prompt | string | (none) | LLM による抽出を制御するためのカスタムプロンプト(json モードで使用) |
tag | string | null | 独立したトラッキング履歴用の識別子 |
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 }>;
}
changeTracking を使う場合は、必ず markdown フォーマットも同時に指定してください。変更追跡は、ページをその markdown コンテンツに基づいて比較します。
- スコープ: 比較はチーム内に限定されます。任意の URL をチームとして初めてスクレイプした場合は、他のユーザーが同じ URL をスクレイプしていても
"new" が返されます。
- URL のマッチング: 過去のスクレイプは、ソース URL、チーム ID、
markdown フォーマット、tag が完全一致したものと照合されます。スクレイプ間で URL を一貫させてください。
- パラメータの一貫性: 同じ URL に対して異なる
includeTags、excludeTags、onlyMainContent 設定を使うと、比較結果が信頼できなくなります。
- 比較アルゴリズム: このアルゴリズムは、空白やコンテンツ順序の変化に強く設計されています。CAPTCHA やボット対策によるランダム化に対応するため、iframe のソース URL は無視されます。
- キャッシュ:
changeTracking を指定したリクエストは、インデックス キャッシュをバイパスします。maxAge パラメータは無視されます。
- エラー処理: レスポンス内の
warning フィールドを監視し、changeTracking オブジェクトが存在しない可能性を考慮して処理してください(これは、前回スクレイプのデータベース検索がタイムアウトした場合に発生することがあります)。
| モード | 料金 |
|---|
| 基本的な変更追跡 | 追加料金なし(通常のスクレイプクレジットを使用) |
git-diff モード | 追加料金なし |
json モード | 1ページあたり 5 クレジット |