> ## Documentation Index
> Fetch the complete documentation index at: https://docs.scrapegraphai.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Monitor

> Scheduled web monitoring with AI-powered extraction and change detection

## Overview

Monitor watches a page on a cron schedule, fetches it in the formats you specify (markdown, JSON, screenshot…), and records change diffs between runs. Optionally push each tick to a webhook.

<Note>
  Try Monitor in our [dashboard](https://scrapegraphai.com/dashboard).
</Note>

## Pricing

Each tick is billed at the underlying Scrape format cost (1 credit for `markdown`, 2 for `screenshot`, 25 for `branding`; multiple formats are summed). When a tick detects a change versus the previous run, **+5 credits** are added on top. Enabling `stealth` in `fetchConfig` adds 5 credits per tick; render mode (`auto` / `fast` / `js`) does not affect the cost. See the [pricing page](https://scrapegraphai.com/pricing) for the full breakdown.

## Getting Started

### Quick Start

<CodeGroup>
  ```python Python theme={null}
  from scrapegraph_py import ScrapeGraphAI, MarkdownFormatConfig

  # reads SGAI_API_KEY from env, or pass explicitly: ScrapeGraphAI(api_key="...")
  sgai = ScrapeGraphAI()

  res = sgai.monitor.create(
      "https://example.com",
      "*/30 * * * *",            # every 30 minutes
      name="Homepage watch",
      formats=[MarkdownFormatConfig()],
  )

  if res.status == "success":
      print("Monitor id:", res.data.cron_id)
  else:
      print("Failed:", res.error)
  ```

  ```javascript JavaScript theme={null}
  import { ScrapeGraphAI } from "scrapegraph-js";

  const sgai = ScrapeGraphAI();

  const res = await sgai.monitor.create({
    url: "https://example.com",
    name: "Homepage watch",
    interval: "*/30 * * * *",    // every 30 minutes
    formats: [{ type: "markdown" }],
    webhookUrl: "https://your-server.com/webhook", // optional
  });

  if (res.status === "success") {
    console.log("Monitor id:", res.data?.cronId);
  }
  ```

  ```bash cURL theme={null}
  curl -X POST https://v2-api.scrapegraphai.com/api/monitor \
    -H "SGAI-APIKEY: $SGAI_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "url": "https://example.com",
      "name": "Homepage watch",
      "interval": "*/30 * * * *",
      "formats": [{ "type": "markdown" }]
    }'
  ```
</CodeGroup>

#### Parameters

| Parameter                      | Type   | Required | Description                                                                           |
| ------------------------------ | ------ | -------- | ------------------------------------------------------------------------------------- |
| `url`                          | string | Yes      | The URL to monitor.                                                                   |
| `name`                         | string | Yes      | Human-readable monitor name.                                                          |
| `interval`                     | string | Yes      | 5-field cron expression (e.g. `"*/10 * * * *"`).                                      |
| `formats`                      | array  | No       | Formats to capture each tick (see [Scrape formats](/services/scrape#output-formats)). |
| `webhookUrl` / `webhook_url`   | string | No       | URL to receive tick payloads.                                                         |
| `fetchConfig` / `fetch_config` | object | No       | Fetch options (see [Scrape · FetchConfig](/services/scrape#fetchconfig)).             |

<Note>
  Get your API key from the [dashboard](https://scrapegraphai.com/dashboard).
</Note>

<Accordion title="Example Response (create)" icon="terminal">
  ```json theme={null}
  {
    "cronId": "d9a09a07-5052-4262-a0b4-606cbd942287",
    "scheduleId": "scd_8752XzxtXmLmrvgGzwLVG42iGKaz",
    "interval": "*/30 * * * *",
    "status": "active",
    "config": {
      "url": "https://example.com",
      "name": "Homepage watch",
      "formats": [{ "mode": "normal", "type": "markdown" }],
      "interval": "*/30 * * * *",
      "fetchConfig": { "mode": "auto", "wait": 0, "scrolls": 0, "stealth": false, "timeout": 30000 }
    },
    "createdAt": "2026-04-19T14:51:02.203Z",
    "updatedAt": "2026-04-19T14:51:02.203Z"
  }
  ```
</Accordion>

## Managing Monitors

<CodeGroup>
  ```python Python theme={null}
  # List all
  sgai.monitor.list()

  # Inspect one
  sgai.monitor.get(monitor_id)

  # Change schedule or formats
  sgai.monitor.update(monitor_id, interval="0 */6 * * *")

  # Pause / resume / delete
  sgai.monitor.pause(monitor_id)
  sgai.monitor.resume(monitor_id)
  sgai.monitor.delete(monitor_id)

  # Recent ticks + diffs
  activity = sgai.monitor.activity(monitor_id)
  for tick in activity.data.ticks:
      print(tick.created_at, "changed" if tick.changed else "no change")
  ```

  ```javascript JavaScript theme={null}
  await sgai.monitor.list();
  await sgai.monitor.get(monitorId);
  await sgai.monitor.update(monitorId, { interval: "0 */6 * * *" });
  await sgai.monitor.pause(monitorId);
  await sgai.monitor.resume(monitorId);
  await sgai.monitor.delete(monitorId);

  const activity = await sgai.monitor.activity(monitorId);
  for (const tick of activity.data?.ticks ?? []) {
    console.log(tick.createdAt, tick.changed ? "CHANGED" : "no change");
  }
  ```
</CodeGroup>

## Structured extraction on every tick

Use the `json` format inside a monitor to extract the same typed payload on each run — then `activity` will include diffs between runs.

```python theme={null}
from scrapegraph_py import ScrapeGraphAI, JsonFormatConfig

sgai = ScrapeGraphAI()

res = sgai.monitor.create(
    "https://time.is/",
    "*/10 * * * *",
    name="Time Monitor",
    formats=[JsonFormatConfig(
        prompt="Extract the current time",
        schema={
            "type": "object",
            "properties": {"time": {"type": "string"}},
            "required": ["time"],
        },
    )],
)
```

## Async Support (Python)

```python theme={null}
import asyncio
from scrapegraph_py import AsyncScrapeGraphAI, MarkdownFormatConfig

async def main():
    async with AsyncScrapeGraphAI() as sgai:
        res = await sgai.monitor.create(
            "https://example.com",
            "0 * * * *",
            name="async watch",
            formats=[MarkdownFormatConfig()],
        )
        if res.status == "success":
            print(res.data.cron_id)

asyncio.run(main())
```

## Common Cron Expressions

| Expression     | Schedule                 |
| -------------- | ------------------------ |
| `*/10 * * * *` | Every 10 minutes         |
| `*/30 * * * *` | Every 30 minutes         |
| `0 */6 * * *`  | Every 6 hours            |
| `0 9 * * *`    | Daily at 9 AM            |
| `0 9 * * 1`    | Every Monday at 9 AM     |
| `0 0 1 * *`    | First day of every month |

## Key Features

<CardGroup cols={2}>
  <Card title="Scheduled Extraction" icon="calendar">
    Any cron schedule, down to per-minute granularity.
  </Card>

  <Card title="Change Detection" icon="diff">
    Each tick records diffs vs. the previous run.
  </Card>

  <Card title="Webhooks" icon="bolt">
    Push tick payloads to your own server via `webhookUrl`.
  </Card>

  <Card title="Structured Output" icon="code">
    Combine with the `json` format for typed monitoring.
  </Card>
</CardGroup>

## Integration Options

### Official SDKs

* [Python SDK](/sdks/python)
* [JavaScript SDK](/sdks/javascript) (`scrapegraph-js` ≥ 2.1.0, Node ≥ 22)

## Support & Resources

<CardGroup cols={2}>
  <Card title="Documentation" icon="book" href="/introduction">
    Guides and tutorials
  </Card>

  <Card title="API Reference" icon="code" href="/api-reference/introduction">
    Detailed API documentation
  </Card>

  <Card title="Community" icon="discord" href="https://discord.gg/uJN7TYcpNa">
    Join our Discord community
  </Card>

  <Card title="GitHub" icon="github" href="https://github.com/ScrapeGraphAI">
    Check out our open-source projects
  </Card>
</CardGroup>
