# See When a Web Page Changed: Wayback History & Text Diff (`craigmckee/wayback-change-tracker`) Actor

Get the Internet Archive history of any URL: first/last seen, number of real content changes per year, and optional text diff between archived versions.

- **URL**: https://apify.com/craigmckee/wayback-change-tracker.md
- **Developed by:** [Print & Plan UK](https://apify.com/craigmckee) (community)
- **Categories:** SEO tools, News
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.00 / 1,000 url history summariseds

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

## See When a Web Page Changed: Wayback History & Text Diff

**What it does:** shows when a web page changed and what changed, using the Internet Archive's Wayback Machine, by Print & Plan UK. **You give it:** page URLs (or a whole site or path), an optional start year, and whether to compare content. **You get:** one summary per URL with first and last capture, number of content versions, changes per year and days since the last change, plus an optional readable text diff of the latest version against the previous one. **Cost per run:** $0.004 per URL summarised, plus $0.004 more when you ask for a diff (2 archived versions at $0.002 each), so 100 URLs with diffs cost $0.80; failed lookups are free. **Example inputs:** `https://apify.com/pricing`, `https://www.python.org/downloads/`, `https://www.bbc.co.uk/terms`.

Use it to track competitor pricing and terms pages over time, research a domain's history before buying it, collect evidence for compliance and disputes, run SEO content-decay audits and do journalism research.

### Why this Actor?

Other Wayback Actors list raw snapshots. This one answers the question you actually have: *"Has this page changed, how often, and what's different?"*

- **Change summary per URL**: capture count, unique content versions, change count, last change date and per-year breakdowns.
- **Content diff**: latest version vs the previous *different* version, or vs the very first capture. Visible text only (scripts and styles stripped).
- **Whole-site mode**: `prefix`, `host` and `domain` match types summarise every archived URL under a path or site, with the top URLs listed.
- **Optional raw capture rows**: timestamp, digest, size and snapshot link, if you want the full list.
- **Official public CDX API**: no scraping tricks, no proxies, polite rate limiting with retries.

### Input example

```json
{
  "urls": ["https://apify.com/pricing", "https://www.python.org/downloads/"],
  "matchType": "exact",
  "from": "2023",
  "maxSnapshotsPerUrl": 200,
  "compareContent": "previousVsLatest",
  "includeSnapshots": false
}
```

### Output example (summary item, trimmed)

```json
{
  "type": "summary",
  "url": "https://apify.com/pricing",
  "snapshotCount": 131,
  "firstCaptured": "2023-01-29T23:10:04+00:00",
  "lastCaptured": "2026-10-03T19:35:38+00:00",
  "uniqueContentVersions": 131,
  "changeCount": 129,
  "changesPerYear": {"2023": 19, "2024": 26, "2025": 38, "2026": 46},
  "contentComparison": {
    "mode": "previousVsLatest",
    "before": "2026-10-03T03:43:41+00:00",
    "after": "2026-10-03T19:35:38+00:00",
    "visibleTextChanged": true,
    "similarity": 0.9978,
    "addedLines": ["Browse 80,364 Actors"],
    "removedLines": ["Browse 79,601 Actors"],
    "beforeSnapshotUrl": "https://web.archive.org/web/20261003034341/https://apify.com/pricing",
    "afterSnapshotUrl": "https://web.archive.org/web/20261003193538/https://apify.com/pricing"
  }
}
```

**Note:** a "change" means the archived bytes differ (a different content hash). Dynamic pages can change on every capture because of counters or tokens. Use `contentComparison.visibleTextChanged` and `similarity` to see whether the visible text really changed.

### Pricing (pay per event)

| Event | Price |
|---|---|
| URL history summarised | $0.004 |
| Archived version downloaded (2 per compared URL) | $0.002 each |
| Capture record (only with "Output every capture record") | $0.0003 |

A summary plus a content diff costs $0.008 per URL. Failed API lookups are not charged.

### FAQ

**Why is it slow sometimes?** The Internet Archive is a non-profit and rate-limits heavy use. The Actor retries politely, and concurrency is capped at 5 (default 2).

**Can I monitor pages going forward?** Yes. Schedule the Actor daily or weekly with `compareContent: previousVsLatest`, then alert on `daysSinceLastChange` or `visibleTextChanged` using an Apify webhook or integration.

**Does it archive pages?** No. It only reads existing public captures.

Data © Internet Archive, used through their public CDX/Wayback APIs. Please respect their terms of use.

### More tools from this developer

- [Bulk Domain Intel (RDAP)](https://apify.com/craigmckee/domain-intel-rdap): domain age, expiry, registrar, DNS and an SPF/DMARC/DKIM grade.
- [Website Tech Stack Detector](https://apify.com/craigmckee/tech-stack-detector): CMS, ecommerce, analytics and CDN, with evidence for each detection.
- [Broken Link & Redirect Chain Auditor](https://apify.com/craigmckee/site-link-auditor): broken links, redirect chains, mixed content and noindex pages.
- [Document to Markdown + RAG chunks](https://apify.com/craigmckee/document-to-markdown): PDF, Word, PowerPoint and Excel to Markdown and RAG-ready chunks.

# Actor input Schema

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

Pages (or sites, with match type) to look up in the Internet Archive's Wayback Machine, e.g. `https://apify.com/pricing`.

## `matchType` (type: `string`):

`exact` = this URL only (enables content comparison). `prefix` = all URLs starting with it. `host` = every page on this host. `domain` = host plus subdomains.

## `from` (type: `string`):

Only captures on or after this date. Formats: `2020`, `202003`, `2020-03-15`.

## `to` (type: `string`):

Only captures on or before this date. Same formats as From.

## `maxSnapshotsPerUrl` (type: `integer`):

Upper limit of capture records analysed per input URL.

## `mostRecentFirst` (type: `boolean`):

When the limit is hit, keep the most recent captures (on) or the oldest (off).

## `collapseIdenticalCaptures` (type: `boolean`):

Merge back-to-back captures whose content hash is identical, so each record represents a content version.

## `onlySuccessfulCaptures` (type: `boolean`):

Ignore redirects, errors and other non-200 captures.

## `compareContent` (type: `string`):

Download two archived versions (exact match only) and return a text diff: the latest version vs the previous different one, or vs the very first capture.

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

Maximum added/removed lines returned in the comparison.

## `includeSnapshots` (type: `boolean`):

Also push one dataset row per capture (timestamp, digest, size, snapshot link). Charged per record.

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

URLs processed in parallel. Keep this low; the Internet Archive is a non-profit service.

## Actor input object example

```json
{
  "urls": [
    "https://apify.com/pricing",
    "https://www.python.org/downloads/"
  ],
  "matchType": "exact",
  "maxSnapshotsPerUrl": 1000,
  "mostRecentFirst": true,
  "collapseIdenticalCaptures": true,
  "onlySuccessfulCaptures": true,
  "compareContent": "previousVsLatest",
  "maxDiffLines": 60,
  "includeSnapshots": false,
  "maxConcurrency": 2
}
```

# 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 = {
    "urls": [
        "https://apify.com/pricing",
        "https://www.python.org/downloads/"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("craigmckee/wayback-change-tracker").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://apify.com/pricing",
        "https://www.python.org/downloads/",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("craigmckee/wayback-change-tracker").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://apify.com/pricing",
    "https://www.python.org/downloads/"
  ]
}' |
apify call craigmckee/wayback-change-tracker --silent --output-dataset

```

## MCP server setup

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

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/blf4vllV3Jzo2o62c/builds/i2Jcl4zyrJgt5sbpX/openapi.json
