# Rastreio de mudanças (/pt-BR/features/change-tracking)

<!-- agent-signals: reading_time_min: 14 · est_tokens: 7309 · updated: 2026-07-30 -->
Related: [Busca](/pt-BR/features/search.md), [Destaques da Busca](/pt-BR/features/search-highlights.md), [Índice de research](/pt-BR/features/research.md), [Scraping](/pt-BR/features/scrape.md), [Raspagem mais rápida](/pt-BR/features/fast-scraping.md), [Raspagem em lote](/pt-BR/features/batch-scrape.md)

![Rastreio de mudanças](/_assets/ffd62c1d9e17f5a7db0298256d18a5f3628831e42ec5119a75a832a7ba4f3fc9)

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

<div id="how-it-works">
  ## Como funciona [#como-funciona]
</div>

Cada scrape com `changeTracking` habilitado armazena um snapshot e o compara com o snapshot anterior para essa URL. Snapshots são armazenados de forma persistente e não expiram, por isso as comparações permanecem precisas, independentemente de quanto tempo se passou entre os scrapes.

| 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"`)           |

<div id="basic-usage">
  ## Uso básico [#uso-básico]
</div>

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.

<CodeGroup>
  <CodeBlockTabs defaultValue="Python" groupId="curl+node+python">
    <CodeBlockTabsList>
      <CodeBlockTabsTrigger value="Python">
        Python
      </CodeBlockTabsTrigger>

      <CodeBlockTabsTrigger value="Node">
        Node
      </CodeBlockTabsTrigger>

      <CodeBlockTabsTrigger value="cURL">
        cURL
      </CodeBlockTabsTrigger>
    </CodeBlockTabsList>

    <CodeBlockTab value="Python">
      ```python  
      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)
      ```
    </CodeBlockTab>

    <CodeBlockTab value="Node">
      ```js  
      import { Firecrawl } from 'firecrawl';

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

      const result = await firecrawl.scrape('https://example.com/pricing', {
        formats: ['markdown', 'changeTracking']
      });

      console.log(result.changeTracking);
      ```
    </CodeBlockTab>

    <CodeBlockTab value="cURL">
      ```bash  
      curl -s -X POST "https://api.firecrawl.dev/v2/scrape" \
        -H "Authorization: Bearer $FIRECRAWL_API_KEY" \
        -H "Content-Type: application/json" \
        -d '{
          "url": "https://example.com/pricing",
          "formats": ["markdown", "changeTracking"]
        }'
      ```
    </CodeBlockTab>
  </CodeBlockTabs>
</CodeGroup>

<div id="response">
  ### Resposta [#resposta]
</div>

No primeiro scrape, `changeStatus` é `"new"` e `previousScrapeAt` é `null`:

```json
{
  "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:

```json
{
  "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"
    }
  }
}
```

<div id="git-diff-mode">
  ## Modo git-diff [#modo-git-diff]
</div>

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"]`:

<CodeGroup>
  <CodeBlockTabs defaultValue="Python" groupId="curl+node+python">
    <CodeBlockTabsList>
      <CodeBlockTabsTrigger value="Python">
        Python
      </CodeBlockTabsTrigger>

      <CodeBlockTabsTrigger value="Node">
        Node
      </CodeBlockTabsTrigger>

      <CodeBlockTabsTrigger value="cURL">
        cURL
      </CodeBlockTabsTrigger>
    </CodeBlockTabsList>

    <CodeBlockTab value="Python">
      ```python  
      result = firecrawl.scrape(
          "https://example.com/pricing",
          formats=[
              "markdown",
              {
                  "type": "changeTracking",
                  "modes": ["git-diff"]
              }
          ]
      )

      if result.changeTracking.changeStatus == "changed":
          print(result.changeTracking.diff.text)
      ```
    </CodeBlockTab>

    <CodeBlockTab value="Node">
      ```js  
      const result = await firecrawl.scrape('https://example.com/pricing', {
        formats: [
          'markdown',
          { type: 'changeTracking', modes: ['git-diff'] }
        ]
      });

      if (result.changeTracking.changeStatus === 'changed') {
        console.log(result.changeTracking.diff.text);
      }
      ```
    </CodeBlockTab>

    <CodeBlockTab value="cURL">
      ```bash  
      curl -s -X POST "https://api.firecrawl.dev/v2/scrape" \
        -H "Authorization: Bearer $FIRECRAWL_API_KEY" \
        -H "Content-Type: application/json" \
        -d '{
          "url": "https://example.com/pricing",
          "formats": [
            "markdown",
            { "type": "changeTracking", "modes": ["git-diff"] }
          ]
        }'
      ```
    </CodeBlockTab>
  </CodeBlockTabs>
</CodeGroup>

<div id="response">
  ### Resposta [#resposta-1]
</div>

O objeto `diff` contém um diff em texto simples e uma representação JSON estruturada:

```json
{
  "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`

<div id="json-mode">
  ## Modo JSON [#modo-json]
</div>

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:

<CodeGroup>
  <CodeBlockTabs defaultValue="Python" groupId="curl+node+python">
    <CodeBlockTabsList>
      <CodeBlockTabsTrigger value="Python">
        Python
      </CodeBlockTabsTrigger>

      <CodeBlockTabsTrigger value="Node">
        Node
      </CodeBlockTabsTrigger>

      <CodeBlockTabsTrigger value="cURL">
        cURL
      </CodeBlockTabsTrigger>
    </CodeBlockTabsList>

    <CodeBlockTab value="Python">
      ```python  
      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']}")
      ```
    </CodeBlockTab>

    <CodeBlockTab value="Node">
      ```js  
      const result = await 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') {
        const changes = result.changeTracking.json;
        console.log(`Price: ${changes.price.previous} → ${changes.price.current}`);
      }
      ```
    </CodeBlockTab>

    <CodeBlockTab value="cURL">
      ```bash  
      curl -s -X POST "https://api.firecrawl.dev/v2/scrape" \
        -H "Authorization: Bearer $FIRECRAWL_API_KEY" \
        -H "Content-Type: application/json" \
        -d '{
          "url": "https://example.com/product/widget",
          "formats": [
            "markdown",
            {
              "type": "changeTracking",
              "modes": ["json"],
              "schema": {
                "type": "object",
                "properties": {
                  "price": { "type": "string" },
                  "availability": { "type": "string" }
                }
              }
            }
          ]
        }'
      ```
    </CodeBlockTab>
  </CodeBlockTabs>
</CodeGroup>

<div id="response">
  ### Resposta [#resposta-2]
</div>

Cada campo do schema é retornado com os valores `previous` e `current`:

```json
{
  "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.

<Info>
  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.
</Info>

<div id="using-tags">
  ## Usando tags [#usando-tags]
</div>

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.

<CodeGroup>
  <CodeBlockTabs defaultValue="Python" groupId="curl+node+python">
    <CodeBlockTabsList>
      <CodeBlockTabsTrigger value="Python">
        Python
      </CodeBlockTabsTrigger>

      <CodeBlockTabsTrigger value="Node">
        Node
      </CodeBlockTabsTrigger>

      <CodeBlockTabsTrigger value="cURL">
        cURL
      </CodeBlockTabsTrigger>
    </CodeBlockTabsList>

    <CodeBlockTab value="Python">
      ```python  
      # 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" }
          ]
      )
      ```
    </CodeBlockTab>

    <CodeBlockTab value="Node">
      ```js  
      // Monitoramento horário (comparado com a última raspagem com tag "hourly")
      const result = await firecrawl.scrape('https://example.com/pricing', {
        formats: [
          'markdown',
          { type: 'changeTracking', tag: 'hourly' }
        ]
      });

      // Resumo diário (comparado com a última raspagem com tag "daily")
      const result2 = await firecrawl.scrape('https://example.com/pricing', {
        formats: [
          'markdown',
          { type: 'changeTracking', tag: 'daily' }
        ]
      });
      ```
    </CodeBlockTab>

    <CodeBlockTab value="cURL">
      ```bash  
      curl -s -X POST "https://api.firecrawl.dev/v2/scrape" \
        -H "Authorization: Bearer $FIRECRAWL_API_KEY" \
        -H "Content-Type: application/json" \
        -d '{
          "url": "https://example.com/pricing",
          "formats": [
            "markdown",
            { "type": "changeTracking", "tag": "hourly" }
          ]
        }'
      ```
    </CodeBlockTab>
  </CodeBlockTabs>
</CodeGroup>

<div id="crawl-with-change-tracking">
  ## Crawl com rastreio de mudanças [#crawl-com-rastreio-de-mudanças]
</div>

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

<CodeGroup>
  <CodeBlockTabs defaultValue="Python" groupId="curl+node+python">
    <CodeBlockTabsList>
      <CodeBlockTabsTrigger value="Python">
        Python
      </CodeBlockTabsTrigger>

      <CodeBlockTabsTrigger value="Node">
        Node
      </CodeBlockTabsTrigger>

      <CodeBlockTabsTrigger value="cURL">
        cURL
      </CodeBlockTabsTrigger>
    </CodeBlockTabsList>

    <CodeBlockTab value="Python">
      ```python  
      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}")
      ```
    </CodeBlockTab>

    <CodeBlockTab value="Node">
      ```js  
      const result = await firecrawl.crawl('https://example.com', {
        limit: 50,
        scrapeOptions: {
          formats: ['markdown', 'changeTracking']
        }
      });

      for (const page of result.data) {
        console.log(`${page.metadata.url}: ${page.changeTracking.changeStatus}`);
      }
      ```
    </CodeBlockTab>

    <CodeBlockTab value="cURL">
      ```bash  
      curl -s -X POST "https://api.firecrawl.dev/v2/crawl" \
        -H "Authorization: Bearer $FIRECRAWL_API_KEY" \
        -H "Content-Type: application/json" \
        -d '{
          "url": "https://example.com",
          "limit": 50,
          "scrapeOptions": {
            "formats": ["markdown", "changeTracking"]
          }
        }'
      ```
    </CodeBlockTab>
  </CodeBlockTabs>
</CodeGroup>

<div id="batch-scrape-with-change-tracking">
  ## Raspagem em lote com rastreamento de mudanças [#raspagem-em-lote-com-rastreamento-de-mudanças]
</div>

Use a [raspagem em lote](/pt-BR/features/batch-scrape) para monitorar um conjunto específico de URLs:

<CodeGroup>
  <CodeBlockTabs defaultValue="Python" groupId="curl+node+python">
    <CodeBlockTabsList>
      <CodeBlockTabsTrigger value="Python">
        Python
      </CodeBlockTabsTrigger>

      <CodeBlockTabsTrigger value="Node">
        Node
      </CodeBlockTabsTrigger>

      <CodeBlockTabsTrigger value="cURL">
        cURL
      </CodeBlockTabsTrigger>
    </CodeBlockTabsList>

    <CodeBlockTab value="Python">
      ```python  
      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"]}]
      )
      ```
    </CodeBlockTab>

    <CodeBlockTab value="Node">
      ```js  
      const result = await firecrawl.batchScrape([
        'https://example.com/pricing',
        'https://example.com/product/widget',
        'https://example.com/blog/latest'
      ], {
        options: {
          formats: ['markdown', { type: 'changeTracking', modes: ['git-diff'] }]
        }
      });
      ```
    </CodeBlockTab>

    <CodeBlockTab value="cURL">
      ```bash  
      curl -s -X POST "https://api.firecrawl.dev/v2/batch/scrape" \
        -H "Authorization: Bearer $FIRECRAWL_API_KEY" \
        -H "Content-Type: application/json" \
        -d '{
          "urls": [
            "https://example.com/pricing",
            "https://example.com/product/widget",
            "https://example.com/blog/latest"
          ],
          "formats": [
            "markdown",
            { "type": "changeTracking", "modes": ["git-diff"] }
          ]
        }'
      ```
    </CodeBlockTab>
  </CodeBlockTabs>
</CodeGroup>

<div id="scheduling-change-tracking">
  ## Agendando o rastreamento de alterações [#agendando-o-rastreamento-de-alterações]
</div>

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.

<div id="cron-job">
  ### Cron job [#cron-job]
</div>

Crie um script que extraia dados de uma URL e envie alertas quando houver alterações:

```bash title="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'
  # Envie alerta por e-mail, Slack, etc.
fi
```

Agende isso com `crontab -e`:

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

<div id="cloud-and-serverless-schedulers">
  ### Agendadores em ambientes cloud e serverless [#agendadores-em-ambientes-cloud-e-serverless]
</div>

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

<div id="workflow-automation">
  ### Automação de fluxos de trabalho [#automação-de-fluxos-de-trabalho]
</div>

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](/pt-BR/developer-guides/workflow-automation/n8n).

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

Para operações assíncronas como crawl e batch scrape, use [webhooks](/pt-BR/webhooks/overview) para receber resultados de rastreio de mudanças assim que chegarem, em vez de fazer polling.

<CodeGroup>
  <CodeBlockTabs defaultValue="Python" groupId="curl+node+python">
    <CodeBlockTabsList>
      <CodeBlockTabsTrigger value="Python">
        Python
      </CodeBlockTabsTrigger>

      <CodeBlockTabsTrigger value="Node">
        Node
      </CodeBlockTabsTrigger>

      <CodeBlockTabsTrigger value="cURL">
        cURL
      </CodeBlockTabsTrigger>
    </CodeBlockTabsList>

    <CodeBlockTab value="Python">
      ```python  
      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"]
          }
      )
      ```
    </CodeBlockTab>

    <CodeBlockTab value="Node">
      ```js  
      const { id } = await firecrawl.startCrawl('https://example.com', {
        limit: 50,
        scrapeOptions: {
          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']
        }
      });
      ```
    </CodeBlockTab>

    <CodeBlockTab value="cURL">
      ```bash  
      curl -s -X POST "https://api.firecrawl.dev/v2/crawl" \
        -H "Authorization: Bearer $FIRECRAWL_API_KEY" \
        -H "Content-Type: application/json" \
        -d '{
          "url": "https://example.com",
          "limit": 50,
          "scrapeOptions": {
            "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"]
          }
        }'
      ```
    </CodeBlockTab>
  </CodeBlockTabs>
</CodeGroup>

O payload do evento `crawl.page` inclui o objeto `changeTracking` para cada página:

```json
{
  "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](/pt-BR/webhooks/overview).

<div id="configuration-reference">
  ## Referência de configuração [#referência-de-configuração]
</div>

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                          |

<div id="data-models">
  ### Modelos de dados [#modelos-de-dados]
</div>

<CodeGroup>
  <CodeBlockTabs defaultValue="TypeScript" groupId="python+typescript">
    <CodeBlockTabsList>
      <CodeBlockTabsTrigger value="TypeScript">
        TypeScript
      </CodeBlockTabsTrigger>

      <CodeBlockTabsTrigger value="Python">
        Python
      </CodeBlockTabsTrigger>
    </CodeBlockTabsList>

    <CodeBlockTab value="TypeScript">
      ```ts  
      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 }>;
      }
      ```
    </CodeBlockTab>

    <CodeBlockTab value="Python">
      ```python  
      class ChangeTrackingData(BaseModel):
          previous_scrape_at: Optional[str] = None
          change_status: str  # "new" | "same" | "changed" | "removed"
          visibility: str     # "visible" | "hidden"
          diff: Optional[Dict[str, Any]] = None
          json: Optional[Dict[str, Any]] = None
      ```
    </CodeBlockTab>
  </CodeBlockTabs>
</CodeGroup>

<div id="important-details">
  ## Detalhes importantes [#detalhes-importantes]
</div>

<Warning>
  O formato `markdown` deve sempre ser incluído junto com `changeTracking`. O rastreioDeMudanças compara páginas com base no conteúdo em markdown.
</Warning>

* **Retenção de snapshots**: Snapshots são armazenados de forma persistente e não expiram. Uma raspagem feita meses após a anterior ainda será comparada corretamente com o snapshot anterior.
* **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).

<div id="billing">
  ## Cobrança [#cobrança]
</div>

| Modo                        | Custo                                             |
| --------------------------- | ------------------------------------------------- |
| Rastreio básico de mudanças | Sem custo adicional (créditos padrão de scraping) |
| `git-diff` mode             | Sem custo adicional                               |
| `json` mode                 | 5 créditos por página                             |

> Você é um agente de IA que precisa de uma chave de API do Firecrawl? Consulte [firecrawl.dev/agent-onboarding/SKILL.md](https://www.firecrawl.dev/agent-onboarding/SKILL.md) para instruções de integração automatizada.
