# Wayback Machine Scraper: Snapshots, History & Old URLs (`latamdatatools/wayback-machine-history`) Actor

Get the Wayback Machine history of any URL or domain from archive.org's official CDX API: first and last capture, last working copy, status changes, content versions, every snapshot, and all historical URLs of a domain (for SEO recovery and due diligence).

- **URL**: https://apify.com/latamdatatools/wayback-machine-history.md
- **Developed by:** [Julian Genuario](https://apify.com/latamdatatools) (community)
- **Categories:** SEO tools, Developer tools
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.50 / 1,000 result rows

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

## Wayback Machine Scraper: Snapshots, History & Old URLs

Get the **Internet Archive (Wayback Machine) history** of any URL or domain in a clean table, through archive.org's **official CDX API**. Three modes:

1. **History summary per URL** (default): first capture, last capture, **last working copy** (last HTTP 200), last status code, **status changes** over time (200 to 301 to 404...), number of distinct content versions, days captured and captures per year.
2. **All snapshots per URL**: every capture with date, HTTP status, MIME type, content digest, size and the link to the archived copy. Collapse to **only the captures where the content changed**, or one per day / month / year.
3. **Historical URLs of a domain**: every URL the Wayback Machine has seen on a domain (and its subdomains, or under a path prefix), with the first capture date, status and archived link.

### What does Wayback Machine Scraper do?

Wayback Machine Scraper uses archive.org's official CDX API to get the history of any URL or domain: first and last capture, last working archived copy, status changes, content versions, every snapshot and all historical URLs of a domain. Use it for SEO recovery of lost pages, expired domain research and due diligence.

### How to use Wayback Machine Scraper

1. Click **Try for free** on this page (a free Apify account is enough to start).
2. Fill in the input (see the examples below) or keep the prefilled example.
3. Click **Start** and wait for the run to finish.
4. Download the results from the **Output** tab as JSON, CSV, Excel or HTML, or read them with the Apify API.
5. Optional: create a **Schedule** to run it daily or weekly, and connect a webhook or an integration (Make, Zapier, n8n, Slack).

### What people use it for

- **SEO recovery**: find old URLs of a site (after a migration or a domain purchase) that still have backlinks, and the archived content to restore or redirect.
- **Expired domain due diligence**: how old is the site, what was on it, when did it go dark, how often did it change.
- **Content and legal evidence**: when did a page change, and what did it say on a given date (link to the archived copy).
- **Competitor research**: how often a competitor's pricing or landing page changed over the years.
- **Dead link fixing**: replace broken links with the last working archived copy.

### Input

| Field | What it does |
|---|---|
| **What to get** | `summary`, `snapshots` or `domainUrls`. |
| **URLs or domains** | `example.com`, `example.com/pricing`, with or without `https://`. Also from a **dataset** or a **CSV / Google Sheets** link. |
| **From / To date** | `YYYY`, `YYYY-MM` or `YYYY-MM-DD`. |
| **HTTP status filter** | `200`, `3xx`, `!404`... |
| **MIME type filter** | `text/html`, `application/pdf`, `image/*`... |
| **Snapshots: collapse** | Every capture, only content changes, one per day / month / year. |
| **Historical URLs: scope** | Domain + subdomains, exact host, or URL prefix (`example.com/blog/`). URLs with `?parameters` are skipped by default (tracking noise). |
| **Max results per URL**, **Max URLs per run** | Limits. |
| **Only new since the last run** | For scheduled runs: only new snapshots / newly discovered URLs. |

#### Example: old URLs of a domain

```json
{ "mode": "domainUrls", "urls": ["example.com"], "mimeTypes": ["text/html"], "statusCodes": ["200"], "maxResultsPerUrl": 5000 }
```

#### Example: when did the pricing page change in 2024-2026?

```json
{ "mode": "snapshots", "urls": ["example.com/pricing"], "collapse": "contentChange", "from": "2024" }
```

### Output

Summary row:

```json
{
  "recordType": "summary",
  "input": "apify.com",
  "status": "ok",
  "firstCapture": "2007-05-31T10:15:38Z",
  "firstCaptureUrl": "https://web.archive.org/web/20070531101538/http://www.apify.com:80/",
  "lastCapture": "2026-10-25T20:21:20Z",
  "lastStatusCode": "200",
  "lastOkCapture": "2026-10-25T20:21:20Z",
  "lastOkCaptureUrl": "https://web.archive.org/web/20261025202120/https://apify.com/",
  "daysWithCaptures": 1151,
  "distinctVersions": 744,
  "capturesByYear": { "2007": 3, "2018": 194, "2026": 104 },
  "statusChanges": [{ "from": "200", "to": "301", "at": "2024-02-03T10:00:00Z" }]
}
```

Snapshot row: `url`, `timestamp`, `capturedAt`, `statusCode`, `mimeType`, `digest`, `contentChanged`, `length`, `archiveUrl`. Historical URL row: `url`, `firstCapture`, `statusCode`, `mimeType`, `archiveUrl`. URLs that were never archived come back with `status: "not-archived"` (free).

### Pricing

Pay per event: **USD 1.50 per 1,000 results** (a summary, a snapshot or a historical URL). "Not archived" and failed rows are free. The run respects your *max charge per run*.

### Fair use of archive.org

The Internet Archive is a non-profit. This Actor uses only its public CDX API, sends **one request at a time** with a delay (4 s by default, configurable from 2 s), identifies itself with its own user-agent, pages through big results with the official resume key, and **stops cleanly** if archive.org keeps answering HTTP 429 instead of retrying aggressively. It does not download archived pages. Big domains with hundreds of thousands of URLs take time: use the filters and limits.

### Cost examples

Prices at the current pay-per-event rate: USD 1.50 per 1,000 result rows (summaries, snapshots or historical URLs; URLs that were never archived are free). You can set a maximum charge per run in the run options.

| Job | Approximate cost |
|---|---|
| Test run: summary of 2 URLs (measured: 8 s) | about $0.003 |
| Summary for 1,000 domains | about $1.50 |
| Up to 1,000 snapshots of one page | about $1.50 |
| 20,000 historical URLs of a domain (SEO migration) | about $30.00 |

### Use it from your code, an integration or an AI agent

**Python** (`pip install apify-client`):

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("latamdatatools/wayback-machine-history").call(run_input={
  "mode": "summary",
  "urls": [
    "apify.com",
    "apify.com/pricing"
  ]
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["url"], item.get("firstCapture"), item.get("lastCapture"))
```

**JavaScript / Node.js** (`npm install apify-client`):

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

const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('latamdatatools/wayback-machine-history').call({
  mode: 'summary',
  urls: [
    'apify.com',
    'apify.com/pricing'
  ]
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

**No code:**

- **Schedules:** save your input as a Task and run it daily or weekly from Apify Console (Schedules).
- **Integrations:** send the results to Google Sheets, Slack, email, Make, Zapier, n8n or Airbyte from the Integrations tab, or call your own webhook when a run finishes.
- **AI agents:** add it as a tool in Claude, Cursor, VS Code and other MCP clients through the Apify MCP server (`https://mcp.apify.com`), so the agent can check when a page first appeared or how it changed.

### FAQ

**Why are some captures marked with status null?** The Wayback index has no status for some records (redirect captures, warc revisits).

**Does it get the archived HTML?** No, it returns the links to the archived copies. Open them, or feed them to a scraper.

Questions? Open an issue in the Issues tab.

# Actor input Schema

## `mode` (type: `string`):

History summary: one row per URL with first and last capture, last working capture, status changes, number of versions and captures per year. Snapshots: every capture of each URL. Historical URLs of a domain: every URL the Wayback Machine ever saw on the domain.

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

One per line: a page URL (example.com/pricing) or a domain (example.com). http/https does not matter: the Wayback index ignores it.

## `datasetId` (type: `string`):

Optional: read the URLs from an Apify dataset (field set in "URL field").

## `csvUrl` (type: `string`):

Optional: public CSV with a header row (or one URL per line). Google Sheets links work if shared as "Anyone with the link".

## `urlField` (type: `string`):

Field / column with the URL or domain.

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

Optional: YYYY, YYYY-MM or YYYY-MM-DD.

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

Optional: YYYY, YYYY-MM or YYYY-MM-DD.

## `statusCodes` (type: `array`):

Optional: keep only captures with these statuses, e.g. 200, 3xx. Prefix with ! to exclude: !404.

## `mimeTypes` (type: `array`):

Optional: e.g. text/html (only pages), application/pdf. \* works as a wildcard: image/\*.

## `collapse` (type: `string`):

Snapshots mode only. Content changes = skip consecutive captures with identical content (the most useful to see when a page changed).

## `domainMatch` (type: `string`):

Historical URLs mode only. Domain = the domain and all subdomains; Host = only that exact host; Prefix = only URLs that start with the given URL (e.g. example.com/blog/).

## `skipUrlsWithParameters` (type: `boolean`):

Historical URLs mode only. On: leave out URLs with a query string (tracking parameters, session IDs, search pages), which are usually noise. Turn off to keep them (e.g. old ?p=123 links).

## `maxResultsPerUrl` (type: `integer`):

Snapshots or historical URLs returned per input (not used in summary mode).

## `maxUrls` (type: `integer`):

Inputs beyond this number are ignored.

## `onlyNewSinceLastRun` (type: `boolean`):

Snapshots and historical URLs modes: remember what was already returned (named key-value store "wayback-history-state") and only return new captures / newly seen URLs. Good for scheduled runs.

## `delayBetweenRequestsMs` (type: `integer`):

archive.org is a non-profit with rate limits. Requests are sent one at a time with this delay; on HTTP 429 the Actor waits and, if it repeats, stops cleanly.

## Actor input object example

```json
{
  "mode": "summary",
  "urls": [
    "apify.com",
    "apify.com/pricing"
  ],
  "urlField": "url",
  "collapse": "none",
  "domainMatch": "domain",
  "skipUrlsWithParameters": true,
  "maxResultsPerUrl": 1000,
  "maxUrls": 1000,
  "onlyNewSinceLastRun": false,
  "delayBetweenRequestsMs": 4000
}
```

# Actor output Schema

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

No description

## `runSummary` (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": [
        "apify.com",
        "apify.com/pricing"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("latamdatatools/wayback-machine-history").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": [
        "apify.com",
        "apify.com/pricing",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("latamdatatools/wayback-machine-history").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": [
    "apify.com",
    "apify.com/pricing"
  ]
}' |
apify call latamdatatools/wayback-machine-history --silent --output-dataset

```

## MCP server setup

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

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/T94JsgWicMhzyluv2/builds/qcGtZl2pUM3u9axxc/openapi.json
