# Website Change Detector (`eloquent_mountain/website-change-detector`) Actor

Monitors websites for changes. Detects modifications to HTML structure and visual differences via screenshots. Provides detailed change reports including HTML diff. Track multiple URLs. Use tasks for recurring runs. Integrate as API

- **URL**: https://apify.com/eloquent\_mountain/website-change-detector.md
- **Developed by:** [Paco](https://apify.com/eloquent_mountain) (community)
- **Categories:** Automation, Developer tools
- **Stats:** 79 total users, 6 monthly users, 79.7% runs succeeded, 4 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

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

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

### Website Change Detector

This Website Change Detector is a tool for monitoring changes in web pages over time. It detects modifications to both the HTML structure and visual differences via screenshots, and generates detailed reports including an HTML diff. This Actor is ideal for tracking changes on competitor websites, important pages, or any web content that needs constant monitoring.

### What Does This Actor Do?

This actor automates the process of web page monitoring, it offers a comprehensive solution for detecting modifications in web content by:

- **HTML Structure Change Detection:** It identifies changes to a webpage's underlying HTML structure by calculating a signature of the page and comparing it to the previous version.
- **Visual Change Detection:** It captures screenshots of the web page and identifies visual changes to the page by comparing the current screenshots with the previous ones.
- **Detailed Change Reports:** Provides a granular report of HTML changes, using an HTML diffing library.Every run is stored
- **Multi-URL Support:** Can monitor changes in multiple URLs of different websites.
- **Avoids Bot Detection:** Takes several measures to avoid bot detection (using realistic user-agents and headless browser settings).

### How to Use the Website Change Detector

Using this actor is straightforward:

1. **Create an Apify Account:** Start with a free Apify account using your email.
2. **Open the Website Change Detector:** Go to the actor page.
3. **Provide URLs:** Input a list of URLs you want to monitor.
4. **Run the Actor:** Click the "Start" button and wait for the checks to complete.
5. **Download Your Data:** Retrieve the change reports in JSON format or access all historical runs in **Storage > Key-value stores > webpage-snapshots > history..**
6. **OPTIONAL: Schedule tasks**: Create a scheduled task for this actor to run automatically on any given time interval e.g cron job. Navigate to "Schedules" in the Apify UI.

### Input

To start monitoring websites, the actor accepts the following input parameters:

- `urls`: An array of URLs of the web pages you want to monitor.
- `save_screenshot`: A boolean flag to determine whether to take a screenshot of the web pages or not (default is `false`).
- `cacheTtl`: How long a cached extraction for a given content hash stays valid, in seconds (default `86400`, i.e. 24h). On a cache hit within this window the page's expensive processing (screenshot capture) is skipped and the previous result is reused. Set to `0` to keep cached entries forever.
- `forceRefresh`: A boolean flag that ignores any cached extractions and re-processes every page from scratch, refreshing the cache (default is `false`).

#### Content-hash caching & dedup

The dominant use case for this Actor is **monitoring** — running the same URLs repeatedly, where most pages haven't changed between runs. Re-doing the expensive work (screenshot capture) on unchanged content is pure waste, so the Actor caches results by content hash:

- The filtered page content is hashed into a `signature`. That signature keys a persistent cache mapping the content hash to its extraction.
- On a **cache hit** (the exact same content was seen in a previous run, within `cacheTtl`), the cached extraction is reused and the screenshot capture is skipped. The record is marked `_cached: true`.
- Identical pages **within a single run** are deduplicated too (common when the same page is reached via different URL/tracking parameters).
- Every record carries `_contentChanged` (did the content differ from the last check of this URL) and `_cached` (was the extraction reused), so downstream billing can charge cached pages at a lower rate — you only pay full price for pages that actually changed.

Here’s an example of an input configuration in JSON format:

```json
{
    "urls": [
       "https://apify.com/",
        "https://www.example.com/",
        "https://www.ikea.com/nl/nl/p/onsevig-vloerkleed-laagpolig-veelkleurig-60497078/"
    ]
    "save_screenshot": true
}
```

### Output

The output from this Actor is stored in a dataset. You can view this data in the Apify UI or download it in JSON, CSV, or other formats.

The output is a JSON object with the following structure for each URL:

```json
{
  "url": "https://apify.com/",
  "hasChanged": true,
  "screenshotChange": false,
  "date": 1704000000.000,
  "htmlDiff": "<div class=\"diff\">...</div>",
  "previous_screenshot": "base64_encoded_previous_screenshot",
  "current_screenshot": "base64_encoded_current_screenshot",
  "signature": "sha256_hash_of_the_html",
  "html": "<html>...</html>",
  "_cached": false,
  "_contentChanged": true,
  "_dedupedInRun": false
}
```

- `url`: The URL of the web page that was monitored.
- `hasChanged`: A boolean that indicates if there were changes to the HTML structure since the last run
- `screenshotChange`: A boolean that indicates if there were changes to the screenshot since the last run.
- `date`: The timestamp of when the check was made
- `htmlDiff`:  A string that contains the differences in the HTML if `hasChanged` is `true`, it contains `null` otherwise.
- `previous_screenshot`: Base64-encoded string of the previous screenshot, if available, `null` otherwise
- `current_screenshot`: Base64-encoded string of the current screenshot, if available, `null` otherwise
- `signature`: SHA256 hash of the page's HTML (used for change detection).
- `html`: The current HTML of the page
- `_cached`: `true` if the extraction was reused from the content-hash cache instead of being re-computed (the screenshot capture was skipped).
- `_contentChanged`: `true` if the content differs from the last check of this URL.
- `_dedupedInRun`: `true` if identical content was already seen earlier in the same run and this record reused that extraction.

### How Can I Use the Data from the Website Change Detector?

- **Competitor Monitoring:** Track changes on competitor websites, to identify changes in layout, pricing, or marketing.
- **Website Monitoring:** Monitor your own websites for unwanted changes or defacement.
- **Content Tracking:** Track changes on news websites, research pages, or any other information source.
- **Alerting:** Use the API and webhooks to send alerts when changes are detected.

### How Does the Website Change Detector Work?

This actor fetches, analyzes, and compares web page data using a series of steps:

1. **Input Configuration:**
   - The actor takes a list of URLs and parameters such as `check_interval` and `save_screenshot`.
2. **HTML Content Fetching:**
   - The actor uses httpx to fetch the HTML content of the specified URLs.
3. **HTML Signature Generation:**
   - The HTML content is processed and a hash of its content (signature) is generated after removing dynamic attributes, comments, and normalizing whitespaces.
   - The signature is used to detect changes in the HTML structure.
4. **Screenshot Capturing (optional):**
   - If `save_screenshot` is true, it will create a full-page screenshot of the web page using Selenium.
5. **Change Detection:**
   - The current HTML signature is compared with the previous one, if it is different then `hasChanged` will be set to `true`.
   - The current screenshot is compared to the previous one (if available), if they are different then `screenshotChange` will be set to `true`.
   - If changes are detected, an HTML diff of the previous and current versions of the HTML is generated.
6. **Data Storage:**
   - All results, including the URL, `hasChanged`, `screenshotChange`, timestamps, HTML diff, screenshots, and the current HTML, are stored in Apify's Key-value store.
   - The current HTML signature and screenshots are also saved in the Key-Value store for future comparisons.
   - **You can find your data in Apify: Storage > Key-value stores > webpage-snapshots.** Data is stored indefinitely unless manually removed.

### Integrations

This Actor integrates with other Apify platform components and other external services:

- **Webhooks:** Automatically notify you when the scraping is complete or send the data to another application.
- **API:** Control the Actor programmatically using the Apify API.
- **Cloud Services:** Use Apify integrations to automatically store the data in services like Google Sheets, Google Drive, Slack, and others.

### Track Changes on Any Webpage with This Dynamic Monitor

This Website Change Detector will allow you to track changes in the websites you need by efficiently monitoring for changes in the structure, and also tracking the screenshots.

### Not What You Need? Build Your Own!

If this actor doesn't exactly meet your needs, you can use one of the scraper templates available in Python, JavaScript, and TypeScript to get started or check out our open-source library [Crawlee](https://github.com/apify/crawlee).

You can also request a custom scraping solution from us.

### Your Feedback

Your feedback is valuable to us. If you have any suggestions or find a bug, please create an issue on the Actor's Issues tab in the Apify Console.

### FAQ

#### How much does Website Change Detector cost?

This actor uses Apify's Pay-per-result pricing model. Apify also provides you with free monthly usage credits.

#### How can I use Website Change Detector with the Apify API?

You can access the Apify API programmatically via RESTful HTTP endpoints or SDKs (apify-client NPM package for JavaScript, apify-client PyPI package for Python) to run, manage, and get the data out of any actor.

#### Is it legal to scrape data using the Website Change Detector?

This actor only extracts data that is publicly available. Please ensure that you comply with the terms and conditions of websites you scrape, and you are responsible for ensuring your compliance with data privacy regulations such as GDPR.

# Actor input Schema

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

URLs of the website to monitor

## `save_screenshot` (type: `boolean`):

Save the page screenshot

## `cacheTtl` (type: `integer`):

How long a cached extraction for a given content hash stays valid, in seconds. On a cache hit within this window the page's expensive processing (screenshot capture) is skipped and the previous result is reused. Set to 0 to keep cached entries forever.

## `forceRefresh` (type: `boolean`):

Ignore any cached extractions and re-process every page from scratch, refreshing the cache. Use this for a full re-scan that bypasses the cache.

## Actor input object example

```json
{
  "urls": [
    "https://www.ikea.com/nl/nl/p/onsevig-vloerkleed-laagpolig-veelkleurig-60497078/",
    "https://apify.com/"
  ],
  "save_screenshot": false,
  "cacheTtl": 86400,
  "forceRefresh": false
}
```

# 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": [
        "https://www.ikea.com/nl/nl/p/onsevig-vloerkleed-laagpolig-veelkleurig-60497078/",
        "https://apify.com/"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("eloquent_mountain/website-change-detector").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": [
        "https://www.ikea.com/nl/nl/p/onsevig-vloerkleed-laagpolig-veelkleurig-60497078/",
        "https://apify.com/",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("eloquent_mountain/website-change-detector").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": [
    "https://www.ikea.com/nl/nl/p/onsevig-vloerkleed-laagpolig-veelkleurig-60497078/",
    "https://apify.com/"
  ]
}' |
apify call eloquent_mountain/website-change-detector --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,eloquent_mountain/website-change-detector"
        }
    }
}

```

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/xXYaEGV6biNPxmQ8U/builds/Ny8PFbEU88KhkecOs/openapi.json
