# Web Page Change Monitor (`cyber1nj3ct0r/web-page-change-monitor`) Actor

Watch any web page for changes. Each run compares the page with the version saved before and returns the lines that were added and removed. Watch a whole page or one part of it, ignore noise such as dates and ads, and send changes to Slack, Discord or any webhook.

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

## Pricing

from $0.60 / 1,000 page checks

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?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

### What does Web Page Change Monitor do?

Web Page Change Monitor **watches web pages and tells you exactly what changed**: the lines that were added and the lines that were removed since the last check.

Add the pages you care about, put the tool on a schedule, and you have a website change detection service that runs by itself. The first run saves each page as the starting point. Every later run compares the page with the saved version.

- **Shows the change, not just that something changed**: added lines, removed lines and a readable diff for every page.
- **Watch one part of a page**: give a CSS selector such as `#pricing` and the rest of the page is ignored.
- **Cut out noise**: ignore parts of the page (ads, footers, clocks) or text patterns (dates, counters) so you only hear about real changes.
- **Alerts where you work**: send changes to a Slack or Discord channel, or to Zapier, Make, n8n or your own server through a webhook. Nothing is sent when nothing changed.
- **Text or HTML**: compare the visible text, or the HTML if you also want to catch changed links and images.
- **Works on JSON too**: point it at a JSON API address and get the changed fields.

### What can you monitor?

- **Competitor pricing pages**: know the day a price or plan changes.
- **Terms, privacy policies and legal notices**: keep a record of every wording change.
- **Job boards and tender pages**: see new postings as they appear.
- **Product pages**: stock status, specifications, delivery times.
- **Documentation and changelogs** of tools you depend on.
- **Your own website**: catch unplanned changes, defacement or a broken deployment.
- **Government and regulator pages**: notices, fee tables, deadlines.

### How to monitor a web page for changes

1. Enter the pages under **Pages to watch**.
2. Optional: enter a CSS selector under **Watch only this part of the page**, and a webhook address under **Send changes to this webhook**.
3. Press **Start**. This first run saves the starting point; every page has the status `new`.
4. Open **Schedules** in Apify Console and run the tool as often as you need, for example every hour or every morning.
5. From then on each run reports every page as `unchanged` or `changed`, with the changed lines.

### How much does it cost to monitor a website?

You pay per page check: **$1.00 per 1,000 page checks**. Apify subscribers on the Silver plan pay $0.80 and on the Gold plan $0.60 per 1,000. Each run also has a start fee of $0.00005.

| What you watch | Checks a month | Cost a month |
|---|---|---|
| 10 pages once a day | 300 | $0.30 |
| 50 pages once a day | 1,500 | $1.50 |
| 10 pages every hour | 7,200 | $7.20 |
| 100 pages every hour | 72,000 | $72.00 |

Apify's free plan includes $5 of credit each month, enough for about 5,000 page checks. There is no monthly fee and no limit on the number of pages.

### Input

Only **Pages to watch** is required.

```json
{
    "urls": [{ "url": "https://www.example.com/pricing" }],
    "selector": "#pricing",
    "ignoreSelectors": [".cookie-banner", "footer"],
    "ignoreText": ["/Updated: .*/", "/\\d+ visitors/"],
    "compare": "text",
    "webhookUrl": "https://hooks.slack.com/services/XXX/YYY/ZZZ"
}
```

| Field | What it does |
|---|---|
| `urls` | The pages to watch |
| `selector` | CSS selector of the part to watch; empty means the whole page |
| `webhookUrl` | Where to send changes; stored encrypted |
| `ignoreSelectors` | CSS selectors of parts that should not count |
| `ignoreText` | Text or regular expressions removed before comparing |
| `compare` | `text` (visible text) or `html` |
| `monitorName` | Keeps saved versions apart, so one page can be watched in several ways |
| `resetBaseline` | Forget the saved versions and start over |
| `includeContent` | Add the compared text to each result |

### Output example

One record per page and run:

```json
{
    "url": "https://www.example.com/pricing",
    "status": "changed",
    "changed": true,
    "checkedAt": "2026-10-13T08:00:04.512Z",
    "lastChangedAt": "2026-10-13T08:00:04.512Z",
    "changesDetected": 3,
    "httpStatus": 200,
    "title": "Pricing",
    "addedCount": 2,
    "removedCount": 1,
    "changePercent": 4.2,
    "addedLines": ["Basic plan: $12 a month", "New: phone support"],
    "removedLines": ["Basic plan: $10 a month"],
    "diff": "  Pricing\n- Basic plan: $10 a month\n+ Basic plan: $12 a month\n  Support by e-mail\n+ New: phone support",
    "error": null
}
```

`status` is one of `new` (saved as the starting point), `unchanged`, `changed` or `error`. A page that could not be reached gets `error` with a code such as `HTTP_404` or `TIMEOUT`; its saved version is kept, so a short outage is not reported as a change.

### Getting alerts

**Slack or Discord**: create an incoming webhook in your channel settings and paste its address into **Send changes to this webhook**. You get a message listing the changed pages with their first added and removed lines.

**Zapier, Make, n8n or your own server**: paste the webhook address. The tool posts JSON like this when at least one page changed:

```json
{
    "event": "pages-changed",
    "monitorName": "default",
    "pagesChecked": 12,
    "changedCount": 1,
    "changes": [{ "url": "https://www.example.com/pricing", "title": "Pricing", "addedCount": 2, "removedCount": 1, "addedLines": ["..."], "removedLines": ["..."], "diff": "..." }],
    "resultsUrl": "https://api.apify.com/v2/datasets/DATASET_ID/items?clean=true"
}
```

**E-mail**: use a Zapier, Make or n8n webhook that sends an e-mail. That way you get mail only when something changed.

### FAQ

#### Why does a page report changes every time?

Something on the page differs on every visit: a date, a visitor counter, a rotating banner, a random token. Look at the `diff` to see what it is, then add it under **Parts to ignore** (by CSS selector) or **Text to ignore** (by text or regular expression).

#### Does it work on pages that load their content with JavaScript?

No. The tool reads the HTML the server sends and does not run a browser, which is what keeps it fast and cheap. If the part you want is built by JavaScript, the tool reports `SELECTOR_NOT_FOUND` or `EMPTY_CONTENT`. Many such sites load their data from a JSON address, which you can watch directly.

#### Where are the saved versions kept?

In a key-value store named `web-page-change-monitor` in your own Apify account. Nobody else can read it. Delete the store, or turn on **Start over**, to reset.

#### What happens when I change the selector or the ignore rules?

The page is saved again as a new starting point under the new settings, because the old saved version would not be comparable. The next run after that reports changes as usual.

#### Can it log in to a page?

No. It watches pages that are open to everyone.

#### How often can it check?

As often as you schedule it in Apify Console. Please pick an interval that is fair to the website; for most pages once an hour or once a day is enough.

#### Something does not work

Open an issue on the **Issues** tab and include the page address and your settings. Every report is read and answered.

# Actor input Schema

## `urls` (type: `array`):

Add the address of each page you want to watch, for example a pricing page, a terms page or a job board.

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

A CSS selector for the part to watch, for example <code>#pricing</code>, <code>main</code> or <code>.job-list</code>. Leave empty to watch the whole page. The same selector is used for every page in the list.

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

When at least one page has changed, the tool posts the changes to this address. Paste a Slack or Discord incoming-webhook address to get a readable message there, or the webhook address of Zapier, Make, n8n or your own server to get the changes as JSON. Nothing is sent when nothing changed.

## `ignoreSelectors` (type: `array`):

CSS selectors for parts that change on every visit and should not count, for example <code>.ad</code>, <code>#clock</code> or <code>footer</code>.

## `ignoreText` (type: `array`):

Text that is removed before comparing. Plain text matches anywhere and <code>*</code> stands for any characters. For a regular expression, wrap it in slashes, for example <code>/\d+ views/</code> or <code>/Updated: .*/</code>.

## `compare` (type: `string`):

<b>Visible text</b> reports a change when the words on the page change. <b>HTML</b> also reports changed links, images and markup.

## `monitorName` (type: `string`):

Saved versions are kept under this name. Use different names to watch the same page separately, for example with different selectors in different tasks.

## `resetBaseline` (type: `boolean`):

Forget the saved versions of these pages and take this run as the new starting point.

## `includeContent` (type: `boolean`):

Add the full text that was compared to each result.

## `maxDiffLines` (type: `integer`):

For a page with very many changes, list at most this many added and this many removed lines.

## `requestTimeoutSecs` (type: `integer`):

How long to wait for one page before giving up.

## `userAgent` (type: `string`):

The name the tool sends with each request. Leave empty to use the tool's own name, which tells site owners what is visiting.

## Actor input object example

```json
{
  "urls": [
    {
      "url": "https://apify.com/change-log"
    }
  ],
  "compare": "text",
  "monitorName": "default",
  "resetBaseline": false,
  "includeContent": false,
  "maxDiffLines": 200,
  "requestTimeoutSecs": 30
}
```

# Actor output Schema

## `pages` (type: `string`):

One record per page checked: whether it changed, and the lines added and removed.

## `summary` (type: `string`):

How many pages were new, unchanged, changed or could not be checked, and whether the webhook was sent.

# 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 = {
    "urls": [
        {
            "url": "https://apify.com/change-log"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("cyber1nj3ct0r/web-page-change-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 = { "urls": [{ "url": "https://apify.com/change-log" }] }

# Run the Actor and wait for it to finish
run = client.actor("cyber1nj3ct0r/web-page-change-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 '{
  "urls": [
    {
      "url": "https://apify.com/change-log"
    }
  ]
}' |
apify call cyber1nj3ct0r/web-page-change-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,cyber1nj3ct0r/web-page-change-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/oKAiLk4QmK28KQvSJ/builds/w6ftellIS2qnEr5Fi/openapi.json
