# Internet Archive API — Search, Metadata & Files (`insight.solutions/internet-archive-api`) Actor

Search archive.org and get its catalogue as data. One row per item: identifier, title, creators, date, subjects, collections, language, downloads, size and licence. Optional rows per file with direct download URLs, formats, sizes and checksums, and per public review. No API key, no login.

- **URL**: https://apify.com/insight.solutions/internet-archive-api.md
- **Developed by:** [Insight Solutions](https://apify.com/insight.solutions) (community)
- **Categories:** Education, AI, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.25 / 1,000 item returneds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Internet Archive API — Search, Metadata & Files

**Turn archive.org into a table.** Give this Actor a search — `collection:librivoxaudio`, `creator:"Jane Austen" AND mediatype:texts`, or just `apollo 11` — and get one row per item: identifier, title, creators, date, subjects, collections, language, downloads, size, licence and thumbnail. Pass identifiers instead and you get the full record for each one, plus a row per file with a direct download URL, format, size, MD5 and SHA-1, plus a row per public review.

No API key. No login. No cookies to paste. **$0.40 per 1,000 items, proxy included**, searches that match nothing are free, and a run that returns nothing costs nothing at all.

### Try it in 30 seconds

```json
{
  "searchQueries": ["subject:\"machine learning\" AND mediatype:texts"],
  "sort": "downloads",
  "maxResultsPerQuery": 100
}
```

Or go straight at items you already know:

```json
{
  "identifiers": [
    "nasa_techdoc_19930072988",
    "https://archive.org/details/0_sense_and_sensibility_librivox"
  ],
  "includeFiles": true,
  "fileFormats": ["MP3"],
  "includeReviews": true
}
```

### What comes back

One `item` row per archive.org item:

```jsonc
{
  "ok": true,
  "rowType": "item",                  // "item" | "file" | "review" | "diagnostic"

  "identifier": "0_sense_and_sensibility_librivox",
  "url": "https://archive.org/details/0_sense_and_sensibility_librivox",
  "input": "collection:librivoxaudio",
  "query": "collection:librivoxaudio",  // the query as the index saw it
  "position": 1,

  "title": "Sense and Sensibility",
  "creators": ["Jane Austen"],        // always a list, however the Archive stored it
  "date": "2007-03-30T00:00:00.000Z", // when the thing itself is dated
  "year": 2007,                       // survives even when the date is only a year
  "publicDate": "2007-03-30T06:03:05.000Z",
  "addedDate": null,                  // metadata-API only — see the note below
  "mediaType": "audio",
  "collections": ["librivoxaudio", "audio_bookspoetry", "…"],
  "subjects": ["librivox", "literature", "audiobook", "romance", "England"],
  "languages": ["eng"],

  "description": "LibriVox recording of Sense and Sensibility, by Jane Austen…",
  "descriptionHtml": null,            // the uploader's raw markup, metadata-API only
  "downloads": 2011009,               // all-time, search-index only
  "itemSizeBytes": 2173798776,
  "filesCount": null,                 // metadata-API only
  "avgRating": 3,
  "numReviews": 3,
  "license": null,                    // a licence URL when the uploader declared one
  "uploader": null,
  "thumbnailUrl": "https://archive.org/services/img/0_sense_and_sensibility_librivox",
  "recordSource": "search",           // "search" (short record) | "metadata" (full record)

  "error": null,
  "errorType": null,
  "scrapedAt": "2026-09-10T15:04:32.000Z",
  "source": "archive.org",
  "sourceUrl": "https://archive.org/advancedsearch.php?q=…"
}
```

One `file` row per file, with `includeFiles: true`:

```jsonc
{
  "ok": true,
  "rowType": "file",
  "identifier": "0_sense_and_sensibility_librivox",
  "position": 1,
  "fileName": "senseandsensibility_01_austen.mp3",
  "downloadUrl": "https://archive.org/download/0_sense_and_sensibility_librivox/senseandsensibility_01_austen.mp3",
  "format": "VBR MP3",                // the Archive's own label, not an extension
  "sourceKind": "original",           // "original" | "derivative" | "metadata"
  "sizeBytes": 9245780,
  "md5": "6b8718b186d5cb87178911cd49e4f535",
  "sha1": "7158d9c4b8e21acee4a069dde06f20cd84c53064",
  "modifiedAt": "2007-03-30T06:00:21.000Z",
  "durationSec": 577.86,
  "width": null,                      // the Archive writes 0 on audio; that is not a size
  "height": null,
  "title": "Chapter 01",
  "track": 1                          // "1/50" on the wire; the track itself here
}
```

And one `review` row per public review, with `includeReviews: true`:

```jsonc
{
  "ok": true,
  "rowType": "review",
  "identifier": "nasa_techdoc_19930072988",
  "reviewer": "Basquetteur",
  "reviewerHandle": "@basquette",     // archive.org/details/@basquette
  "title": "wrong keywords",
  "body": "wrong keywords",           // exactly as written
  "stars": 1,
  "reviewedAt": "2017-11-29T20:39:18.000Z"
}
```

Every row carries every column, with null wherever it does not apply — so a CSV export, a SQL insert or a dataframe gets one stable shape.

### Use cases

- **Build a training or RAG corpus from public-domain material.** A subject or collection query gives you identifiers, licences and descriptions; `includeFiles` with `fileFormats: ["PDF"]` or `["EPUB"]` gives you the direct download URL and the checksum for each one. `license` tells you what you are allowed to do with it before you download a byte.
- **Bulk-download a collection properly.** File rows carry `md5` and `sha1`, so a download can be verified rather than assumed, and `sourceKind` separates the uploader's original from the copies the Archive generated.
- **Catalogue and library work.** One row per item with creators, subjects, collections, language, dates and size — the shape a librarian or a metadata pipeline actually wants, out of an API that otherwise answers one item at a time.
- **Media research.** `mediatype:movies` plus `dateFrom`/`dateTo` over the Prelinger or NASA collections, sorted by downloads, tells you what survives and what people actually watch.
- **Reception and sentiment.** `includeReviews` gives you the public reviews with star ratings and dates, for items whose reception nobody has ever tabulated.
- **Audit your own uploads.** `uploader:you@example.com` as a query returns everything you have contributed, with sizes, file counts and download totals.

### How it works, and why it keeps working

The Internet Archive publishes three JSON endpoints for public use, and this Actor reads exactly those:

| Step | Request | What it gets |
|---|---|---|
| 1 | `advancedsearch.php?q=…&rows=100&page=1&output=json` | Page one: up to 100 items, plus `numFound` — how many the query matches |
| 2… | `…&page=2`, `page=3`, … | 100 more each time, until your cap, your budget, the end of the results, or the index's 10,000 ceiling |
| A | `metadata/<identifier>` | One item's full record: metadata, every file, and its reviews |
| B | `metadata/<identifier>/reviews` | Reviews alone — only when a record does not carry them |

Four details in there are the ones cheap scrapers get wrong:

**Page numbers, not a cursor.** The Archive also publishes a cursor-paged search service, and it is the obvious thing to reach for. In September 2026 we found it handing back page one again for every cursor, and on some queries answering a completely different query's results. Page numbers on `advancedsearch.php` were correct in the same runs, so that is what this Actor walks: `page=1`, `page=2`, and `response.start` on every page saying where it landed.

**Pages can overlap, so identifiers are de-duplicated.** Page one of `collection:prelinger` ends on `MilitaryCour` and page two opens with it. A large index is not a frozen list; items move while you walk it. Every identifier already returned for a query is skipped the second time, the run log says how many were skipped, and you are never billed twice for the same row.

**The same field is a string on one item and a list on the next.** `creator` arrives as an array on 35 of the 50 hits in one captured page and as a bare string on the other 15. `subject` adds a third shape that only the metadata API uses: `"librivox; literature; audiobook; romance; England;"` — several subjects packed into one string. All three normalise to a list here, so `creators` and `subjects` are always arrays and never a surprise.

**File names are paths.** 90 of the 103 files on the Apollo 11 onboard film live inside a `.thumbs/` directory, so their names contain a `/`. Percent-encoding the whole name turns that slash into `%2F` and every download URL into a 404; each segment is encoded on its own.

Underneath: **Apify datacenter proxy**, one pinned session per parallel worker. The Archive answers a burst from one address with HTTP 429 or 503, and when that happens the session is retired and **the same page is asked for once more from a different exit**. Retrying on an address that was just refused only deepens it, so it is never done. If the second exit is refused too, the walk stops, **keeps every row it already delivered**, and files one free `blocked` row saying where it stopped.

Requests to the same target are spaced 300–600 ms apart and three targets run in parallel. Nothing forces that. The Internet Archive is a non-profit serving these endpoints to anyone who asks, without a key and without a quota, and this is a rate that reads it rather than hammering it.

**This is not the Wayback Machine.** Archived copies of web pages live in a different index with a different API; paste a `web.archive.org/web/…` URL here and you get a diagnostic row saying so. That job is [Wayback Machine Toolkit](https://apify.com/insight.solutions/wayback-toolkit).

### How it compares

- **No API key, no quota, no login.** A search string is the whole input.
- **Search and full records in one Actor.** The search index holds a short record; the metadata API holds the complete one. Most tools give you one or the other. Here `recordSource` tells you which you are looking at, and `includeMetadataForSearchHits` upgrades search hits when you want the full thing.
- **Files are first-class rows.** Direct download URLs, formats, sizes, durations, dimensions, track numbers, MD5 and SHA-1 — as data you can join, not a link you have to scrape a page for.
- **Reviews nobody else returns.** Public reviews with star ratings, reviewer accounts and exact dates, usually at no extra request.
- **The messy shapes are handled.** String-or-array fields, semicolon-packed subjects, two different timestamp spellings for the same instant, year-only dates, `"0"` written where a dimension does not exist. Every one of those is a real case from a captured response, and every one is normalised.
- **Failures are free and legible.** An unknown identifier, a query that matches nothing, a Wayback URL, a rate-limited page — each produces a diagnostic row with an `errorType` you can branch on, and no charge. A run that returns nothing at all finishes **FAILED** with the reason in its status message, never a green run containing an apology.
- **A partial walk is kept, not thrown away.** Hit `maxRunSecs` or your charge ceiling on page 12 and you keep pages 1–11.

### Input reference

| Field | Type | Default | What it does |
|---|---|---|---|
| `searchQueries` | array of strings | prefilled with one query | Archive query syntax: `collection:…`, `creator:"…"`, `subject:"…"`, `uploader:…`, plain words, combined with `AND` / `OR` / `NOT`. One `item` row per hit |
| `identifiers` | array of strings | `[]` | Item identifiers or `archive.org/details/…` URLs. Read from the metadata API, so the record is the complete one. Case-sensitive |
| `mediaType` | `any` | `texts` | `audio` | `movies` | `image` | `software` | `data` | `web` | `any` | Appended to each query as `AND mediatype:…`, unless the query already names one |
| `sort` | `relevance` | `downloads` | `date` | `publicdate` | `title` | `relevance` | Result order. A sort the index refuses is dropped once and the query retried, rather than failing |
| `dateFrom`, `dateTo` | `YYYY-MM-DD` | none | Bound each query by the item's own date. Either end can stand alone |
| `maxResultsPerQuery` | integer | `100` | Items per query. The walk reads 100-item pages and stops on the page that reaches your number. `0` = everything, up to the index's 10,000 ceiling |
| `includeFiles` | boolean | `false` | One `file` row per file on each item in `identifiers`. Billed as its own event |
| `maxFilesPerItem` | integer | `200` | Ceiling on file rows per item, applied *after* `fileFormats`. `0` = no ceiling |
| `fileFormats` | array of strings | `[]` | Keep only these formats. `MP3` matches `VBR MP3` and `64Kbps MP3`; `PDF` matches `Text PDF`. Extensions work too |
| `includeReviews` | boolean | `false` | One `review` row per public review on each item in `identifiers`. Usually costs no extra request |
| `includeMetadataForSearchHits` | boolean | `false` | Fill search hits in from the metadata API. **One extra request per hit** — a hundred results means a hundred requests |
| `maxConcurrency` | integer | `3` | Queries and items in parallel. Each worker keeps its own proxy session. Pages within one query cannot be parallelised |
| `maxRunSecs` | integer | `240` | Whole-run wall-clock budget. When it runs out the Actor keeps what it has and files a free diagnostic row for each entry it never reached |
| `proxyConfiguration` | object | Apify datacenter | Leave it alone unless you are pulling tens of thousands of items, in which case residential is the upgrade |

### Output reference

Every row carries the same keys. `ok: true` is an item, a file or a review; `ok: false` is a free diagnostic row.

| Field | What it is |
|---|---|
| `rowType` | `item`, `file`, `review` or `diagnostic` |
| `identifier`, `url`, `input`, `query`, `position` | The item, its public page, the entry you supplied, the query that found it, and where it fell in the order |
| `title`, `creators`, `date`, `year`, `publicDate`, `addedDate` | Item rows: what it is, who made it, when it is dated and when it reached the Archive |
| `mediaType`, `collections`, `subjects`, `languages` | Item rows: how the Archive classifies it |
| `description`, `descriptionHtml` | Item rows: the description as text (≤ 5,000 chars) and, from the metadata API, as the uploader wrote it |
| `downloads`, `itemSizeBytes`, `filesCount`, `avgRating`, `numReviews` | Item rows: the five numbers people rank and filter on |
| `license`, `uploader`, `thumbnailUrl`, `recordSource` | Item rows: the declared licence URL, who uploaded it, a thumbnail, and whether this row is the short record or the full one |
| `fileName`, `downloadUrl`, `format`, `sourceKind`, `sizeBytes` | File rows: the file, where to get it, what it is, and whether it is the original or a derivative |
| `md5`, `sha1`, `modifiedAt` | File rows: checksums to verify a download, and when the file was last written |
| `durationSec`, `width`, `height`, `track`, `title` | File rows: playing time, pixel dimensions, track number and the file's own title |
| `reviewer`, `reviewerHandle`, `title`, `body`, `stars`, `reviewedAt` | Review rows: who, what and when |
| `ok`, `error`, `errorType` | Whether this row is data, and if not, why not |
| `scrapedAt`, `source`, `sourceUrl` | When, and from exactly which endpoint |

`errorType` on a diagnostic row is one of:

| Value | Meaning | Charged? |
|---|---|---|
| `not-found` | No archive.org item with that identifier. Identifiers are case-sensitive | No |
| `no-results` | The query is valid and matches nothing | No |
| `invalid-input` | The entry was not usable — a Wayback URL, a non-Archive link, an account page, or a query the index rejected (its own message is in `error`) | No |
| `blocked` | The Archive refused our requests from two different exit IPs — usually a rate limit. Rows already returned for that entry are kept | No |
| `timeout` | The run's `maxRunSecs` budget ran out before this entry was reached | No |
| `unavailable` | The Archive answered with something unusable | No |

### Pricing

**$0.40 per 1,000 items.** Pay-per-event, with the proxy already inside that number — there is no separate proxy line on your bill for this Actor.

| Event | What triggers it | FREE | Starter | Scale | Business |
|---|---|---|---|---|---|
| **Item returned** *(primary)* | One `item` row written to your dataset | $0.0004 | $0.0004 | $0.0003 | $0.00025 |
| File record returned | One `file` row — download URL, format, size, checksums | $0.0001 | $0.0001 | $0.0001 | $0.0001 |
| Review returned | One `review` row | $0.0002 | $0.0002 | $0.0002 | $0.0002 |
| Run started | Once per run, after the first paid row | $0.001 | $0.001 | $0.001 | $0.001 |

**Worked example.** 50 audiobook identifiers with `includeFiles: true` and `fileFormats: ["MP3"]`, averaging 100 MP3 derivatives each:

- 50 items × $0.0004 = **$0.02**
- 5,000 file rows × $0.0001 = **$0.50**
- 1 run start = **$0.001**
- **Total: $0.521**

What you are never charged for: a query that matches nothing, an unknown identifier, an entry that was not an Archive item, an entry the run never reached before `maxRunSecs`, or a page the Archive rate-limited. If a whole run comes back empty it finishes FAILED and bills **nothing at all**, start fee included.

Set `ACTOR_MAX_TOTAL_CHARGE_USD` on a run and the Actor stops walking once the ceiling is in sight, rather than handing you rows it cannot bill or billing you for rows it cannot hand over. It finishes SUCCEEDED with the ceiling named in its status message, and everything already delivered is yours.

### Limits, and the ones that might bite

**Search hits carry a shorter record than items.** The index does not publish `licenseurl`, `uploader`, `addeddate` or `files_count`, so those are null on a plain search row — and the metadata API does not publish `downloads`, so that is null on a plain identifier row. `recordSource` says which record you have. `includeMetadataForSearchHits: true` merges both, at one extra request per hit.

**10,000 results per query is the index's ceiling, not ours.** `advancedsearch.php` refuses to page past result 10,000 — `page` × `rows` may not go beyond it — so a walk stops there whatever `maxResultsPerQuery` says, and the run log says it stopped. Split a bigger job by date range, by collection or by media type; `collection:prelinger AND date:[1950-01-01 TO 1959-12-31]` is 1,567 items where the collection is 10,468.

**`includeFiles` on a large item is a lot of rows.** A 50-chapter LibriVox audiobook has 377 files, because the Archive derives an MP3, an Ogg, a spectrogram and two analysis files for every chapter. That is why `maxFilesPerItem` defaults to 200 and why `fileFormats` exists.

**Files and reviews follow `identifiers`, not search hits.** A search returns item rows. To get the files or reviews for what a search found, run the search first and feed the identifiers back in — deliberately, so a hundred-result search cannot quietly turn into thirty thousand file rows.

**Dates on the Archive are what uploaders typed.** Plenty of items are dated by year alone, some are wrong, and a few are missing. `date` is null when the value is not a full calendar date and `year` carries what is known; nothing here invents the first of January.

**A licence of null is not permission.** Most Archive items carry no declared licence, and the Archive hosts material under many different rights situations. `license` reports what the uploader declared and nothing more; what you may do with a file is your call to make.

**Star ratings are sparse.** Most items have no reviews at all, and `avgRating` on a search hit comes from the index while on an identifier it is averaged from that item's own rated reviews. Reviews left without a rating are not counted as zero stars.

**The Archive may change the format.** These are public, undocumented JSON endpoints and they can change without notice — that is true of every tool that reads archive.org, including the ones that do not say so. When a shape changes, rows stop arriving and you get free `blocked` or `unavailable` diagnostic rows rather than quietly wrong data, and a run that returns nothing bills nothing.

**Rate and reliability.** Requests go out through Apify datacenter proxy with per-worker sessions, one rotation per refusal, and a 300–600 ms pause between requests to the same target. Three in parallel is the default because the Archive is a free public service and this is a rate that respects it; raising `maxConcurrency` speeds a long list up and makes 429s more likely.

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

One JSON object in, one flat array out — the shape agent runtimes want. The Actor runs with **limited permissions**, uses **pay-per-event** pricing and never enters Standby, so it works over the Apify MCP server and with x402 agentic payments. The **Integrations** tab pushes results to Slack, a webhook, Zapier, Make, Google Sheets, Snowflake or BigQuery.

```bash
curl -X POST "https://api.apify.com/v2/acts/insight.solutions~internet-archive-api/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"searchQueries":["collection:librivoxaudio"],"sort":"downloads","maxResultsPerQuery":100}'
```

```python
## pip install apify-client
from apify_client import ApifyClient

client = ApifyClient("<APIFY_TOKEN>")
run = client.actor("insight.solutions/internet-archive-api").call(run_input={
    "identifiers": ["0_sense_and_sensibility_librivox"],
    "includeFiles": True,
    "fileFormats": ["MP3"],
    "includeReviews": True,
})

for row in client.dataset(run["defaultDatasetId"]).iterate_items():
    if not row.get("ok"):
        print("skipped:", row["input"], row["errorType"])
    elif row["rowType"] == "item":
        print(f'{row["title"]} — {row["mediaType"]}, {row["filesCount"]} files')
    elif row["rowType"] == "file":
        print(f'  {row["fileName"]}  {row["sizeBytes"]} bytes  {row["md5"]}')
    else:
        print(f'  {row["stars"]}★ {row["reviewer"]}: {row["title"]}')
```

### FAQ

**What query syntax does it take?**
The Archive's own. Field searches (`collection:`, `creator:`, `subject:`, `title:`, `description:`, `uploader:`, `mediatype:`, `date:`, `identifier:`) combined with `AND`, `OR`, `NOT` and parentheses, plus plain words for a full-text search. Quote anything containing a space.

**How many items can I get from one query?**
Up to 10,000 — the search index's own ceiling for one result set. Set `maxResultsPerQuery: 0` for all of them, and split bigger jobs by date range or collection.

**Can I download the actual files?**
This Actor returns the direct download URL, the format, the size and the checksums for every file. Fetching the bytes is a separate job and a different bill — but everything you need to do it correctly, verification included, is in the row.

**Does it read the Wayback Machine?**
No. Archived web pages are a different index. Use [Wayback Machine Toolkit](https://apify.com/insight.solutions/wayback-toolkit) for those.

**Why is `downloads` empty on some rows?**
Because that row came from the metadata API, which does not publish a download count — only the search index does. `recordSource` tells you which record a row is.

**Are file and review rows charged separately?**
Yes: $0.0001 per file row and $0.0002 per review row, against $0.0004 per item. Leave `includeFiles` and `includeReviews` off and neither is fetched or billed.

**What happens if one query fails?**
The others still run. The failed one produces a free diagnostic row and the run finishes `SUCCEEDED`. If *every* entry fails, the run finishes `FAILED` and you are billed nothing at all.

**Is the data fresh?**
Live. Every run reads archive.org at that moment; nothing is cached.

### Legal and data-protection notes

- **Public endpoints only.** Every source is a public Internet Archive API. The Actor never logs in, never accepts cookies or session tokens, never takes an API key belonging to anyone else, and never touches private items, accounts or borrowing records.
- **Rights vary item by item.** The Archive hosts public-domain works, openly licensed works, and works held under many other arrangements. `license` reports the licence URL the uploader declared, and a null there means nothing was declared — not that the item is free to reuse. Checking the rights on what you download is your responsibility.
- **Reviews and uploader names are personal data in most jurisdictions.** A review carries a public account name and a date, and under the GDPR and similar laws that is personal data about an identifiable person. You are the controller of whatever you collect: have a lawful basis, keep only what you need, honour deletion requests, and remember that a review deleted on archive.org stays in your dataset until you remove it.
- **Be a good citizen.** The Internet Archive is a non-profit that serves these endpoints to everyone, free, without a key. The defaults here — three targets in parallel, a pause between requests, a hard ceiling on results per query — are set to read it politely, and raising them is a decision to take seriously. Consider [donating](https://archive.org/donate).
- **Not affiliated with the Internet Archive.** All names and trademarks belong to their respective owners and are used only to describe which public endpoints this Actor reads.

### Our other Actors

Every Insight Solutions Actor is pay-per-result with no browser, no login and no API key, and every one of them returns free diagnostic rows instead of billing for failures. Prices are per 1,000 results.

**Video, audio & social**

- [YouTube Transcript API](https://apify.com/insight.solutions/youtube-transcript-api) — captions as timed segments, text, SRT or VTT, with language fallback and translation.
- [YouTube Comments API](https://apify.com/insight.solutions/youtube-comments-api) — comments and replies with likes, pinned and hearted flags, newest or top sort.
- [YouTube Channel API](https://apify.com/insight.solutions/youtube-channel-api) — a channel's videos, Shorts and live streams, plus YouTube search.
- [Podcast Search, Episodes & Charts API](https://apify.com/insight.solutions/podcast-api) — Apple Podcasts search, charts and full episode feeds.
- [Bluesky Scraper](https://apify.com/insight.solutions/bluesky-scraper) — profiles, posts, followers and follows from the public AT Protocol API.
- [Telegram Channel Scraper](https://apify.com/insight.solutions/telegram-channel-scraper) — posts, views and channel stats from public Telegram channels.
- [Substack Scraper](https://apify.com/insight.solutions/substack-scraper) — posts with full free text, comments and publication profiles.

**News, documents & the web**

- [Google News Search, Topics & Real Article URLs](https://apify.com/insight.solutions/google-news-api) — news search and topic feeds with the publisher's real URL decoded.
- [Website to Markdown — Content Extractor for LLMs & RAG](https://apify.com/insight.solutions/website-content-extractor) — any site as clean Markdown, text and heading-aware chunks.
- [Wayback Machine Toolkit](https://apify.com/insight.solutions/wayback-toolkit) — archived URL inventories, snapshots and text diffs between dates.
- [Website Technology Detector](https://apify.com/insight.solutions/website-tech-detector) — the tech stack behind any site, with the evidence for each detection.
- [Domain Intelligence API](https://apify.com/insight.solutions/domain-intelligence-api) — DNS, RDAP registration, TLS certificate and HTTP facts in one row per domain.
- [SEO Page Audit](https://apify.com/insight.solutions/seo-page-audit) — sitemap crawl with on-page checks, structured data and broken-link reports.
- [Keyword Suggestions API](https://apify.com/insight.solutions/keyword-suggestions-api) — Google, YouTube, Bing, Amazon and eBay autocomplete with alphabet and question expansions.
- [Website Contact Extractor](https://apify.com/insight.solutions/website-contact-extractor) — emails, phone numbers and social profiles from any list of websites.

**Business, finance & jobs**

- [Congress & Insider Trades API](https://apify.com/insight.solutions/congress-insider-trades-api) — STOCK Act periodic transaction reports and SEC Form 4 insider trades in one schema.
- [SEC EDGAR API](https://apify.com/insight.solutions/sec-edgar-api) — filings, XBRL financials and full-text search by ticker or CIK.
- [Y Combinator Companies, Batches & Founders](https://apify.com/insight.solutions/yc-companies-directory) — the YC directory with founders and social links, filterable by batch, industry and hiring status.
- [Career Site Jobs API](https://apify.com/insight.solutions/ats-jobs-api) — jobs straight from Greenhouse, Lever, Ashby, Workable and 10+ other ATS career sites.
- [New Job Postings Monitor](https://apify.com/insight.solutions/job-postings-monitor) — new, closed and changed postings on the career sites you watch.
- [Shopify Products API](https://apify.com/insight.solutions/shopify-products-api) — any Shopify store's catalogue, variants, prices and stock signals.

**Apps & games**

- [App Store & Google Play Reviews API](https://apify.com/insight.solutions/app-reviews-api) — reviews from both stores with ratings, versions and developer replies.
- [App Store Top Charts & App Search API](https://apify.com/insight.solutions/app-charts-api) — Apple top charts by country and genre, plus app search and details.
- [Steam Reviews API](https://apify.com/insight.solutions/steam-reviews-api) — Steam reviews with playtime, helpfulness and game details.
- [Steam Game Data API](https://apify.com/insight.solutions/steam-store-stats-api) — prices, tags, review scores, live player counts and top charts.

# Actor input Schema

## `searchQueries` (type: `array`):

One entry per search, in the Internet Archive's own query language. Field searches — `collection:librivoxaudio`, `creator:"Jane Austen"`, `subject:"machine learning"`, `uploader:someone@example.com` — can be combined with `AND`, `OR` and `NOT`, and plain words search everything. Every hit becomes one `item` row. Leave this empty and pass `identifiers` instead if you already know which items you want.

## `identifiers` (type: `array`):

Items to read directly, as bare identifiers (`nasa_techdoc_19930072988`) or full links (`https://archive.org/details/nasa_techdoc_19930072988`). Each one is read from the Archive's metadata API, which returns the complete record — licence, uploader, added date, file count — rather than the shorter record the search index holds. Identifiers are case-sensitive. Wayback Machine capture URLs are not items and are rejected with an explanation.

## `mediaType` (type: `string`):

Narrow every search query to one kind of item. This is appended to your query as `AND mediatype:…` — but only when the query does not already name a media type of its own, because two `mediatype:` clauses can never both match. It does not affect `identifiers`.

## `sort` (type: `string`):

How the Archive should order each query's results. `relevance` is the index's own default and the fastest. `downloads` puts the most-downloaded items first, which is the closest thing the Archive has to a popularity ranking. `date` is the item's own date (when the thing was made); `publicdate` is when it was uploaded. If the index refuses a sort, the query is retried once in the default order rather than returning nothing, and the run log says so.

## `dateFrom` (type: `string`):

Keep only items whose own `date` is on or after this day. It is added to every search query as `AND date:[from TO to]`, and either end can be left empty for an open range. This is the date of the thing itself — when the film was shot, the book published — not when it was uploaded. Anything that is not a `YYYY-MM-DD` day is ignored rather than sent to the index as a syntax error.

## `dateTo` (type: `string`):

Keep only items whose own `date` is on or before this day. Pairs with `dateFrom`; either can be used alone.

## `maxResultsPerQuery` (type: `integer`):

How many items to return for each search query. The Archive's search index is read a hundred results per page, so a run for ten results reads one page and keeps ten — and the walk stops on the page that reaches your number. Set 0 for everything the query matches, up to the index's own ceiling of 10,000 results per query: it will not page past that, and the run log says so when a walk stops there.

## `includeFiles` (type: `boolean`):

Return one `file` row per file on each item in `identifiers`: name, direct download URL, format, whether it is the original upload or a derivative the Archive made from it, size, MD5 and SHA-1, duration, dimensions and track number. Items have far more files than people expect — a 50-chapter audiobook carries 377 — so this is off by default and bounded by `maxFilesPerItem`. It does not apply to search hits.

## `maxFilesPerItem` (type: `integer`):

The ceiling on `file` rows for one item, applied after `fileFormats` has filtered the list — so a cap of 20 with a format filter gives you 20 of the files you asked for, not 20 of everything. Set 0 for no ceiling.

## `fileFormats` (type: `array`):

Keep only files matching these formats. Matching is case-insensitive against the Archive's own format label and against the file extension, and a single word matches every variant of it: `MP3` keeps both `VBR MP3` and `64Kbps MP3`, `PDF` keeps `Text PDF`. Leave empty to keep every file, originals and derivatives alike.

## `includeReviews` (type: `boolean`):

Return one `review` row per public review on each item in `identifiers`: reviewer, their Archive account, title, body, star rating and date. The metadata record already carries an item's reviews, so this usually costs no extra request. It does not apply to search hits.

## `includeMetadataForSearchHits` (type: `boolean`):

Search hits come from the Archive's index, which holds a shorter record than the item itself: no licence, no uploader, no added date, no file count, and a description with its formatting flattened. Turning this on fetches the full record for every hit — **one extra request per hit**, so a hundred results means a hundred requests and a much longer run. Off by default. The columns the index does have (`downloads`, `avgRating`, `numReviews`) are kept either way.

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

How many search queries and identifiers are read at once. Each parallel worker keeps its own proxy session, so a worker that gets rate-limited burns only its own exit IP. Pages *within* one query are read one after another, not in parallel. Three is deliberate: the Archive is a non-profit serving these endpoints for free, and this is a rate that reads it rather than hammering it.

## `maxRunSecs` (type: `integer`):

Wall-clock budget for the whole run. When it is reached the Actor stops walking, keeps and bills for every row it already wrote, and files a free diagnostic row for each entry it never reached. A query stopped part-way keeps its rows and is not marked as failed. Nothing is charged for work that did not happen.

## `proxyConfiguration` (type: `object`):

The Archive serves these endpoints to datacenter addresses, so the default is Apify's datacenter proxy — the same data at a fraction of the traffic cost, and its cost is already inside the per-item price. Switch to residential only if you are pulling tens of thousands of items and start seeing `blocked` rows. Sessions rotate automatically when an exit IP is refused.

## Actor input object example

```json
{
  "searchQueries": [
    "collection:librivoxaudio",
    "creator:\"Jane Austen\" AND mediatype:texts",
    "apollo 11"
  ],
  "identifiers": [
    "nasa_techdoc_19930072988",
    "https://archive.org/details/0_sense_and_sensibility_librivox"
  ],
  "mediaType": "any",
  "sort": "downloads",
  "dateFrom": "1950-01-01",
  "dateTo": "1959-12-31",
  "maxResultsPerQuery": 100,
  "includeFiles": false,
  "maxFilesPerItem": 200,
  "fileFormats": [
    "MP3",
    "PDF"
  ],
  "includeReviews": false,
  "includeMetadataForSearchHits": false,
  "maxConcurrency": 3,
  "maxRunSecs": 240,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

One row per archive.org item — identifier, title, creators, date, subjects, collections, downloads, size and licence — optionally followed by one row per file and one per public review. Entries that could not be read get a free diagnostic row saying why. Delivered as JSON items in the default dataset.

# 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 = {
    "searchQueries": [
        "subject:\"machine learning\" AND mediatype:texts"
    ],
    "identifiers": [],
    "mediaType": "any",
    "sort": "downloads",
    "maxResultsPerQuery": 100,
    "includeFiles": false,
    "maxFilesPerItem": 200,
    "fileFormats": [],
    "includeReviews": false,
    "includeMetadataForSearchHits": false,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("insight.solutions/internet-archive-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 = {
    "searchQueries": ["subject:\"machine learning\" AND mediatype:texts"],
    "identifiers": [],
    "mediaType": "any",
    "sort": "downloads",
    "maxResultsPerQuery": 100,
    "includeFiles": False,
    "maxFilesPerItem": 200,
    "fileFormats": [],
    "includeReviews": False,
    "includeMetadataForSearchHits": False,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("insight.solutions/internet-archive-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 '{
  "searchQueries": [
    "subject:\\"machine learning\\" AND mediatype:texts"
  ],
  "identifiers": [],
  "mediaType": "any",
  "sort": "downloads",
  "maxResultsPerQuery": 100,
  "includeFiles": false,
  "maxFilesPerItem": 200,
  "fileFormats": [],
  "includeReviews": false,
  "includeMetadataForSearchHits": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call insight.solutions/internet-archive-api --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,insight.solutions/internet-archive-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/lA2wHkNHR4eI7QU9m/builds/Y5RaDa9ofBy1rtO5N/openapi.json
