O rastreio de mudanças compara o conteúdo atual de uma página com o da última vez em que você fez o scrape. Adicione changeTracking ao seu array de formats para detectar se uma página é nova, inalterada ou modificada e, opcionalmente, obter um diff estruturado do que mudou.
- Funciona com
/scrape, /crawl e /batch/scrape
- Dois modos de diff:
git-diff para mudanças em nível de linha e json para comparação em nível de campo
- Restrito à sua equipe e, opcionalmente, a uma tag que você especificar
Cada scrape com changeTracking habilitado armazena um snapshot e o compara com o snapshot anterior para essa URL.
| Scrape | Resultado |
|---|
| Primeiro scrape | changeStatus: "new" (nenhuma versão anterior existe) |
| Conteúdo inalterado | changeStatus: "same" |
| Conteúdo modificado | changeStatus: "changed" (dados de diff disponíveis) |
| Página removida | changeStatus: "removed" |
A resposta inclui estes campos no objeto changeTracking:
| Campo | Tipo | Descrição |
|---|
previousScrapeAt | string | null | Carimbo de data e hora do scrape anterior (null no primeiro scrape) |
changeStatus | string | "new", "same", "changed" ou "removed" |
visibility | string | "visible" (localizável via links/sitemap) ou "hidden" (a URL funciona, mas não está mais linkada) |
diff | object | undefined | Diff em nível de linha (presente apenas no modo git-diff quando o status é "changed") |
json | object | undefined | Comparação em nível de campo (presente apenas no modo json quando o status é "changed") |
Inclua tanto markdown quanto changeTracking no array formats. O formato markdown é obrigatório porque o rastreio de mudanças compara as páginas com base no conteúdo em 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)
No primeiro scrape, changeStatus é "new" e previousScrapeAt é null:
{
"success": true,
"data": {
"markdown": "# Pricing\n\nStarter: $9/mo\nPro: $29/mo...",
"changeTracking": {
"previousScrapeAt": null,
"changeStatus": "new",
"visibility": "visible"
}
}
}
Em raspagens posteriores, changeStatus indica se o conteúdo foi alterado:
{
"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"
}
}
}
O modo git-diff retorna alterações linha a linha em um formato semelhante ao git diff. Passe um objeto no array formats com 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)
O objeto diff contém um diff em texto simples e uma representação JSON estruturada:
{
"rastreioDeMudanças": {
"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" }
]
}]
}]
}
}
}
}
O objeto estruturado diff.json contém:
files: array de arquivos modificados (geralmente um por página da web)
chunks: seções de alterações dentro de um arquivo
changes: alterações individuais de linha com type ("add", "del" ou "normal"), número da linha (ln) e content
O modo json extrai campos específicos tanto da versão atual quanto da versão anterior da página usando um schema que você define. Isso é útil para acompanhar mudanças em dados estruturados, como preços, níveis de estoque ou metadados, sem precisar analisar um diff completo.
Passe modes: ["json"] com um schema definindo os campos a serem extraídos:
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']}")
Cada campo do schema é retornado com os valores previous e 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"
}
}
}
}
Você também pode fornecer um prompt opcional para orientar a extração do LLM em conjunto com o schema.
O modo JSON usa extração com LLM e custa 5 créditos por página. O rastreamento básico de alterações e o modo git-diff não têm custo adicional.
Por padrão, o rastreamento de mudanças compara com a raspagem mais recente da mesma URL feita pela sua equipe. Tags permitem que você mantenha históricos de rastreamento separados para a mesma URL, o que é útil quando você monitora a mesma página em intervalos diferentes ou em contextos distintos.
# Monitoramento horário (comparado com a última raspagem com tag "hourly")
result = firecrawl.scrape(
"https://example.com/pricing",
formats=[
"markdown",
{ "type": "changeTracking", "tag": "hourly" }
]
)
# Resumo diário (comparado com a última raspagem com tag "daily")
result = firecrawl.scrape(
"https://example.com/pricing",
formats=[
"markdown",
{ "type": "changeTracking", "tag": "daily" }
]
)
Adicione rastreio de mudanças às operações de crawl para monitorar um site inteiro em busca de alterações. Passe o 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}")
Raspagem em lote com rastreamento de mudanças
Use a raspagem em lote para monitorar um conjunto específico de URLs:
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"]}]
)
Agendando o rastreamento de alterações
O rastreamento de alterações é mais útil quando você faz scraping em uma agenda regular. Você pode automatizar isso com cron, agendadores em nuvem ou ferramentas de workflow.
Crie um script que extraia dados de uma URL e envie alertas quando houver alterações:
#!/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'
# Envie alerta por e-mail, Slack, etc.
fi
Agende isso com crontab -e:
0 */6 * * * /path/to/check-pricing.sh >> /var/log/price-monitor.log 2>&1
| Agendamento | Expressão |
|---|
| A cada hora | 0 * * * * |
| A cada 6 horas | 0 */6 * * * |
| Diariamente às 9h | 0 9 * * * |
| Toda segunda-feira às 8h | 0 8 * * 1 |
Agendadores em ambientes cloud e serverless
- AWS: regra do EventBridge acionando uma função Lambda
- GCP: Cloud Scheduler acionando uma Cloud Function
- Vercel / Netlify: funções serverless acionadas por cron
- GitHub Actions: workflows agendados com gatilhos
schedule e cron
Automação de fluxos de trabalho
Plataformas no-code como n8n, Zapier e Make podem chamar a API do Firecrawl em intervalos programados e enviar os resultados para o Slack, e-mail ou bancos de dados. Veja os guias de automação de fluxos de trabalho.
Para operações assíncronas como crawl e batch scrape, use webhooks para receber resultados de rastreio de mudanças assim que chegarem, em vez de fazer 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"]
}
)
O payload do evento crawl.page inclui o 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 obter detalhes sobre a configuração de webhooks (cabeçalhos, metadados, eventos, tentativas de nova entrega, verificação de assinatura), consulte a documentação de webhooks.
Referência de configuração
O conjunto completo de opções disponível ao passar um objeto no formato changeTracking:
| Parâmetro | Tipo | Padrão | Descrição |
|---|
type | string | (obrigatório) | Deve ser "changeTracking" |
modes | string[] | [] | Modos de diff a serem habilitados: "git-diff", "json" ou ambos |
schema | object | (nenhum) | JSON Schema para comparação em nível de campo (obrigatório para o modo json) |
prompt | string | (nenhum) | Prompt personalizado para orientar a extração pelo LLM (usado com o modo json) |
tag | string | null | Identificador separado para o histórico de rastreamento |
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 }>;
}
O formato markdown deve sempre ser incluído junto com changeTracking. O rastreioDeMudanças compara páginas com base no conteúdo em markdown.
- Escopo: As comparações são limitadas à sua equipe. Sua primeira raspagem de qualquer URL retorna
"new", mesmo que outros usuários já a tenham raspado.
- Correspondência de URL: Raspagens anteriores são associadas com base na URL de origem exata, ID da equipe, formato
markdown e tag. Mantenha as URLs consistentes entre raspagens.
- Consistência de parâmetros: Usar configurações diferentes de
includeTags, excludeTags ou onlyMainContent em raspagens da mesma URL produz comparações não confiáveis.
- Algoritmo de comparação: O algoritmo é resistente a mudanças em espaços em branco e na ordem do conteúdo. URLs de origem de iframes são ignoradas para lidar com a aleatoriedade de captcha/antibot.
- Cache: Solicitações com
changeTracking contornam o cache do índice. O parâmetro maxAge é ignorado.
- Tratamento de erros: Monitore o campo
warning nas respostas e esteja preparado para o caso de o objeto changeTracking estar ausente (isso pode ocorrer se a consulta ao banco de dados para a raspagem anterior exceder o tempo limite).
| Modo | Custo |
|---|
| Rastreamento básico de alterações | Sem custo adicional (créditos de raspagem padrão) |
Modo git-diff | Sem custo adicional |
Modo json | 5 créditos por página |