# LibriVox Audiobook Scraper (`crawlerbros/librivox-audiobook-scraper`) Actor

Search LibriVox's free public-domain audiobook catalog - get full chapter listings with direct MP3 download URLs, readers, cover art, and metadata. No login, no cost.

- **URL**: https://apify.com/crawlerbros/librivox-audiobook-scraper.md
- **Developed by:** [Crawler Bros](https://apify.com/crawlerbros) (community)
- **Categories:** Developer tools, Integrations, Other
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 results

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

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#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

## LibriVox Audiobook Scraper

Search **LibriVox** — the largest catalog of free, public-domain audiobooks read by volunteers. Get full metadata, complete chapter/section listings with direct MP3 download URLs, reader names, cover art, and genre tags. Powered by LibriVox's official public API — no login, no cost.

### What this actor does

- **Five modes:** `search` (by title), `byAuthor` (exact last name), `byGenre` (147 curated genres), `byIds` (direct lookup), `recent` (catalogued since a given date)
- **Full chapter/section data** — every audiobook record includes its complete list of sections, each with a direct, permanent MP3 URL, reader name, and playtime
- **Filters:** language (106 languages), duration range, copyright year range, keyword search
- **Empty fields are omitted** — every field present in a record is guaranteed to have real data

### Output fields

| Field | Description |
|---|---|
| `bookId` | LibriVox numeric project id |
| `title`, `description` | |
| `language` | Recording language, e.g. `English` |
| `copyrightYear` | Original work's copyright year |
| `numSections`, `totalTime`, `totalTimeSecs` | Chapter count and total audio length |
| `authors[]` | `{authorId, firstName, lastName, name, birthYear, deathYear}` |
| `translators[]` | Same shape as `authors`, when the work is a translation |
| `genres[]` | `{genreId, name}` |
| `sections[]` | `{sectionId, sectionNumber, title, listenUrl, playtimeSecs, readers[]}` — one entry per chapter, each with its own direct MP3 URL |
| `coverArtUrl`, `coverArtThumbnailUrl`, `coverArtPdfUrl` | Cover art at various sizes/formats |
| `rssFeedUrl` | Podcast-style RSS feed for the whole book |
| `zipDownloadUrl` | Direct link to a ZIP of all chapter MP3s |
| `librivoxUrl` | The book's LibriVox project page |
| `textSourceUrl` | Link to the original text (usually Project Gutenberg) |
| `internetArchiveUrl` | The book's Internet Archive details page |
| `projectUrl` | Background-reading link LibriVox associates with the work (often its Wikipedia article), when provided |
| `sourceUrl` | Same as `librivoxUrl` |

Every record also has `recordType: "audiobook"` and `scrapedAt` (UTC ISO timestamp).

### Input

| Field | Type | Applies to | Description |
|---|---|---|---|
| `mode` | select | all | `search` / `byAuthor` / `byGenre` / `byIds` / `recent` |
| `titleQuery` | string | search | Book title — matches from the start (auto-prefix), or an exact full title |
| `authorLastName` | string | byAuthor | Exact author last name, case-insensitive |
| `genre` | select | byGenre | One of LibriVox's 147 genres/sub-genres |
| `bookIds` | array | byIds | LibriVox numeric book IDs |
| `sinceDate` | string | recent | `YYYY-MM-DD` — return audiobooks catalogued on/after this date |
| `language` | select | all | Filter to one of 106 recording languages |
| `minDurationSeconds` / `maxDurationSeconds` | integer | all | Total audiobook length filter |
| `copyrightYearMin` / `copyrightYearMax` | integer | all | Original work's copyright year filter |
| `containsKeyword` | string | all | Case-insensitive match against title / description / author / genre |
| `maxItems` | integer | all | Hard cap on emitted records (1–2000, default 30) |

#### Example: search by title

```json
{ "mode": "search", "titleQuery": "Sherlock Holmes", "maxItems": 20 }
```

#### Example: everything by an author

```json
{ "mode": "byAuthor", "authorLastName": "Twain", "maxItems": 50 }
```

#### Example: short poetry collections in English

```json
{
  "mode": "byGenre",
  "genre": "Poetry",
  "language": "English",
  "maxDurationSeconds": 3600,
  "maxItems": 25
}
```

#### Example: lookup specific books by ID

```json
{ "mode": "byIds", "bookIds": ["52", "47"] }
```

#### Example: recently catalogued audiobooks

```json
{ "mode": "recent", "sinceDate": "2026-05-01", "maxItems": 30 }
```

### Use cases

- **Audiobook apps** — bulk-import a free public-domain audiobook catalog with ready-to-stream chapter URLs
- **Podcast tools** — repurpose `rssFeedUrl` as a podcast feed per book
- **Digital libraries** — pair with `textSourceUrl` to cross-link the audio and text editions of a work
- **Language learners** — filter by `language` to build a practice-listening library
- **Literary research** — analyze genre/author/era coverage of the public-domain audiobook catalog

### FAQ

**Do I need a LibriVox account or API key?**  No. LibriVox's audiobook API is fully public; this actor uses no cookies, API key, or paid proxy.

**Why does `titleQuery` need to match from the start of the title?**  LibriVox's search API only supports exact-title or "starts with" matching, not free-text substring search. The actor automatically anchors your query as a prefix match, so `"Pride and"` will find "Pride and Prejudice" — but a mid-title fragment like `"and Prejudice"` won't match. Use `mode=byAuthor` or `mode=byGenre` for broader discovery.

**Why does `authorLastName` require an exact match?**  This mirrors a limitation of LibriVox's own API — it only accepts an exact last name (case-insensitive), not partial or fuzzy matches.

**Can I get the actual audio, not just links?**  This actor returns direct, permanent MP3 URLs (hosted on archive.org) for every chapter — download them separately with your own HTTP client.

**Are these audiobooks really free to use?**  Yes — LibriVox only records works that are in the public domain, and all recordings are released to the public domain as well.

**How fresh is the data?**  LibriVox adds new recordings continuously; since this actor queries the live API on every run, results reflect the current catalog.

**What does `mode=recent` return?**  Audiobooks that LibriVox catalogued on or after the `sinceDate` you provide, using LibriVox's own `since` API parameter — handy for tracking new additions to the catalog over time.

# Actor input Schema

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

What to fetch.

## `titleQuery` (type: `string`):

Book title to search for. Matches from the start of the title (case-sensitive prefix match) — e.g. `Pride and` matches "Pride and Prejudice". An exact full title also works.

## `authorLastName` (type: `string`):

Exact author last name, case-insensitive (e.g. `Dumas`, `Twain`, `Doyle`). Partial/prefix names are not supported by LibriVox's API.

## `genre` (type: `string`):

Browse audiobooks by LibriVox's genre taxonomy.

## `sinceDate` (type: `string`):

Return audiobooks LibriVox catalogued on or after this date, format `YYYY-MM-DD`. Required for `recent` mode.

## `bookIds` (type: `array`):

LibriVox numeric book/project IDs (e.g. `52`, `47`). Find them via the other modes' `bookId` output field.

## `language` (type: `string`):

Only emit audiobooks recorded in this language.

## `minDurationSeconds` (type: `integer`):

Drop audiobooks shorter than this many seconds.

## `maxDurationSeconds` (type: `integer`):

Drop audiobooks longer than this many seconds.

## `copyrightYearMin` (type: `integer`):

Drop books first copyrighted before this year.

## `copyrightYearMax` (type: `integer`):

Drop books first copyrighted after this year.

## `containsKeyword` (type: `string`):

Only emit audiobooks whose title, description, author name, or genre contains this keyword (case-insensitive).

## `maxItems` (type: `integer`):

Hard cap on the number of records emitted.

## Actor input object example

```json
{
  "mode": "search",
  "titleQuery": "Pride and Prejudice",
  "genre": "Poetry",
  "sinceDate": "2026-05-01",
  "bookIds": [],
  "language": "",
  "maxItems": 30
}
```

# Actor output Schema

## `audiobooks` (type: `string`):

Dataset containing all scraped LibriVox audiobooks.

# 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 = {
    "mode": "search",
    "titleQuery": "Pride and Prejudice",
    "genre": "Poetry",
    "sinceDate": "2026-05-01",
    "bookIds": [],
    "maxItems": 30
};

// Run the Actor and wait for it to finish
const run = await client.actor("crawlerbros/librivox-audiobook-scraper").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 = {
    "mode": "search",
    "titleQuery": "Pride and Prejudice",
    "genre": "Poetry",
    "sinceDate": "2026-05-01",
    "bookIds": [],
    "maxItems": 30,
}

# Run the Actor and wait for it to finish
run = client.actor("crawlerbros/librivox-audiobook-scraper").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 '{
  "mode": "search",
  "titleQuery": "Pride and Prejudice",
  "genre": "Poetry",
  "sinceDate": "2026-05-01",
  "bookIds": [],
  "maxItems": 30
}' |
apify call crawlerbros/librivox-audiobook-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,crawlerbros/librivox-audiobook-scraper"
        }
    }
}

```

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/uka3gM0Hae7d0cSfF/builds/ZKB1s9zbuiU4dQrQw/openapi.json
