# Wayback Machine History: Snapshots & Archived URLs API (`hillcountrybots/wayback-history`) Actor

Get a website's history from the Wayback Machine using the official archive.org APIs. List every snapshot of a URL, every archived URL on a domain, or the capture closest to a date. Dates, status codes, snapshot links and raw links. Empty and failed lookups free.

- **URL**: https://apify.com/hillcountrybots/wayback-history.md
- **Developed by:** [Hill Country Bots](https://apify.com/hillcountrybots) (community)
- **Categories:** SEO tools, Developer tools, Automation
- **Features:** Limited permissions
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$1.00 / 1,000 snapshot 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 History: Snapshots & Archived URLs API

Get the **history of any website from the Wayback Machine** in one run. This Actor uses only the **official Internet Archive APIs** (the CDX server and the Wayback Availability API) to list **every snapshot of a URL**, a **timeline with first and last seen dates, captures per year and status codes**, **every archived URL on a domain**, or **the capture closest to a date**. Each row has the capture date, the HTTP status the site returned back then, the MIME type, size, content digest, a **snapshot link** and a **raw link** to the original file. **No browser, no login, no personal data.** **$1 per 1,000 rows. Inputs with no captures, failed lookups and invalid inputs are free.**

### What does this Wayback Machine tool do?

You give it URLs or domains and pick a mode:

- **Snapshots:** every capture of each exact URL, optionally **one per day, month or year**, or **only when the content changed**
- **Timeline:** one row per URL with **first seen**, **last seen**, **total captures**, **captures per year**, **status code counts** (200, 301, 404...) and how many times the **content actually changed**
- **Archived URLs:** every unique URL the Wayback Machine holds for a **domain (with subdomains)**, a **host**, or a **path prefix** such as `example.com/blog/`, with the first capture of each
- **Closest:** the single capture nearest to a date, for example "what did this page look like on January 1, 2015?"

Filters: date range (`from`, `to`), HTTP 200 only, MIME type (for example `text/html` or `application/pdf`), and skip URLs with query strings. Caps: `maxRowsPerUrl` and `maxRows`.

It never downloads or re-hosts archived pages. You get the links; open or fetch them yourself if you need the content.

### Who is it for?

- **SEO agencies and consultants:** recover old URLs before a migration, find pages that used to rank and now 404, and rebuild redirect maps
- **Domain buyers and investors:** check what an expired or aged domain was used for before you buy it
- **Researchers, journalists and legal teams:** prove what a page said on a given date, with a permanent archive link
- **Developers and AI agents:** clean JSON through the Apify API or MCP, with a predictable price per row

### Quick start

1. Type a domain or URL (the form comes prefilled with `sitemaps.org`).
2. Pick **Snapshots**, **Archived URLs** or **Closest**. Leave `maxRowsPerUrl` at 50 for a quick look.
3. Click **Start**, then download JSON, CSV or Excel, or read the dataset through the API.

#### Sample output

First rows of a real run on **November 12, 2026** (Snapshots mode, sitemaps.org, one snapshot per year):

| Captured (UTC) | Archived URL | Status | Snapshot |
|---|---|---|---|
| 2002-04-10 19:25 | http://sitemaps.org:80/ | 200 | https://web.archive.org/web/20020410192531/http://sitemaps.org:80/ |
| 2004-07-01 21:56 | http://www.sitemaps.org:80/ | 200 | https://web.archive.org/web/20040701215604/http://www.sitemaps.org:80/ |
| 2005-02-05 07:08 | http://www.sitemaps.org:80/ | 302 | https://web.archive.org/web/20050205070836/http://www.sitemaps.org:80/ |
| 2006-12-05 09:52 | http://sitemaps.org:80/ | 200 | https://web.archive.org/web/20061205095241/http://sitemaps.org:80/ |

If an input has no captures, the run writes one row with `status: "not-found"` and `errorCode: "NO_SNAPSHOTS"`. If an input is invalid or the archive cannot answer after three retries, you get a row with `status: "error"`, an `errorCode` and a plain-English `errorMessage`. None of those rows are charged.

#### Sample timeline row

From a real Timeline run on **November 12, 2026** for `sitemaps.org`: first seen **2002-04-10**, last seen **2026-11-06**, **14,183 captures** across **24 years**, **58 content versions**, status codes `{"200": 4260, "301": 4499, "302": 1557, "403": 20, "503": 12, ...}` and captures per year from `{"2002": 2, ... "2025": 1449, "2026": 2941}`. One row, charged once.

#### Example inputs

A history timeline (first/last seen, captures per year, status codes) for a list of domains:

```json
{ "urls": ["sitemaps.org", "example.com"], "mode": "timeline" }
```

Every yearly snapshot of a homepage:

```json
{ "urls": ["sitemaps.org"], "mode": "snapshots", "collapse": "year", "maxRowsPerUrl": 50 }
```

Only captures where the page content changed, between 2015 and 2020:

```json
{ "urls": ["https://www.sitemaps.org/protocol.html"], "mode": "snapshots", "collapse": "digest", "from": "2015", "to": "2020" }
```

Every archived HTML page on a domain (no query-string noise), for a migration redirect map:

```json
{ "urls": ["sitemaps.org"], "mode": "archivedUrls", "matchType": "domain", "onlyStatus200": true, "mimeType": "text/html", "maxRowsPerUrl": 1000 }
```

Archived PDFs under one folder:

```json
{ "urls": ["example.com/docs/"], "mode": "archivedUrls", "matchType": "prefix", "mimeType": "application/pdf" }
```

What several sites looked like on January 1, 2010:

```json
{ "urls": ["sitemaps.org", "example.com"], "mode": "closest", "closestTo": "2010-01-01" }
```

### Output fields

| Field | What it means |
|---|---|
| `input` | The URL or domain you gave |
| `mode` | snapshots, archivedUrls or closest |
| `url` | Original URL as captured (may show `:80` or `http`) |
| `timestamp` | Wayback 14-digit timestamp (UTC); first capture in Archived URLs mode |
| `capturedAt` | The same time as ISO 8601 |
| `snapshotUrl` | View the capture in the Wayback Machine |
| `rawSnapshotUrl` | The original archived file, without the Wayback toolbar (`id_` link) |
| `statusCode` | HTTP status the site gave when it was captured |
| `mimeType`, `lengthBytes`, `digest` | Content type, archived size, content hash (same digest = same content) |
| `urlKey` | The archive's canonical key for the URL |
| `firstSeen`, `lastSeen`, `totalCaptures`, `capturesPerYear`, `statusCodes`, `uniqueContentVersions` | Timeline mode summary fields (`countsComplete` says whether every capture was counted) |
| `status`, `errorCode`, `errorMessage` | ok, not-found or error, and why |

The key-value store also holds `RUN_SUMMARY`: rows charged, inputs with no captures, failures, and rows per input.

### How much does it cost?

**$1 per 1,000 rows** ($0.001 per snapshot, URL or timeline row). No start fee. Rows for inputs with no captures, invalid inputs and archive failures are free. `maxRows` and the run's max-charge setting cap your spend: 50 rows cost $0.05.

### Tips for big sites

Large domains can have millions of archived URLs, and the archive answers big queries slowly. Use a **path prefix**, a **date range**, `collapse` and `maxRowsPerUrl` to keep runs fast. The Actor pages through results and paces itself at about one request per second, as the Internet Archive asks of API users. If the archive is overloaded it retries three times with backoff, then reports `ARCHIVE_UNAVAILABLE` or `ARCHIVE_TIMEOUT` for free.

### Is it legal?

The Actor only calls the Internet Archive's public, documented APIs and returns capture metadata and links. It does not log in, does not bypass anything, and collects no personal data. Archived content belongs to its original owners; check the Internet Archive's terms before republishing it.

### Related tools from Hill Country Bots

- [Sitemap URL Extractor](https://apify.com/hillcountrybots/sitemap-url-extractor): today's URL list, to compare against the archived one
- [SEO Audit Tool](https://apify.com/hillcountrybots/seo-audit): audit the live pages
- [Domain Availability Checker](https://apify.com/hillcountrybots/domain-availability-checker): check if an old domain is free to register

Built by Hill Country Bots. Questions or a missing feature? Open an issue on the Actor page and we will answer.

# Actor input Schema

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

Required. One per line, e.g. example.com, https://example.com/pricing or example.com/blog/. A bare domain means its homepage in Snapshots and Closest modes, and the whole domain in Archived URLs mode. Private and local addresses are refused (free).

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

Snapshots lists captures of the exact URL. Timeline returns one summary row per URL: first and last seen, total captures, captures per year, status code counts and content versions. Archived URLs lists unique URLs (one row per URL, first capture). Closest returns one row per input.

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

Only used in Archived URLs mode. Big domains can have millions of URLs: use a path prefix, a date range and Max rows per URL to keep runs short.

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

Optional. Earliest capture date: 2015, 2015-06 or 2015-06-30 (UTC).

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

Optional. Latest capture date: 2020, 2020-12 or 2020-12-31 (UTC).

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

Snapshots mode: keep only the first capture per hour, day, month or year, or only captures whose content changed. Great for 'how did this page change over time'.

## `onlyStatus200` (type: `boolean`):

Drop captures of redirects, errors and missing pages.

## `skipQueryStrings` (type: `boolean`):

Archived URLs mode: drop URLs with ?parameters (tracking tags, session IDs, search pages), which are usually noise. Turn off to keep them.

## `mimeType` (type: `string`):

Optional. Keep only one content type, e.g. text/html or application/pdf. Leave empty for all.

## `closestTo` (type: `string`):

Closest mode only: target date such as 2012-01-01. Empty = the most recent capture.

## `maxRowsPerUrl` (type: `integer`):

Exact maximum rows returned for each input URL or domain.

## `maxCapturesScanned` (type: `integer`):

Timeline mode only. Captures read per URL to build the counts (first and last seen are always exact). Very popular pages can have 100,000+ captures; above this cap the row says countsComplete: false.

## `maxRows` (type: `integer`):

Exact maximum rows charged in this run, across all inputs. The run's own max-charge setting is also respected.

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

Seconds to wait for one archive API answer. Each request is retried up to 3 times with backoff when the archive is busy.

## Actor input object example

```json
{
  "urls": [
    "sitemaps.org"
  ],
  "mode": "snapshots",
  "matchType": "domain",
  "collapse": "none",
  "onlyStatus200": false,
  "skipQueryStrings": true,
  "maxRowsPerUrl": 50,
  "maxCapturesScanned": 50000,
  "maxRows": 10000,
  "requestTimeoutSecs": 90
}
```

# Actor output Schema

## `snapshots` (type: `string`):

Dataset with one row per snapshot (or per archived URL), with capture date, status code, MIME type and snapshot links.

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

JSON counts for the run (rows charged, inputs with no captures, failures, rows per input). Key: RUN_SUMMARY.

## `timeline` (type: `string`):

Timeline mode rows: first and last seen, captures per year, status codes.

# 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": [
        "sitemaps.org"
    ],
    "maxRowsPerUrl": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("hillcountrybots/wayback-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": ["sitemaps.org"],
    "maxRowsPerUrl": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("hillcountrybots/wayback-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": [
    "sitemaps.org"
  ],
  "maxRowsPerUrl": 50
}' |
apify call hillcountrybots/wayback-history --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,hillcountrybots/wayback-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/fFTYHKGAkisrbh9Te/builds/rOywF8P07d8HbSBKJ/openapi.json
