{
  "data": {
    "id": "IADcjvMrlQA9u17xO",
    "actId": "mXENdRBun6FUTc2pI",
    "userId": "zq8lKbpLzTjGDayPC",
    "startedAt": "2026-11-09T06:43:12.896Z",
    "finishedAt": "2026-11-09T06:43:17.418Z",
    "status": "SUCCEEDED",
    "meta": {
      "origin": "CLI"
    },
    "stats": {
      "durationMillis": 4375,
      "runTimeSecs": 4.375,
      "computeUnits": 0.004861111111111111,
      "imageSizeBytes": 371466240
    },
    "options": {
      "useCache": true,
      "betaPackages": false,
      "memoryMbytes": 4096,
      "diskMbytes": 8192
    },
    "createdByOrganizationMemberUserId": "GK9YjZRyQZVzOdoH5",
    "exitCode": 0,
    "inputSchema": "{\n  \"title\": \"Wayback Machine Snapshot History & Archived Text Input\",\n  \"description\": \"Collect Wayback Machine capture history, closest snapshots, or archived page text for one URL or a bulk list.\",\n  \"type\": \"object\",\n  \"schemaVersion\": 1,\n  \"properties\": {\n    \"mode\": {\n      \"title\": \"Mode\",\n      \"type\": \"string\",\n      \"description\": \"What to collect. 'search' returns every matching capture; 'timeline' returns one row per distinct content version; 'summary' returns archive coverage per target; 'closest' returns the nearest capture to a date; 'content' returns readable text from the archived page.\",\n      \"editor\": \"select\",\n      \"enum\": [\n        \"search\",\n        \"timeline\",\n        \"summary\",\n        \"closest\",\n        \"content\"\n      ],\n      \"enumTitles\": [\n        \"Search capture history\",\n        \"Version timeline\",\n        \"Archive coverage summary\",\n        \"Closest snapshot to a date\",\n        \"Archived page text\"\n      ],\n      \"default\": \"search\",\n      \"prefill\": \"closest\",\n      \"sectionCaption\": \"What to collect\",\n      \"sectionDescription\": \"Pick the result shape first, then set the target and filters below.\"\n    },\n    \"url\": {\n      \"title\": \"URL or domain (single target)\",\n      \"type\": \"string\",\n      \"description\": \"One URL, host, domain, or Wayback playback URL. Examples: 'apify.com', 'https://example.com/blog', 'https://web.archive.org/web/20240101000000/https://apify.com/'. Wildcards like 'example.com/*' and '*.example.com' are detected automatically.\",\n      \"editor\": \"textfield\",\n      \"prefill\": \"apify.com\",\n      \"sectionCaption\": \"Targets\",\n      \"sectionDescription\": \"Use the single field or the bulk list; both are merged and deduplicated.\"\n    },\n    \"urls\": {\n      \"title\": \"URLs or domains (bulk)\",\n      \"type\": \"array\",\n      \"description\": \"One or more targets for batch collection. Each target is queried independently and the Max items budget is split across them.\",\n      \"editor\": \"stringList\",\n      \"default\": [],\n      \"prefill\": []\n    },\n    \"matchType\": {\n      \"title\": \"URL match type\",\n      \"type\": \"string\",\n      \"description\": \"How the target is matched against the archive. 'exact' = that URL only; 'prefix' = the URL and every path beneath it; 'host' = every path on the same host; 'domain' = the host and all subdomains.\",\n      \"editor\": \"select\",\n      \"enum\": [\n        \"exact\",\n        \"prefix\",\n        \"host\",\n        \"domain\"\n      ],\n      \"enumTitles\": [\n        \"Exact URL\",\n        \"URL prefix\",\n        \"Same host\",\n        \"Same domain (includes subdomains)\"\n      ],\n      \"default\": \"exact\",\n      \"prefill\": \"exact\"\n    },\n    \"dateFrom\": {\n      \"title\": \"From date\",\n      \"type\": \"string\",\n      \"description\": \"Earliest capture date, inclusive. Accepts YYYY, YYYY-MM, YYYY-MM-DD, or a full timestamp such as 2024-01-31T12:00:00.\",\n      \"editor\": \"textfield\",\n      \"sectionCaption\": \"Capture filters\",\n      \"sectionDescription\": \"These filters are applied by the Wayback CDX API before records are returned.\"\n    },\n    \"dateTo\": {\n      \"title\": \"To date\",\n      \"type\": \"string\",\n      \"description\": \"Latest capture date, inclusive. Uses the same formats as From date. A date without a time includes the whole day.\",\n      \"editor\": \"textfield\"\n    },\n    \"statusCodes\": {\n      \"title\": \"Keep HTTP status codes\",\n      \"type\": \"array\",\n      \"description\": \"Only keep captures with these HTTP status codes, e.g. ['200','301']. Leave empty for all statuses. Values may also be comma-separated.\",\n      \"editor\": \"stringList\",\n      \"default\": [],\n      \"prefill\": []\n    },\n    \"excludeStatusCodes\": {\n      \"title\": \"Exclude HTTP status codes\",\n      \"type\": \"array\",\n      \"description\": \"Drop captures with these HTTP status codes, e.g. ['404','500']. Leave empty to exclude nothing.\",\n      \"editor\": \"stringList\",\n      \"default\": [],\n      \"prefill\": []\n    },\n    \"mimeTypes\": {\n      \"title\": \"Keep MIME types\",\n      \"type\": \"array\",\n      \"description\": \"Only keep captures with these MIME types, e.g. ['text/html','application/pdf']. Leave empty for all MIME types.\",\n      \"editor\": \"stringList\",\n      \"default\": [],\n      \"prefill\": []\n    },\n    \"excludeMimeTypes\": {\n      \"title\": \"Exclude MIME types\",\n      \"type\": \"array\",\n      \"description\": \"Drop captures with these MIME types, e.g. ['image/png','video/mp4']. Leave empty to exclude nothing.\",\n      \"editor\": \"stringList\",\n      \"default\": [],\n      \"prefill\": []\n    },\n    \"collapseBy\": {\n      \"title\": \"Collapse duplicates\",\n      \"type\": \"string\",\n      \"description\": \"Deduplicate adjacent captures in 'search' mode. 'digest' keeps one record per distinct content fingerprint; 'urlkey' keeps one capture per URL; 'monthly', 'daily', and 'hourly' keep one capture per time bucket; 'none' returns every raw capture. 'timeline' and 'summary' always read raw captures so their counts and durations stay accurate.\",\n      \"editor\": \"select\",\n      \"enum\": [\n        \"none\",\n        \"digest\",\n        \"urlkey\",\n        \"monthly\",\n        \"daily\",\n        \"hourly\"\n      ],\n      \"enumTitles\": [\n        \"None (every capture)\",\n        \"Content digest (distinct versions)\",\n        \"One per URL\",\n        \"One per month\",\n        \"One per day\",\n        \"One per hour\"\n      ],\n      \"default\": \"digest\",\n      \"prefill\": \"none\"\n    },\n    \"sortDirection\": {\n      \"title\": \"Which end of the archive\",\n      \"type\": \"string\",\n      \"description\": \"Choose whether the limited result set comes from the oldest or newest captures. Search rows are emitted in chronological order; 'latest' reverses the final rows so the newest appears first.\",\n      \"editor\": \"select\",\n      \"enum\": [\n        \"earliest\",\n        \"latest\"\n      ],\n      \"enumTitles\": [\n        \"Oldest captures first\",\n        \"Newest captures first\"\n      ],\n      \"default\": \"earliest\",\n      \"prefill\": \"earliest\"\n    },\n    \"targetDate\": {\n      \"title\": \"Target date\",\n      \"type\": \"string\",\n      \"description\": \"Date used by 'closest' and 'content' modes, and as the reference when a playback URL does not include a timestamp. Accepts YYYY, YYYY-MM, YYYY-MM-DD, or a full timestamp. Defaults to now when empty.\",\n      \"editor\": \"textfield\",\n      \"prefill\": \"2024-01-01\",\n      \"sectionCaption\": \"Closest snapshot and archived text\",\n      \"sectionDescription\": \"These settings control date matching and text extraction.\"\n    },\n    \"enrichWithContent\": {\n      \"title\": \"Add archived text to search rows\",\n      \"type\": \"boolean\",\n      \"description\": \"In 'search' mode, fetch the archived HTML for the first Max content fetches rows and add its readable text and metadata. Off by default because it costs extra requests.\",\n      \"default\": false,\n      \"prefill\": false\n    },\n    \"maxContentFetch\": {\n      \"title\": \"Max text fetches for search rows\",\n      \"type\": \"integer\",\n      \"description\": \"Cap on archived pages downloaded when 'Add archived text to search rows' is on. 0 disables enrichment. This setting is ignored by 'content' mode, which uses Max items instead.\",\n      \"default\": 10,\n      \"prefill\": 0,\n      \"minimum\": 0,\n      \"maximum\": 500\n    },\n    \"maxContentChars\": {\n      \"title\": \"Max characters per archived page\",\n      \"type\": \"integer\",\n      \"description\": \"Truncate extracted text at this many characters. The full word count and text hash are still recorded, and contentTruncated is set when clipping happens.\",\n      \"default\": 500000,\n      \"prefill\": 500000,\n      \"minimum\": 1000,\n      \"maximum\": 2000000\n    },\n    \"includeHeadings\": {\n      \"title\": \"Include headings\",\n      \"type\": \"boolean\",\n      \"description\": \"Add the page's H1-H6 headings as structured records when archived text is extracted.\",\n      \"default\": true,\n      \"prefill\": false\n    },\n    \"maxItems\": {\n      \"title\": \"Max items\",\n      \"type\": \"integer\",\n      \"description\": \"Hard cap on emitted records. For bulk search the budget is split evenly across targets. In 'summary' mode it is also the per-target capture scan budget, split between the oldest and newest ends. Up to 100,000 captures are supported through automatic resume-key pagination.\",\n      \"default\": 500,\n      \"prefill\": 1,\n      \"minimum\": 1,\n      \"maximum\": 100000,\n      \"sectionCaption\": \"Output\",\n      \"sectionDescription\": \"Control row volume and change annotations.\"\n    },\n    \"detectChanges\": {\n      \"title\": \"Annotate content changes\",\n      \"type\": \"boolean\",\n      \"description\": \"In 'search' mode, compare each capture with the previous capture of the same URL and add changed, changeType, previousTimestamp, and related fields.\",\n      \"default\": true,\n      \"prefill\": false\n    }\n  }\n}",
    "readme": "# Wayback Machine Snapshot History & Archived Text Extractor\n\nTurn the Internet Archive's public Wayback Machine into a structured dataset. Give this actor one URL, a host, an entire domain, or a bulk list, then choose a capture history, a version timeline, an archive-coverage summary, the closest snapshot to a date, or the readable text of the archived page itself.\n\nNo account, API key, cookie, or proxy setup is needed. The actor talks to the same public CDX and availability endpoints that power the Wayback Machine website.\n\n## Modes\n\n| Mode | What you get | Typical use |\n|---|---|---|\n| `search` | One row per archived capture with timestamp, playback URL, HTTP status, MIME type, digest, and size | Full capture history, broken-link recovery, redirect mapping |\n| `timeline` | One row per distinct content version, with first/last seen dates, capture count, and duration | See how a page changed without reading every duplicate capture |\n| `summary` | One archive-coverage row per target: scanned capture count, version count, first/last capture, days covered, status and year breakdowns | Vet expired domains, measure archive density, compare sites |\n| `closest` | The capture nearest to a target date, with its playback URL and distance in days | Legal, compliance, and journalism checks: \"what did the page say on this date?\" |\n| `content` | Readable text plus title, description, language, canonical URL, headings, word count, character count, and text hash from archived HTML | Recover deleted copy, search archived text, build text corpora |\n\n## Bulk targets and pagination\n\n- Put one target in `url` or many in `urls`; both are merged and deduplicated.\n- The `maxItems` budget is split evenly across targets so every target gets a fair share.\n- Capture history uses automatic resume-key pagination, so a single run can retrieve up to 100,000 captures instead of stopping at the first CDX page.\n- `sortDirection` chooses whether the limited result set comes from the oldest or newest end of the archive. Search rows are chronological; `latest` reverses the final rows so the newest capture appears first.\n- `collapseBy` applies to `search` mode: keep every raw capture, one per distinct content digest, one per URL, or one per month/day/hour. `timeline` and `summary` always read raw captures so version durations and coverage counts are not flattened.\n- `summary` scans up to `maxItems` captures per target, split between the oldest and newest ends, so the first and last capture stay accurate even on dense domains. `captureCount`, `versionCount`, and the breakdowns describe that scanned window; raise `maxItems` for a fuller census.\n\n## Output fields\n\n### Capture rows (`search`)\n\n`originalUrl`, `urlKey`, `timestamp`, `archiveDate`, `archiveUrl`, `rawArchiveUrl`, `sourceUrl`, `statusCode`, `statusText`, `statusClass`, `mimeType`, `contentDigest`, `contentLength`, `host`, `urlPath`, `fileExtension`, `captureYear`, `matchType`, `isRevisit`, `recordType`, `resultIndex`, `scrapedAt`.\n\nWith `detectChanges` on, each row also gets `captureIndex`, `changed`, `changeType` (`initial`, `content`, `status`, `contentAndStatus`, `unchanged`), `isInitialCapture`, `previousTimestamp`, `previousStatusCode`, `previousContentDigest`, and `daysSincePrevious`.\n\nWith `enrichWithContent` on, rows also get the archived-text fields below, up to `maxContentFetch` rows.\n\n### Version rows (`timeline`)\n\n`originalUrl`, `firstTimestamp`, `lastTimestamp`, `firstArchiveDate`, `lastArchiveDate`, `captureCount`, `durationDays`, `archiveUrl`, `rawArchiveUrl`, `contentDigest`, `mimeType`, `statusCode`, `statusText`, `contentLength`, `sourceUrl`, `recordType`, `resultIndex`, `scrapedAt`.\n\n### Summary rows (`summary`)\n\n`originalUrl`, `matchType`, `archived`, `captureCount`, `versionCount`, `firstTimestamp`, `lastTimestamp`, `firstArchiveDate`, `lastArchiveDate`, `firstArchiveUrl`, `lastArchiveUrl`, `spanDays`, `statusBreakdown`, `mimeTypeBreakdown`, `activeYears`, `yearBreakdown`, `sourceUrl`, `recordType`, `resultIndex`, `scrapedAt`.\n\n### Closest-snapshot rows (`closest`)\n\n`originalUrl`, `available`, `requestedTimestamp`, `requestedDate`, `timestamp`, `archiveDate`, `archiveUrl`, `rawArchiveUrl`, `statusCode`, `statusClass`, `statusText`, `captureDistanceDays`, `sourceUrl`, `recordType`, `resultIndex`, `scrapedAt`.\n\n### Archived-page rows (`content`)\n\n`originalUrl`, `timestamp`, `archiveDate`, `archiveUrl`, `rawArchiveUrl`, `statusCode`, `mimeType`, `contentDigest`, `contentLength`, `title`, `description`, `language`, `canonicalUrl`, `metaKeywords`, `headings`, `text`, `wordCount`, `characterCount`, `textHash`, `contentTruncated`, `fetchContentLength`, `fetchContentTruncated`, `contentMimeType`, `sourceUrl`, `recordType`, `resultIndex`, `scrapedAt`.\n\nEmpty values are omitted at every depth, so a field appears only when the archive actually supplied it.\n\n## Input\n\n| Field | Type | Default | Description |\n|---|---|---|---|\n| `mode` | string | `search` | `search`, `timeline`, `summary`, `closest`, or `content` |\n| `url` | string | – | Single URL, host, domain, or playback URL |\n| `urls` | array | `[]` | Bulk targets; merged with `url` |\n| `matchType` | string | `exact` | `exact`, `prefix`, `host`, or `domain`; wildcards are auto-detected |\n| `dateFrom` | string | – | Earliest capture date, inclusive |\n| `dateTo` | string | – | Latest capture date, inclusive |\n| `statusCodes` | array | `[]` | Keep only these HTTP status codes |\n| `excludeStatusCodes` | array | `[]` | Drop these HTTP status codes |\n| `mimeTypes` | array | `[]` | Keep only these MIME types |\n| `excludeMimeTypes` | array | `[]` | Drop these MIME types |\n| `collapseBy` | string | `digest` | `none`, `digest`, `urlkey`, `monthly`, `daily`, or `hourly`; applies to `search` only |\n| `sortDirection` | string | `earliest` | `earliest` or `latest` |\n| `targetDate` | string | – | Reference date for `closest` and `content`; defaults to now |\n| `enrichWithContent` | boolean | `false` | Add archived text to search rows |\n| `maxContentFetch` | integer | `10` | Text-fetch cap for search enrichment (0–500) |\n| `maxContentChars` | integer | `500000` | Text cap per archived page (1,000–2,000,000) |\n| `includeHeadings` | boolean | `true` | Include H1–H6 headings in archived text |\n| `maxItems` | integer | `500` | Record cap (1–100,000) |\n| `detectChanges` | boolean | `true` | Annotate content/status changes in search rows |\n\nThe daily-test prefill is the cheapest possible run: `mode=closest`, `url=apify.com`, `targetDate=2024-01-01`, `maxItems=1`. It performs one availability lookup and returns one snapshot record.\n\n### Example: full capture history with changes\n\n```json\n{\n    \"mode\": \"search\",\n    \"url\": \"https://example.com/\",\n    \"matchType\": \"exact\",\n    \"dateFrom\": \"2020-01-01\",\n    \"dateTo\": \"2024-12-31\",\n    \"statusCodes\": [\"200\"],\n    \"collapseBy\": \"none\",\n    \"detectChanges\": true,\n    \"maxItems\": 500\n}\n```\n\n### Example: bulk closest snapshots\n\n```json\n{\n    \"mode\": \"closest\",\n    \"urls\": [\"apify.com\", \"example.com\", \"wikipedia.org\"],\n    \"targetDate\": \"2020-06-15\",\n    \"maxItems\": 3\n}\n```\n\n### Example: archived text from a playback URL\n\n```json\n{\n    \"mode\": \"content\",\n    \"url\": \"https://web.archive.org/web/20240101000000/https://apify.com/\",\n    \"maxItems\": 1,\n    \"includeHeadings\": true\n}\n```\n\n## Legacy inputs\n\nSaved tasks and integrations from earlier versions keep working. The actor still accepts `url` as a single target. Old field names `maxResults`, `includeContent`, `statusFilter`, and `mimeFilter` are mapped onto `maxItems`, `enrichWithContent`, `statusCodes`, and `mimeTypes` in code. Collapse aliases `timestamp:6`, `timestamp:8`, and `timestamp:10` are accepted alongside `monthly`, `daily`, and `hourly`.\n\n## Use cases\n\n- **Content recovery** — pull the text of pages that no longer exist\n- **SEO link-rot audits** — list archived 404s, redirects, and deleted pages on a domain\n- **Competitive history** — compare pricing, messaging, or product pages month by month\n- **Legal and journalism evidence** — pin the closest capture to a specific date\n- **Domain due diligence** — measure archive age, density, gaps, and version count before buying an expired domain\n- **Dataset building** — export archived text and metadata for search, NLP, or research\n\n## FAQ\n\n**Where does the data come from?**\nThe Internet Archive's public Wayback CDX search API, its availability API, and archived playback pages. No browser UI is scraped.\n\n**Do I need an Internet Archive account or API key?**\nNo. Every request is anonymous and cookieless.\n\n**Can I search the archive by keyword?**\nThe CDX API indexes URLs and capture metadata, not full text. Use `mode=content` to download page text and filter it in your own pipeline.\n\n**Why are some captures marked `warc/revisit`?**\nThe archive sometimes records a revisit instead of a full copy. Those rows keep the digest and size but may not have an HTTP status code.\n\n**Why is `content` missing from a row?**\nThe row was beyond the text-fetch budget, the archived resource was not HTML/text, or replay returned an error. `contentTruncated` is set when text was clipped at `maxContentChars`.\n\n**Why does `closest` mode omit MIME type and digest?**\nThe availability endpoint returns the nearest capture URL, timestamp, and status only. Use `search` mode with a narrow date range when you need full CDX metadata.\n\n**Can I retrieve more than 10,000 captures?**\nYes. The actor pages through the CDX index with resume keys, so `maxItems` can go up to 100,000. Very broad host/domain queries and `collapseBy=urlkey` can be slower on the archive side.\n\n**Is archive coverage complete?**\nNo. The Wayback Machine only stores what its crawlers captured. Popular pages usually have dense history; obscure pages may have none, and a summary row with `captureCount=0` is still a valid result.\n\n**Is this affiliated with the Internet Archive?**\nNo. It is an independent tool that reads the Internet Archive's public Wayback Machine endpoints.\n",
    "actorDefinition": {
      "actorSpecification": 1,
      "name": "wayback-machine-snapshot-history-and-archived-text",
      "title": "Wayback Machine Snapshot History & Archived Text Extractor",
      "description": "Collect Wayback capture history, version timelines, closest snapshots, and readable archived page text for any URL, host, or domain. Filters, bulk targets, and automatic pagination included.",
      "version": "2.0",
      "buildTag": "latest",
      "input": {
        "title": "Wayback Machine Snapshot History & Archived Text Input",
        "description": "Collect Wayback Machine capture history, closest snapshots, or archived page text for one URL or a bulk list.",
        "type": "object",
        "schemaVersion": 1,
        "properties": {
          "mode": {
            "title": "Mode",
            "type": "string",
            "description": "What to collect. 'search' returns every matching capture; 'timeline' returns one row per distinct content version; 'summary' returns archive coverage per target; 'closest' returns the nearest capture to a date; 'content' returns readable text from the archived page.",
            "editor": "select",
            "enum": [
              "search",
              "timeline",
              "summary",
              "closest",
              "content"
            ],
            "enumTitles": [
              "Search capture history",
              "Version timeline",
              "Archive coverage summary",
              "Closest snapshot to a date",
              "Archived page text"
            ],
            "default": "search",
            "prefill": "closest",
            "sectionCaption": "What to collect",
            "sectionDescription": "Pick the result shape first, then set the target and filters below."
          },
          "url": {
            "title": "URL or domain (single target)",
            "type": "string",
            "description": "One URL, host, domain, or Wayback playback URL. Examples: 'apify.com', 'https://example.com/blog', 'https://web.archive.org/web/20240101000000/https://apify.com/'. Wildcards like 'example.com/*' and '*.example.com' are detected automatically.",
            "editor": "textfield",
            "prefill": "apify.com",
            "sectionCaption": "Targets",
            "sectionDescription": "Use the single field or the bulk list; both are merged and deduplicated."
          },
          "urls": {
            "title": "URLs or domains (bulk)",
            "type": "array",
            "description": "One or more targets for batch collection. Each target is queried independently and the Max items budget is split across them.",
            "editor": "stringList",
            "default": [],
            "prefill": []
          },
          "matchType": {
            "title": "URL match type",
            "type": "string",
            "description": "How the target is matched against the archive. 'exact' = that URL only; 'prefix' = the URL and every path beneath it; 'host' = every path on the same host; 'domain' = the host and all subdomains.",
            "editor": "select",
            "enum": [
              "exact",
              "prefix",
              "host",
              "domain"
            ],
            "enumTitles": [
              "Exact URL",
              "URL prefix",
              "Same host",
              "Same domain (includes subdomains)"
            ],
            "default": "exact",
            "prefill": "exact"
          },
          "dateFrom": {
            "title": "From date",
            "type": "string",
            "description": "Earliest capture date, inclusive. Accepts YYYY, YYYY-MM, YYYY-MM-DD, or a full timestamp such as 2024-01-31T12:00:00.",
            "editor": "textfield",
            "sectionCaption": "Capture filters",
            "sectionDescription": "These filters are applied by the Wayback CDX API before records are returned."
          },
          "dateTo": {
            "title": "To date",
            "type": "string",
            "description": "Latest capture date, inclusive. Uses the same formats as From date. A date without a time includes the whole day.",
            "editor": "textfield"
          },
          "statusCodes": {
            "title": "Keep HTTP status codes",
            "type": "array",
            "description": "Only keep captures with these HTTP status codes, e.g. ['200','301']. Leave empty for all statuses. Values may also be comma-separated.",
            "editor": "stringList",
            "default": [],
            "prefill": []
          },
          "excludeStatusCodes": {
            "title": "Exclude HTTP status codes",
            "type": "array",
            "description": "Drop captures with these HTTP status codes, e.g. ['404','500']. Leave empty to exclude nothing.",
            "editor": "stringList",
            "default": [],
            "prefill": []
          },
          "mimeTypes": {
            "title": "Keep MIME types",
            "type": "array",
            "description": "Only keep captures with these MIME types, e.g. ['text/html','application/pdf']. Leave empty for all MIME types.",
            "editor": "stringList",
            "default": [],
            "prefill": []
          },
          "excludeMimeTypes": {
            "title": "Exclude MIME types",
            "type": "array",
            "description": "Drop captures with these MIME types, e.g. ['image/png','video/mp4']. Leave empty to exclude nothing.",
            "editor": "stringList",
            "default": [],
            "prefill": []
          },
          "collapseBy": {
            "title": "Collapse duplicates",
            "type": "string",
            "description": "Deduplicate adjacent captures in 'search' mode. 'digest' keeps one record per distinct content fingerprint; 'urlkey' keeps one capture per URL; 'monthly', 'daily', and 'hourly' keep one capture per time bucket; 'none' returns every raw capture. 'timeline' and 'summary' always read raw captures so their counts and durations stay accurate.",
            "editor": "select",
            "enum": [
              "none",
              "digest",
              "urlkey",
              "monthly",
              "daily",
              "hourly"
            ],
            "enumTitles": [
              "None (every capture)",
              "Content digest (distinct versions)",
              "One per URL",
              "One per month",
              "One per day",
              "One per hour"
            ],
            "default": "digest",
            "prefill": "none"
          },
          "sortDirection": {
            "title": "Which end of the archive",
            "type": "string",
            "description": "Choose whether the limited result set comes from the oldest or newest captures. Search rows are emitted in chronological order; 'latest' reverses the final rows so the newest appears first.",
            "editor": "select",
            "enum": [
              "earliest",
              "latest"
            ],
            "enumTitles": [
              "Oldest captures first",
              "Newest captures first"
            ],
            "default": "earliest",
            "prefill": "earliest"
          },
          "targetDate": {
            "title": "Target date",
            "type": "string",
            "description": "Date used by 'closest' and 'content' modes, and as the reference when a playback URL does not include a timestamp. Accepts YYYY, YYYY-MM, YYYY-MM-DD, or a full timestamp. Defaults to now when empty.",
            "editor": "textfield",
            "prefill": "2024-01-01",
            "sectionCaption": "Closest snapshot and archived text",
            "sectionDescription": "These settings control date matching and text extraction."
          },
          "enrichWithContent": {
            "title": "Add archived text to search rows",
            "type": "boolean",
            "description": "In 'search' mode, fetch the archived HTML for the first Max content fetches rows and add its readable text and metadata. Off by default because it costs extra requests.",
            "default": false,
            "prefill": false
          },
          "maxContentFetch": {
            "title": "Max text fetches for search rows",
            "type": "integer",
            "description": "Cap on archived pages downloaded when 'Add archived text to search rows' is on. 0 disables enrichment. This setting is ignored by 'content' mode, which uses Max items instead.",
            "default": 10,
            "prefill": 0,
            "minimum": 0,
            "maximum": 500
          },
          "maxContentChars": {
            "title": "Max characters per archived page",
            "type": "integer",
            "description": "Truncate extracted text at this many characters. The full word count and text hash are still recorded, and contentTruncated is set when clipping happens.",
            "default": 500000,
            "prefill": 500000,
            "minimum": 1000,
            "maximum": 2000000
          },
          "includeHeadings": {
            "title": "Include headings",
            "type": "boolean",
            "description": "Add the page's H1-H6 headings as structured records when archived text is extracted.",
            "default": true,
            "prefill": false
          },
          "maxItems": {
            "title": "Max items",
            "type": "integer",
            "description": "Hard cap on emitted records. For bulk search the budget is split evenly across targets. In 'summary' mode it is also the per-target capture scan budget, split between the oldest and newest ends. Up to 100,000 captures are supported through automatic resume-key pagination.",
            "default": 500,
            "prefill": 1,
            "minimum": 1,
            "maximum": 100000,
            "sectionCaption": "Output",
            "sectionDescription": "Control row volume and change annotations."
          },
          "detectChanges": {
            "title": "Annotate content changes",
            "type": "boolean",
            "description": "In 'search' mode, compare each capture with the previous capture of the same URL and add changed, changeType, previousTimestamp, and related fields.",
            "default": true,
            "prefill": false
          }
        }
      },
      "output": {
        "actorOutputSchemaVersion": 1,
        "title": "Wayback Machine Snapshot History & Archived Text Output",
        "description": "Wayback capture history, closest snapshots, archive coverage summaries, version timelines, and readable archived page text.",
        "properties": {
          "records": {
            "type": "string",
            "title": "Wayback Machine records",
            "description": "Dataset containing snapshot, version, summary, closest-snapshot, archived-page, or diagnostic records for the selected mode.",
            "template": "{{links.apiDefaultDatasetUrl}}/items"
          }
        }
      },
      "dockerfile": "../Dockerfile",
      "readme": "# Wayback Machine Snapshot History & Archived Text Extractor\n\nTurn the Internet Archive's public Wayback Machine into a structured dataset. Give this actor one URL, a host, an entire domain, or a bulk list, then choose a capture history, a version timeline, an archive-coverage summary, the closest snapshot to a date, or the readable text of the archived page itself.\n\nNo account, API key, cookie, or proxy setup is needed. The actor talks to the same public CDX and availability endpoints that power the Wayback Machine website.\n\n## Modes\n\n| Mode | What you get | Typical use |\n|---|---|---|\n| `search` | One row per archived capture with timestamp, playback URL, HTTP status, MIME type, digest, and size | Full capture history, broken-link recovery, redirect mapping |\n| `timeline` | One row per distinct content version, with first/last seen dates, capture count, and duration | See how a page changed without reading every duplicate capture |\n| `summary` | One archive-coverage row per target: scanned capture count, version count, first/last capture, days covered, status and year breakdowns | Vet expired domains, measure archive density, compare sites |\n| `closest` | The capture nearest to a target date, with its playback URL and distance in days | Legal, compliance, and journalism checks: \"what did the page say on this date?\" |\n| `content` | Readable text plus title, description, language, canonical URL, headings, word count, character count, and text hash from archived HTML | Recover deleted copy, search archived text, build text corpora |\n\n## Bulk targets and pagination\n\n- Put one target in `url` or many in `urls`; both are merged and deduplicated.\n- The `maxItems` budget is split evenly across targets so every target gets a fair share.\n- Capture history uses automatic resume-key pagination, so a single run can retrieve up to 100,000 captures instead of stopping at the first CDX page.\n- `sortDirection` chooses whether the limited result set comes from the oldest or newest end of the archive. Search rows are chronological; `latest` reverses the final rows so the newest capture appears first.\n- `collapseBy` applies to `search` mode: keep every raw capture, one per distinct content digest, one per URL, or one per month/day/hour. `timeline` and `summary` always read raw captures so version durations and coverage counts are not flattened.\n- `summary` scans up to `maxItems` captures per target, split between the oldest and newest ends, so the first and last capture stay accurate even on dense domains. `captureCount`, `versionCount`, and the breakdowns describe that scanned window; raise `maxItems` for a fuller census.\n\n## Output fields\n\n### Capture rows (`search`)\n\n`originalUrl`, `urlKey`, `timestamp`, `archiveDate`, `archiveUrl`, `rawArchiveUrl`, `sourceUrl`, `statusCode`, `statusText`, `statusClass`, `mimeType`, `contentDigest`, `contentLength`, `host`, `urlPath`, `fileExtension`, `captureYear`, `matchType`, `isRevisit`, `recordType`, `resultIndex`, `scrapedAt`.\n\nWith `detectChanges` on, each row also gets `captureIndex`, `changed`, `changeType` (`initial`, `content`, `status`, `contentAndStatus`, `unchanged`), `isInitialCapture`, `previousTimestamp`, `previousStatusCode`, `previousContentDigest`, and `daysSincePrevious`.\n\nWith `enrichWithContent` on, rows also get the archived-text fields below, up to `maxContentFetch` rows.\n\n### Version rows (`timeline`)\n\n`originalUrl`, `firstTimestamp`, `lastTimestamp`, `firstArchiveDate`, `lastArchiveDate`, `captureCount`, `durationDays`, `archiveUrl`, `rawArchiveUrl`, `contentDigest`, `mimeType`, `statusCode`, `statusText`, `contentLength`, `sourceUrl`, `recordType`, `resultIndex`, `scrapedAt`.\n\n### Summary rows (`summary`)\n\n`originalUrl`, `matchType`, `archived`, `captureCount`, `versionCount`, `firstTimestamp`, `lastTimestamp`, `firstArchiveDate`, `lastArchiveDate`, `firstArchiveUrl`, `lastArchiveUrl`, `spanDays`, `statusBreakdown`, `mimeTypeBreakdown`, `activeYears`, `yearBreakdown`, `sourceUrl`, `recordType`, `resultIndex`, `scrapedAt`.\n\n### Closest-snapshot rows (`closest`)\n\n`originalUrl`, `available`, `requestedTimestamp`, `requestedDate`, `timestamp`, `archiveDate`, `archiveUrl`, `rawArchiveUrl`, `statusCode`, `statusClass`, `statusText`, `captureDistanceDays`, `sourceUrl`, `recordType`, `resultIndex`, `scrapedAt`.\n\n### Archived-page rows (`content`)\n\n`originalUrl`, `timestamp`, `archiveDate`, `archiveUrl`, `rawArchiveUrl`, `statusCode`, `mimeType`, `contentDigest`, `contentLength`, `title`, `description`, `language`, `canonicalUrl`, `metaKeywords`, `headings`, `text`, `wordCount`, `characterCount`, `textHash`, `contentTruncated`, `fetchContentLength`, `fetchContentTruncated`, `contentMimeType`, `sourceUrl`, `recordType`, `resultIndex`, `scrapedAt`.\n\nEmpty values are omitted at every depth, so a field appears only when the archive actually supplied it.\n\n## Input\n\n| Field | Type | Default | Description |\n|---|---|---|---|\n| `mode` | string | `search` | `search`, `timeline`, `summary`, `closest`, or `content` |\n| `url` | string | – | Single URL, host, domain, or playback URL |\n| `urls` | array | `[]` | Bulk targets; merged with `url` |\n| `matchType` | string | `exact` | `exact`, `prefix`, `host`, or `domain`; wildcards are auto-detected |\n| `dateFrom` | string | – | Earliest capture date, inclusive |\n| `dateTo` | string | – | Latest capture date, inclusive |\n| `statusCodes` | array | `[]` | Keep only these HTTP status codes |\n| `excludeStatusCodes` | array | `[]` | Drop these HTTP status codes |\n| `mimeTypes` | array | `[]` | Keep only these MIME types |\n| `excludeMimeTypes` | array | `[]` | Drop these MIME types |\n| `collapseBy` | string | `digest` | `none`, `digest`, `urlkey`, `monthly`, `daily`, or `hourly`; applies to `search` only |\n| `sortDirection` | string | `earliest` | `earliest` or `latest` |\n| `targetDate` | string | – | Reference date for `closest` and `content`; defaults to now |\n| `enrichWithContent` | boolean | `false` | Add archived text to search rows |\n| `maxContentFetch` | integer | `10` | Text-fetch cap for search enrichment (0–500) |\n| `maxContentChars` | integer | `500000` | Text cap per archived page (1,000–2,000,000) |\n| `includeHeadings` | boolean | `true` | Include H1–H6 headings in archived text |\n| `maxItems` | integer | `500` | Record cap (1–100,000) |\n| `detectChanges` | boolean | `true` | Annotate content/status changes in search rows |\n\nThe daily-test prefill is the cheapest possible run: `mode=closest`, `url=apify.com`, `targetDate=2024-01-01`, `maxItems=1`. It performs one availability lookup and returns one snapshot record.\n\n### Example: full capture history with changes\n\n```json\n{\n    \"mode\": \"search\",\n    \"url\": \"https://example.com/\",\n    \"matchType\": \"exact\",\n    \"dateFrom\": \"2020-01-01\",\n    \"dateTo\": \"2024-12-31\",\n    \"statusCodes\": [\"200\"],\n    \"collapseBy\": \"none\",\n    \"detectChanges\": true,\n    \"maxItems\": 500\n}\n```\n\n### Example: bulk closest snapshots\n\n```json\n{\n    \"mode\": \"closest\",\n    \"urls\": [\"apify.com\", \"example.com\", \"wikipedia.org\"],\n    \"targetDate\": \"2020-06-15\",\n    \"maxItems\": 3\n}\n```\n\n### Example: archived text from a playback URL\n\n```json\n{\n    \"mode\": \"content\",\n    \"url\": \"https://web.archive.org/web/20240101000000/https://apify.com/\",\n    \"maxItems\": 1,\n    \"includeHeadings\": true\n}\n```\n\n## Legacy inputs\n\nSaved tasks and integrations from earlier versions keep working. The actor still accepts `url` as a single target. Old field names `maxResults`, `includeContent`, `statusFilter`, and `mimeFilter` are mapped onto `maxItems`, `enrichWithContent`, `statusCodes`, and `mimeTypes` in code. Collapse aliases `timestamp:6`, `timestamp:8`, and `timestamp:10` are accepted alongside `monthly`, `daily`, and `hourly`.\n\n## Use cases\n\n- **Content recovery** — pull the text of pages that no longer exist\n- **SEO link-rot audits** — list archived 404s, redirects, and deleted pages on a domain\n- **Competitive history** — compare pricing, messaging, or product pages month by month\n- **Legal and journalism evidence** — pin the closest capture to a specific date\n- **Domain due diligence** — measure archive age, density, gaps, and version count before buying an expired domain\n- **Dataset building** — export archived text and metadata for search, NLP, or research\n\n## FAQ\n\n**Where does the data come from?**\nThe Internet Archive's public Wayback CDX search API, its availability API, and archived playback pages. No browser UI is scraped.\n\n**Do I need an Internet Archive account or API key?**\nNo. Every request is anonymous and cookieless.\n\n**Can I search the archive by keyword?**\nThe CDX API indexes URLs and capture metadata, not full text. Use `mode=content` to download page text and filter it in your own pipeline.\n\n**Why are some captures marked `warc/revisit`?**\nThe archive sometimes records a revisit instead of a full copy. Those rows keep the digest and size but may not have an HTTP status code.\n\n**Why is `content` missing from a row?**\nThe row was beyond the text-fetch budget, the archived resource was not HTML/text, or replay returned an error. `contentTruncated` is set when text was clipped at `maxContentChars`.\n\n**Why does `closest` mode omit MIME type and digest?**\nThe availability endpoint returns the nearest capture URL, timestamp, and status only. Use `search` mode with a narrow date range when you need full CDX metadata.\n\n**Can I retrieve more than 10,000 captures?**\nYes. The actor pages through the CDX index with resume keys, so `maxItems` can go up to 100,000. Very broad host/domain queries and `collapseBy=urlkey` can be slower on the archive side.\n\n**Is archive coverage complete?**\nNo. The Wayback Machine only stores what its crawlers captured. Popular pages usually have dense history; obscure pages may have none, and a summary row with `captureCount=0` is still a valid result.\n\n**Is this affiliated with the Internet Archive?**\nNo. It is an independent tool that reads the Internet Archive's public Wayback Machine endpoints.\n",
      "storages": {
        "dataset": {
          "actorSpecification": 1,
          "views": {
            "snapshots": {
              "title": "Capture history",
              "transformation": {
                "fields": [
                  "originalUrl",
                  "archiveDate",
                  "archiveUrl",
                  "statusCode",
                  "mimeType",
                  "contentLength",
                  "changeType",
                  "captureYear",
                  "resultIndex"
                ]
              },
              "display": {
                "component": "table",
                "properties": {
                  "originalUrl": {
                    "label": "Original URL",
                    "format": "text"
                  },
                  "archiveDate": {
                    "label": "Archive date",
                    "format": "date"
                  },
                  "archiveUrl": {
                    "label": "Wayback URL",
                    "format": "link"
                  },
                  "statusCode": {
                    "label": "HTTP status",
                    "format": "number"
                  },
                  "mimeType": {
                    "label": "MIME type",
                    "format": "text"
                  },
                  "contentLength": {
                    "label": "Bytes",
                    "format": "number"
                  },
                  "changeType": {
                    "label": "Change",
                    "format": "text"
                  },
                  "captureYear": {
                    "label": "Year",
                    "format": "number"
                  },
                  "resultIndex": {
                    "label": "Result #",
                    "format": "number"
                  }
                }
              }
            },
            "archivedText": {
              "title": "Archived text",
              "transformation": {
                "fields": [
                  "originalUrl",
                  "archiveDate",
                  "title",
                  "wordCount",
                  "characterCount",
                  "archiveUrl"
                ]
              },
              "display": {
                "component": "table",
                "properties": {
                  "originalUrl": {
                    "label": "Original URL",
                    "format": "text"
                  },
                  "archiveDate": {
                    "label": "Archive date",
                    "format": "date"
                  },
                  "title": {
                    "label": "Page title",
                    "format": "text"
                  },
                  "wordCount": {
                    "label": "Words",
                    "format": "number"
                  },
                  "characterCount": {
                    "label": "Characters",
                    "format": "number"
                  },
                  "archiveUrl": {
                    "label": "Wayback URL",
                    "format": "link"
                  }
                }
              }
            },
            "closestSnapshots": {
              "title": "Closest snapshots",
              "transformation": {
                "fields": [
                  "originalUrl",
                  "requestedDate",
                  "archiveDate",
                  "available",
                  "statusCode",
                  "archiveUrl"
                ]
              },
              "display": {
                "component": "table",
                "properties": {
                  "originalUrl": {
                    "label": "Original URL",
                    "format": "text"
                  },
                  "requestedDate": {
                    "label": "Requested date",
                    "format": "date"
                  },
                  "archiveDate": {
                    "label": "Archive date",
                    "format": "date"
                  },
                  "available": {
                    "label": "Archived",
                    "format": "boolean"
                  },
                  "statusCode": {
                    "label": "HTTP status",
                    "format": "number"
                  },
                  "archiveUrl": {
                    "label": "Wayback URL",
                    "format": "link"
                  }
                }
              }
            },
            "versions": {
              "title": "Version timeline",
              "transformation": {
                "fields": [
                  "originalUrl",
                  "firstArchiveDate",
                  "lastArchiveDate",
                  "captureCount",
                  "statusCode",
                  "archiveUrl"
                ]
              },
              "display": {
                "component": "table",
                "properties": {
                  "originalUrl": {
                    "label": "Original URL",
                    "format": "text"
                  },
                  "firstArchiveDate": {
                    "label": "First seen",
                    "format": "date"
                  },
                  "lastArchiveDate": {
                    "label": "Last seen",
                    "format": "date"
                  },
                  "captureCount": {
                    "label": "Captures",
                    "format": "number"
                  },
                  "statusCode": {
                    "label": "HTTP status",
                    "format": "number"
                  },
                  "archiveUrl": {
                    "label": "Wayback URL",
                    "format": "link"
                  }
                }
              }
            },
            "summaries": {
              "title": "Archive coverage",
              "transformation": {
                "fields": [
                  "originalUrl",
                  "captureCount",
                  "versionCount",
                  "firstArchiveDate",
                  "lastArchiveDate",
                  "spanDays"
                ]
              },
              "display": {
                "component": "table",
                "properties": {
                  "originalUrl": {
                    "label": "Original URL",
                    "format": "text"
                  },
                  "captureCount": {
                    "label": "Captures",
                    "format": "number"
                  },
                  "versionCount": {
                    "label": "Versions",
                    "format": "number"
                  },
                  "firstArchiveDate": {
                    "label": "First capture",
                    "format": "date"
                  },
                  "lastArchiveDate": {
                    "label": "Last capture",
                    "format": "date"
                  },
                  "spanDays": {
                    "label": "Days covered",
                    "format": "number"
                  }
                }
              }
            }
          }
        }
      },
      "defaultMemoryMbytes": 1024
    },
    "buildNumber": "2.0.1",
    "imageDigest": "ce98d8e14a320ea71ec3e83ccc23dea7325444e5f59b4efb2e95e3b2382e694a",
    "actVersion": {
      "sourceType": "SOURCE_FILES",
      "buildTag": "latest",
      "versionNumber": "2.0"
    },
    "usage": {
      "ACTOR_COMPUTE_UNITS": 0.004861111111111111
    }
  }
}