# Wayback Machine API – Snapshots, Archived URLs & Page Changes (`ostrata/wayback-machine-api`) Actor

Internet Archive Wayback Machine API: list snapshots of any URL, find all archived URLs of a domain, first-seen / domain age, archived page text and what changed between two dates. Official CDX & availability APIs, no proxies, pay per result.

- **URL**: https://apify.com/ostrata/wayback-machine-api.md
- **Developed by:** [Ostrata](https://apify.com/ostrata) (community)
- **Categories:** SEO tools, Developer tools, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.60 / 1,000 records

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 API – Snapshots, Archived URLs & Page Changes

**Everything the Internet Archive knows about a URL, as clean rows.** List every snapshot of a page, find all archived URLs of a domain, get the first-seen date (archive age) of a site, download the archived text of old versions, or compare two dates and see exactly which lines changed.

**Also known as:** Wayback Machine scraper, Wayback Machine API, archive.org CDX API, Internet Archive snapshots, website history checker, domain age / first seen, archived URLs extractor, old website versions, historical page changes.

- **Official public APIs only:** the Wayback [CDX server API](https://github.com/internetarchive/wayback/tree/master/wayback-cdx-server) and the [Availability API](https://archive.org/help/wayback_api.php). No scraping of web pages, no login, no proxies.
- **Polite by design:** one request at a time to web.archive.org, ~1 request per second, automatic back-off on HTTP 429/5xx. Big jobs are slower, but they do not get blocked.
- **Five modes in one Actor**, one consistent schema.
- **Pay only for results.** URLs that were never archived, failed downloads and errors are free.

### Modes

| Mode | What you get | Charged |
|---|---|---|
| `snapshots` | One row per capture: timestamp, status, MIME type, digest, size, Wayback link, raw-content link. Filter by date range, status, MIME type; deduplicate by content change or one per hour/day/month/year. | 1 Record per row |
| `urls` | Every distinct URL archived for a host, domain (with subdomains) or path prefix, with the date it was first captured. Great for finding old pages, lost content, redirects to set up after a migration, SEO link recovery. | 1 Record per URL |
| `summary` | First capture, last capture, archive age in days/years, list of years with captures. Use it for domain-age checks, due diligence, fraud signals. | 1 Record per input URL |
| `content` | Archived page text (title, meta description, H1, readable text, word and link counts) for up to N snapshots per URL. | 1 Page per archived page downloaded |
| `compare` | Closest captures to two dates, then lines added / removed, similarity %, title change. Pricing pages, terms of service, competitor messaging over time. | 1 Page per archived page downloaded (2 per comparison, 1 if both dates hit the same capture) |

### Input example

```json
{
  "urls": ["apify.com/pricing", "https://www.example.com/terms"],
  "mode": "compare",
  "compareFrom": "2022-01",
  "compareTo": "",
  "ignorePatterns": ["©\\s*\\d{4}"]
}
```

Snapshots of a page, one per month in 2023, successful captures only:

```json
{ "urls": ["apify.com/pricing"], "mode": "snapshots", "from": "2023", "to": "2023-12", "collapse": "month", "statusCodes": ["200"], "maxRecordsPerUrl": 24 }
```

All archived URLs of a domain:

```json
{ "urls": ["example.com"], "mode": "urls", "matchType": "domain", "statusCodes": ["200"], "maxRecordsPerUrl": 5000 }
```

### Output

Snapshot row:

```json
{
  "type": "snapshot", "input": "apify.com/pricing", "url": "https://apify.com/pricing",
  "timestamp": "20230115083012", "capturedAt": "2023-01-15T08:30:12Z",
  "statusCode": 200, "mimeType": "text/html", "digest": "Q3J…", "lengthBytes": 31234,
  "archiveUrl": "https://web.archive.org/web/20230115083012/https://apify.com/pricing",
  "rawContentUrl": "https://web.archive.org/web/20230115083012id_/https://apify.com/pricing"
}
```

Comparison row: `from` / `to` (timestamp, Wayback link, title, word count), `changed`, `similarityPercent`, `titleChanged`, `addedLinesCount`, `removedLinesCount`, `addedLines`, `removedLines`.

A run summary (status per input: `ok`, `no_captures`, `archive_fetch_failed`, `invalid_url`, `error`) is saved as `SUMMARY` in the key-value store.

### Pricing

Pay per event, no subscription:

- **Record** (snapshot row, archived URL or summary): **$0.0006** → $0.60 per 1,000.
- **Page** (archived page downloaded and converted to text, in Content and Compare modes): **$0.002**.
- Actor start: $0.00005.

Nothing is charged for URLs with no captures, archive download failures or errors. The run stops cleanly at your maximum charge per run: you are never billed past it.

### Honest limits

- **The Internet Archive is slow and rate-limited.** Expect ~1 request per second; a 5,000-row CDX page is one request, but each archived page download is one request too. Content and Compare jobs on hundreds of URLs take minutes.
- **Coverage depends on the Archive.** Small or new sites may have few or no captures; pages blocked by robots.txt or excluded by owners are not available.
- **Text extraction is plain HTML parsing.** Pages that build their content with JavaScript can come back nearly empty in Content/Compare mode (the archived HTML is what the crawler saw).
- **The diff is line-based** (lines that appear or disappear), not a word-level edit script. Use `ignorePatterns` to drop dates, counters and copyright years.
- `urls` mode returns the first capture of each distinct URL as the Archive canonicalizes it (query-string and `www.` variants may merge).
- Not affiliated with the Internet Archive. Please respect its [terms of use](https://archive.org/about/terms.php); consider [donating](https://archive.org/donate) if this is useful to you.

### Use cases

- **SEO & migrations:** recover old URLs to redirect, find lost content and backlinked pages.
- **Due diligence / KYB / fraud:** how old is this website really? Since when does this shop exist?
- **Competitive intelligence:** how a competitor's pricing page, plans or claims changed over time.
- **Legal & compliance:** what the terms or privacy policy said on a given date (with a Wayback link as reference).
- **AI agents & research:** feed historical page text to LLMs; MCP-ready through Apify.

### Related Actors

- [Website Change Monitor](https://apify.com/ostrata/website-change-monitor): watch pages going forward and get what changed since the last run.
- [Accessibility Checker (WCAG, axe-core)](https://apify.com/ostrata/accessibility-checker): audit pages for WCAG 2.1 / 2.2 issues in real Chrome.
- [EU Company Verification (KYB)](https://apify.com/ostrata/eu-company-check): verify companies from a name, SIREN/SIRET, VAT number or LEI (register status, VIES VAT, insolvency, LEI).
- [Website to Company (Impressum & Mentions Légales)](https://apify.com/ostrata/website-company-check): find the legal entity behind a website and verify it in official registries.
- [France Company List (SIRENE)](https://apify.com/ostrata/france-company-list): build lists of French companies by NAF code, area, headcount and revenue.
- [All-ATS Jobs API](https://apify.com/ostrata/ats-jobs-api): normalized jobs from Greenhouse, Lever, Ashby, Workable, SmartRecruiters and Recruitee.
- [AI Brand Visibility Tracker](https://apify.com/ostrata/ai-search-visibility): check whether ChatGPT, Perplexity and Gemini mention and cite your brand.

# Actor input Schema

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

One per line: a domain (apify.com), a page URL (https://www.example.com/pricing) or a web.archive.org link.

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

Snapshots and URLs are charged per record, Summary is one record per URL, Content and Compare are charged per archived page downloaded.

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

In 'All archived URLs' mode, Exact is treated as Host.

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

Optional. 2015, 2015-06 or 2015-06-30.

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

Optional. 2020, 2020-12 or 2020-12-31.

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

Applies to Snapshots and Content modes.

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

Keep captures with these archived status codes. Empty = all (including redirects and errors).

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

Optional, e.g. text/html, application/pdf.

## `maxRecordsPerUrl` (type: `integer`):

Snapshots / URLs modes.

## `maxPagesPerUrl` (type: `integer`):

Content mode: how many snapshots to download per URL (oldest first within the date range).

## `maxTextChars` (type: `integer`):

Content mode. 0 = no text, metadata only.

## `compareFrom` (type: `string`):

Compare mode: the capture closest to this date is the 'before' version. 2023 or 2023-01-15.

## `compareTo` (type: `string`):

Compare mode: the capture closest to this date is the 'after' version. Empty = latest capture.

## `ignorePatterns` (type: `array`):

Text removed before comparing, e.g. \d{1,2}:\d{2} for clocks or ©\s\*\d{4}.

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

Max added and removed lines returned per comparison (counts are always complete).

## Actor input object example

```json
{
  "urls": [
    "apify.com/pricing"
  ],
  "mode": "snapshots",
  "matchType": "exact",
  "collapse": "month",
  "statusCodes": [
    "200"
  ],
  "maxRecordsPerUrl": 24,
  "maxPagesPerUrl": 3,
  "maxTextChars": 20000,
  "maxDiffLines": 200
}
```

# Actor output Schema

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

Dataset items.

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

Per URL: status (ok / no_captures / archive_fetch_failed / invalid_url / error) and counts.

# 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/pricing"
    ],
    "mode": "snapshots",
    "collapse": "month",
    "maxRecordsPerUrl": 24
};

// Run the Actor and wait for it to finish
const run = await client.actor("ostrata/wayback-machine-api").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/pricing"],
    "mode": "snapshots",
    "collapse": "month",
    "maxRecordsPerUrl": 24,
}

# Run the Actor and wait for it to finish
run = client.actor("ostrata/wayback-machine-api").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/pricing"
  ],
  "mode": "snapshots",
  "collapse": "month",
  "maxRecordsPerUrl": 24
}' |
apify call ostrata/wayback-machine-api --silent --output-dataset

```

## MCP server setup

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

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/ymHjK2lGKEtUthFUI/builds/LSVFmfPV3E838WEKP/openapi.json
