# Site Intel Monitor – Screenshot & Track Changes (`zaden/site-intel-monitor`) Actor

Screenshot any page, extract clean Markdown content, pull every table as structured JSON, and get alerted the moment the page changes — with an optional AI-written summary of exactly what changed. Built for competitor tracking, pricing-page monitoring, and changelog watching.

- **URL**: https://apify.com/zaden/site-intel-monitor.md
- **Developed by:** [Zaden](https://apify.com/zaden) (community)
- **Categories:** SEO tools, Automation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $18.00 / 1,000 page analyzeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Site Intel Monitor — Screenshot + Content + Tables + Change Detection + AI Summaries

Site Intel Monitor is a website change monitor and competitor price monitoring tool in one: point it at any page — a competitor's pricing page, a changelog, a docs site, a product listing — and get back everything in one run: a full-page screenshot, the main content as clean Markdown, every table on the page as structured JSON, and — unlike most change-monitor tools, which only tell you *that* a page changed — a real paragraph-level summary of *what* changed, optionally rewritten into a plain-English, business-impact sentence by an LLM and pushed straight to Slack or your own webhook.

Most tools on Apify Store do one of these things well. This Actor exists because in practice you usually want several of them together — especially for competitive intelligence and pricing monitoring, where "did the price change," "show me exactly what changed," and "tell my team right now" are really the same job.

### What you get, per URL

- **Screenshot** — full-page PNG, stored and linked from the result.
- **Content** — the main article/content area converted to clean Markdown, with title, byline, publish date, and excerpt pulled from page metadata where available. Navigation, ads, cookie banners, and other clutter are stripped before extraction.
- **Tables** — every `<table>` on the page (or within a CSS selector you specify), parsed into headers, raw rows, and — when the table has clean unique headers — row objects you can use directly.
- **Change detection with a real diff** — the Actor remembers each URL's content in your own account storage. On the next check, it doesn't just flag `changed: true` — it tells you how many paragraphs were added or removed, with examples of the actual text, so you don't have to open the page to find out what happened.
- **AI-written summaries (optional, bring your own key)** — paste your own Anthropic or OpenAI API key and, instead of a paragraph count, you get one plain-English sentence about what actually changed: *"Pro plan price dropped from $49 to $39/mo"* rather than *"1 paragraph added, 1 removed."* Your key is used only for that run and never stored; you're billed by the Actor only when a summary is actually produced.
- **Slack / webhook alerts** — set a webhook URL and get pushed a message the moment a change is detected, formatted to render directly in Slack (or consume as plain JSON anywhere else — Zapier, Make, n8n, your own endpoint). The AI summary, when available, is used as the headline.
- **A severity tag** — `critical` (nothing could be extracted from the page — usually a blocked request, wrong selector, or a page that needs JS/login this Actor can't provide), `warning` (content changed since last check), or `ok` (no change) — for instant triage across a large batch of monitored URLs.
- **A one-line executive summary** — whatever's most useful right now: the AI or diff summary if something changed, "no changes" if it didn't, or a flag if extraction failed.
- **Bounded concurrency** — URLs are screenshotted, extracted, and diffed **in parallel** (configurable), so a batch of 50 monitored pages finishes in a fraction of the time a one-by-one check would take.

### Who this is for

- Competitive intelligence teams tracking competitor pricing pages, feature pages, or changelogs
- Sales and marketing teams that want an alert-style feed of "what changed on their site"
- Anyone feeding LLMs / RAG pipelines who also wants tables extracted as real structured data, not just flattened into Markdown text
- Anyone who wants a visual screenshot alongside the extracted content for a quick human sanity-check

### How to use it

1. Add one or more URLs under **URLs to check**.
2. Optionally set a **CSS selector** to scope extraction to part of the page (e.g. `.pricing-table`) — otherwise the Actor auto-detects the main content area.
3. Toggle **screenshot**, **extract tables**, and **detect changes** on or off depending on what you need.
4. Optionally paste a **Slack incoming webhook URL** (or any webhook endpoint) to get pinged the moment a change is detected — no extra setup needed on our side.
5. Optionally paste your own **Anthropic or OpenAI API key** to turn on AI-written change summaries.
6. Optionally adjust **max concurrent pages** — the default (5) balances speed against not hammering any one site too hard.
7. Run it once for a one-off snapshot, or put it on an Apify **Schedule** to monitor pages over time — change detection compares each run against your last one automatically.

### Example output (one item)

```json
{
  "url": "https://example.com/pricing",
  "title": "Pricing – Example",
  "markdown": "# Pricing\n\nOur plans...",
  "wordCount": 412,
  "tables": [
    {
      "index": 0,
      "caption": "Plans",
      "headers": ["Plan", "Price", "Seats"],
      "rowObjects": [
        { "Plan": "Starter", "Price": "$29/mo", "Seats": "1" },
        { "Plan": "Team", "Price": "$99/mo", "Seats": "10" }
      ]
    }
  ],
  "severity": "warning",
  "summary": "Team plan price dropped from $99/mo to $89/mo.",
  "changed": true,
  "previousCheckedAt": "2026-08-12T09:00:00.000Z",
  "diffSummary": "1 paragraph added, 0 removed since last check.",
  "aiSummary": "Team plan price dropped from $99/mo to $89/mo.",
  "paragraphsAdded": 1,
  "paragraphsRemoved": 0,
  "addedExamples": ["Team plan is now $89/mo (was $99/mo)."],
  "removedExamples": [],
  "screenshotUrl": "https://api.apify.com/v2/key-value-stores/.../records/screenshot-...png",
  "checkedAt": "2026-08-19T09:00:00.000Z"
}
```

The first time you check a given URL, `changed` will be `null` — there's nothing to compare against yet. From the second check onward it's `true` or `false`, and `diffSummary`/`addedExamples`/`removedExamples` are populated whenever a change is found.

### Pricing

This Actor uses pay-per-event pricing:

- **Page analyzed** — charged once per URL successfully processed (content extraction, table extraction, and change-detection are bundled into this single event).
- **Screenshot** — charged once per URL only when the screenshot option is enabled.
- **AI summary** — charged only when you've supplied your own API key, a change was actually detected, and a summary was successfully produced. No key, no charge.

You only pay for what you actually use — turn off tables, screenshots, or AI summaries for URLs where you don't need them and you won't be charged for those events. Note: AI summaries require your own Anthropic or OpenAI API key, and that provider bills you directly for the underlying LLM call — this Actor's "AI summary" event only covers the orchestration.

### FAQ

**What do the "severity" and "summary" fields mean?**
`summary` is a one-line, plain-English description of what happened on this check — the AI or diff summary if content changed, "no changes detected" if it didn't, or a flag if extraction failed. `severity` is the triage tag: `critical` means nothing could be extracted from the page at all (usually a blocked request, wrong selector, or a page that needs JavaScript rendering or a login this Actor can't provide) — which is worth checking regardless of whether you care about content changes. `warning` means content changed since your last check. `ok` means the page loaded fine and nothing changed.

**Will higher concurrency get me rate-limited?**
It can, on sites with aggressive rate limiting, or if you're monitoring many URLs on the same domain. Start at the default (5) and lower it if you see more failed/blocked requests for a particular site.

**Does change detection work across scheduled runs?**
Yes — the baseline is stored in your own Apify account (a persistent key-value store), keyed by URL, so it persists between runs regardless of how you trigger them.

**Can I scope extraction to just part of the page?**
Yes, use the CSS selector input. Useful for pages with a lot of unrelated content around the part you actually care about.

**How do the Slack/webhook alerts work?**
Paste a Slack incoming webhook URL (or any HTTPS endpoint that accepts a JSON POST) into the webhook input. Whenever a run detects a change, the Actor POSTs a message with a human-readable `text` field (renders natively in Slack) plus structured fields (`aiSummary`, `diffSummary`, `paragraphsAdded`, `paragraphsRemoved`, `addedExamples`, `removedExamples`) for anything else — Zapier, Make, n8n, or your own backend. No alert is sent on the first check of a URL (nothing to compare against yet) or on runs where nothing changed.

**How do AI summaries work, and is my API key safe?**
Paste your own Anthropic or OpenAI API key into the "AI API key" input and pick the matching provider. When (and only when) a change is detected on a URL, the Actor sends the added/removed text to your provider with a tight prompt asking for one plain-English, business-impact sentence — not a general chatbot call, no conversation history, nothing stored server-side. Your key is read from that run's input, used for that one HTTP request, and discarded; it is never logged, written to the dataset, or reused across runs. If you leave this blank, everything else (screenshot, tables, diff, webhook alerts) works exactly the same, just with `diffSummary` instead of `aiSummary` as your description of the change.

**Can I use this to monitor a competitor's website for changes?**
Yes — that's the primary use case. Add their pricing page, changelog, or product page as a URL, turn on change detection, and put the Actor on a schedule. You'll get a diff (and, with a BYOK API key, an AI-written summary) the moment something moves, pushed to Slack or your own webhook — no manual page-checking needed.

**Is this legal?**
Web scraping publicly available, non-personal data is generally legal; what you do with the content is a separate question, and content like documentation, articles, or blogs is typically copyrighted. If you're unsure, seek professional legal advice.

# Actor input Schema

## `startUrls` (type: `array`):

One or more pages to screenshot, extract, and monitor. Great for competitor pricing pages, changelog pages, or any page you want structured data + change alerts on.

## `selector` (type: `string`):

If set, only this part of the page is extracted for content/tables (e.g. "main" or ".pricing-table"). Leave blank to auto-detect the main article/content area.

## `takeScreenshot` (type: `boolean`):

Capture a full-page PNG screenshot of each URL. Billed as a separate event from content extraction.

## `extractTables` (type: `boolean`):

Pull every HTML table on the page (or within the selector) into structured JSON — headers, rows, and row objects.

## `detectChanges` (type: `boolean`):

Compare this run's content against the last time you checked this same URL (stored in your account) and flag whether it changed. Most useful when this Actor is run on a schedule.

## `maxRequestsPerCrawl` (type: `integer`):

Safety cap on how many URLs this run will process.

## `maxConcurrency` (type: `integer`):

How many URLs to screenshot/extract/diff in parallel. Higher values finish a large batch faster; lower it if you're monitoring many pages on the same site and want to be gentler on it.

## `webhookUrl` (type: `string`):

If set, this Actor POSTs a JSON alert here whenever a change is detected on one of your URLs. Works directly with Slack incoming webhooks (uses a "text" field they render automatically) and with generic webhook receivers, Zapier, Make, or n8n. Leave blank to disable.

## `aiApiKey` (type: `string`):

Paste your own Anthropic or OpenAI API key to get a one-sentence, plain-English summary of what actually changed and why it matters (e.g. "Pro plan price dropped from $49 to $39/mo") instead of just a paragraph count. Your key is used only for this run, sent directly to the provider, and never stored. Billed as a separate 'AI summary' event, and only on runs where a real change was detected and a summary was produced. Leave blank to skip — everything else works the same without it.

## `aiProvider` (type: `string`):

Which provider your API key above is for. Only used if you supplied a key.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://example.com"
    }
  ],
  "takeScreenshot": true,
  "extractTables": true,
  "detectChanges": true,
  "maxRequestsPerCrawl": 100,
  "maxConcurrency": 5,
  "aiProvider": "anthropic"
}
```

# Actor output Schema

## `results` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "startUrls": [
        {
            "url": "https://example.com"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("zaden/site-intel-monitor").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "startUrls": [{ "url": "https://example.com" }] }

# Run the Actor and wait for it to finish
run = client.actor("zaden/site-intel-monitor").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "startUrls": [
    {
      "url": "https://example.com"
    }
  ]
}' |
apify call zaden/site-intel-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,zaden/site-intel-monitor"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/1CwyGyRsNloXk5ngd/builds/JLLkgf0DjqRrYzmCL/openapi.json
