# Website Change Monitor | Page Diff Alerts (`taroyamada/url-change-watch-scraper`) Actor

Monitor public web pages and receive source-linked added/removed text, change alerts, and portfolio diff reports. Unchanged checks emit no rows and no event charge.

- **URL**: https://apify.com/taroyamada/url-change-watch-scraper.md
- **Developed by:** [naoki anzai](https://apify.com/taroyamada) (community)
- **Categories:** Automation, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $80.00 / 1,000 url change detecteds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js/docs.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python/docs.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/integrations/mcp.md).

If your project is in a different language, use 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

## Website Change Monitor | Page Diff Alerts

Competitive intelligence, product operations, and web teams use this Actor to track approved public pages.
Input public URLs with optional CSS focus and noise filters.
Get source-linked added/removed text, change alerts, snapshots, and portfolio digest reports.

### Store Quickstart

The first run stores a free baseline. Schedule the same input to receive rows only when the watched content changes.

```json
{
  "targets": [
    {
      "name": "Competitor pricing",
      "url": "https://example.com/pricing",
      "cssSelector": "main",
      "ignoreSelectors": [".cookie-banner"]
    }
  ],
  "initialRunMode": "baseline_only",
  "generateDigest": true,
  "emitSnapshots": false,
  "emitUnchanged": false,
  "maxDiffSegments": 20,
  "maxChargeUsd": 10,
  "snapshotKey": "competitor-pricing",
  "dryRun": false
}
````

An unchanged run writes zero dataset rows and creates zero event charges.

### Run the next report

- Audit content, headings, metadata, and crawlability with [Site QA Content Report](https://apify.com/taroyamada/site-qa-content-report-scraper).
- Compare pricing, changelogs, release notes, and status pages with [SaaS Pricing & Changelog Battlecard](https://apify.com/taroyamada/saas-pricing-changelog-battlecard-watch-scraper).
- Run a multi-site technical regression audit with [Technical SEO & AI Crawler Audit](https://apify.com/taroyamada/technical-seo-portfolio-regression-report).

### Input examples

#### Pricing-page watch

```json
{
  "targets": [
    {
      "name": "Pricing",
      "url": "https://example.com/pricing",
      "cssSelector": "main",
      "ignoreSelectors": [".last-updated"]
    }
  ],
  "initialRunMode": "baseline_only",
  "stripDates": true,
  "generateDigest": true,
  "maxChargeUsd": 10,
  "snapshotKey": "pricing-watch",
  "dryRun": false
}
```

#### Product documentation watch

```json
{
  "targets": [
    {
      "name": "API changelog",
      "url": "https://example.com/changelog",
      "cssSelector": "article",
      "ignoreSelectors": []
    },
    {
      "name": "API limits",
      "url": "https://example.com/docs/limits",
      "cssSelector": "main",
      "ignoreSelectors": ["nav"]
    }
  ],
  "initialRunMode": "baseline_only",
  "stripDates": false,
  "stripVolatileNumbers": false,
  "generateDigest": true,
  "maxDiffSegments": 30,
  "maxChargeUsd": 10,
  "snapshotKey": "api-docs-watch",
  "dryRun": false
}
```

#### Paid first-observation trial

Use `emit_backfill` only when you explicitly want the current page captured as the first change row.

```json
{
  "targets": [
    {
      "name": "Terms page",
      "url": "https://example.com/terms",
      "cssSelector": "main",
      "ignoreSelectors": []
    }
  ],
  "initialRunMode": "emit_backfill",
  "generateDigest": false,
  "emitSnapshots": false,
  "maxChargeUsd": 0.1,
  "snapshotKey": "terms-trial",
  "dryRun": false
}
```

### Sample output

```json
{
  "rowType": "url_change",
  "billingEventName": "url-change-detected",
  "targetName": "Competitor pricing",
  "sourceUrl": "https://example.com/pricing",
  "changeKind": "content_hash_diff",
  "addedSegments": ["The Pro plan now includes priority support."],
  "removedSegments": ["The Pro plan includes standard support."],
  "addedSegmentCount": 1,
  "removedSegmentCount": 1,
  "changeRatio": 0.25,
  "contentHash": "bcf38e4a58839f6c7686c3f1",
  "previousContentHash": "dba4a91988d5ed0d5f3dbd31",
  "checkedAt": "2026-07-27T01:00:00.000Z"
}
```

Each change row includes the source URL, final URL, HTTP status, current and previous hashes, bounded added/removed text segments, a change ratio, and a stable key. Digest rows summarize all changed targets in the run.

### Pricing

| Event | Price | Delivered when |
|---|---:|---|
| `url-change-detected` | $0.08 | A normalized watched region changes, or an explicit backfill is requested |
| `url-snapshot` | $0.02 | `emitSnapshots` is enabled and a public page is fetched successfully |
| `change-digest-report` | $5.00 | At least one change exists and `generateDigest` is enabled |

`maxChargeUsd` is checked before delivery. The Actor fails before pushing billable rows if the configured output would exceed the buyer-approved cap.

### Change controls

- `cssSelector` limits the watched region to a simple ID, class, or tag selector.
- `ignoreSelectors` removes known noisy regions.
- `stripDates` removes common timestamps before hashing.
- `stripVolatileNumbers` normalizes long counters.
- `maxDiffSegments` bounds the added and removed text included in each row.
- `snapshotKey` keeps recurring watches isolated.

### Compliance and limitations

- Public HTTP(S) pages supplied by the buyer only.
- Private networks, metadata endpoints, non-HTTP URLs, disallowed robots paths, access challenges, and login walls fail closed.
- Redirect count, response size, and request time are bounded.
- Results are source-linked observations and do not determine legal, security, compliance, or financial conclusions.
- Lightweight CSS focus is not a full browser selector engine, and text diffs do not represent pixel-level layout changes.

### See also

- [Site QA Content Report](https://apify.com/taroyamada/site-qa-content-report-scraper)
- [SaaS Pricing & Changelog Battlecard](https://apify.com/taroyamada/saas-pricing-changelog-battlecard-watch-scraper)
- [Technical SEO & AI Crawler Audit](https://apify.com/taroyamada/technical-seo-portfolio-regression-report)

# Actor input Schema

## `targets` (type: `array`):

Public pages to monitor. Optional cssSelector narrows the hashed region; ignoreSelectors remove noisy nodes (as text patterns).

## `maxTargets` (type: `integer`):

Maximum targets to check in one run.

## `emitSnapshots` (type: `boolean`):

Emit a url-snapshot row whenever a page is successfully fetched (in addition to change rows).

## `generateDigest` (type: `boolean`):

When any change is detected, emit one change-digest-report summarizing the run.

## `stripDates` (type: `boolean`):

Remove ISO-like dates and common timestamps before hashing to reduce false positives.

## `stripVolatileNumbers` (type: `boolean`):

Normalize long digit runs (view counts, etc.) before hashing.

## `maxDiffSegments` (type: `integer`):

Maximum number of added and removed text segments included in each change row.

## `emitUnchanged` (type: `boolean`):

When false (default), repeated unchanged runs emit zero rows and zero charges.

## `dryRun` (type: `boolean`):

Emit local sample rows without fetching or charging.

## `initialRunMode` (type: `string`):

emit\_backfill allows first-run change rows when no baseline exists; baseline\_only records hashes with zero output rows.

## `snapshotKey` (type: `string`):

Optional state namespace for canary and recurring schedules.

## `maxChargeUsd` (type: `number`):

Fail before delivery when configured output events would exceed this buyer-approved cap.

## Actor input object example

```json
{
  "targets": [
    {
      "name": "Example page",
      "url": "https://example.com/",
      "cssSelector": "",
      "ignoreSelectors": []
    }
  ],
  "maxTargets": 25,
  "emitSnapshots": false,
  "generateDigest": true,
  "stripDates": true,
  "stripVolatileNumbers": false,
  "maxDiffSegments": 20,
  "emitUnchanged": false,
  "dryRun": false,
  "initialRunMode": "baseline_only",
  "snapshotKey": "",
  "maxChargeUsd": 10
}
```

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("taroyamada/url-change-watch-scraper").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("taroyamada/url-change-watch-scraper").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{}' |
apify call taroyamada/url-change-watch-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=taroyamada/url-change-watch-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Website Change Monitor | Page Diff Alerts",
        "description": "Monitor public web pages and receive source-linked added/removed text, change alerts, and portfolio diff reports. Unchanged checks emit no rows and no event charge.",
        "version": "0.1",
        "x-build-id": "CRLeoHAzDsoVyCKOj"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/taroyamada~url-change-watch-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-taroyamada-url-change-watch-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/taroyamada~url-change-watch-scraper/runs": {
            "post": {
                "operationId": "runs-sync-taroyamada-url-change-watch-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/taroyamada~url-change-watch-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-taroyamada-url-change-watch-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "targets": {
                        "title": "Watch targets",
                        "type": "array",
                        "description": "Public pages to monitor. Optional cssSelector narrows the hashed region; ignoreSelectors remove noisy nodes (as text patterns).",
                        "default": [
                            {
                                "name": "Example page",
                                "url": "https://example.com/",
                                "cssSelector": "",
                                "ignoreSelectors": []
                            }
                        ]
                    },
                    "maxTargets": {
                        "title": "Max targets",
                        "minimum": 1,
                        "maximum": 100,
                        "type": "integer",
                        "description": "Maximum targets to check in one run.",
                        "default": 25
                    },
                    "emitSnapshots": {
                        "title": "Emit snapshot rows",
                        "type": "boolean",
                        "description": "Emit a url-snapshot row whenever a page is successfully fetched (in addition to change rows).",
                        "default": false
                    },
                    "generateDigest": {
                        "title": "Generate digest report",
                        "type": "boolean",
                        "description": "When any change is detected, emit one change-digest-report summarizing the run.",
                        "default": true
                    },
                    "stripDates": {
                        "title": "Strip date-like tokens",
                        "type": "boolean",
                        "description": "Remove ISO-like dates and common timestamps before hashing to reduce false positives.",
                        "default": true
                    },
                    "stripVolatileNumbers": {
                        "title": "Strip volatile counters",
                        "type": "boolean",
                        "description": "Normalize long digit runs (view counts, etc.) before hashing.",
                        "default": false
                    },
                    "maxDiffSegments": {
                        "title": "Maximum added/removed segments",
                        "minimum": 1,
                        "maximum": 100,
                        "type": "integer",
                        "description": "Maximum number of added and removed text segments included in each change row.",
                        "default": 20
                    },
                    "emitUnchanged": {
                        "title": "Emit unchanged rows",
                        "type": "boolean",
                        "description": "When false (default), repeated unchanged runs emit zero rows and zero charges.",
                        "default": false
                    },
                    "dryRun": {
                        "title": "Dry run",
                        "type": "boolean",
                        "description": "Emit local sample rows without fetching or charging.",
                        "default": false
                    },
                    "initialRunMode": {
                        "title": "Initial run mode",
                        "enum": [
                            "emit_backfill",
                            "baseline_only"
                        ],
                        "type": "string",
                        "description": "emit_backfill allows first-run change rows when no baseline exists; baseline_only records hashes with zero output rows.",
                        "default": "baseline_only"
                    },
                    "snapshotKey": {
                        "title": "Snapshot key",
                        "type": "string",
                        "description": "Optional state namespace for canary and recurring schedules.",
                        "default": ""
                    },
                    "maxChargeUsd": {
                        "title": "Maximum event charge per run",
                        "minimum": 0.01,
                        "maximum": 1000,
                        "type": "number",
                        "description": "Fail before delivery when configured output events would exceed this buyer-approved cap.",
                        "default": 10
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
