# Open Library Books Scraper (`zerobreak/open-library-books-scraper`) Actor

Open Library Books Scraper is a Python tool designed to extract book metadata, ISBNs, authors, publishers, subjects, and cover links from Open Library. It exports structured bibliographic data into clean CSV or JSON formats for library archiving, data enrichment, and research.

- **URL**: https://apify.com/zerobreak/open-library-books-scraper.md
- **Developed by:** [ZeroBreak](https://apify.com/zerobreak) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.99 / 1,000 results

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?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Open Library Scraper: Book Search, ISBN Lookup, Authors, Ratings and Covers (Free)

<p align="center">
  <img src="https://imgur.com/Qh8WrCL.png" alt="Open Library Scraper" width="800" />
</p>

Collect book and author metadata for catalogs, research, reading lists, and recommendation datasets. Search by keyword, title, author, subject, or ISBN. Depending on the selected mode, results can include editions, publishers, page counts, ISBNs, subjects, ratings, reading-shelf counts, author biographies, and cover image URLs.

No API key is required. Cover images are represented by URLs; the actor does not download the image files.

### What This Book Metadata Scraper Extracts

- **Book search:** Titles, authors, publication years, edition counts, ISBNs, publishers, and cover information.
- **Subject search:** Book records associated with a subject, such as `science_fiction`.
- **ISBN lookup:** Edition details associated with an ISBN.
- **Work details:** Descriptions, subjects, ratings, reading-shelf counts, and optional edition lists.
- **Author records:** Author names, biographies, birth and death dates, external identifiers, and photo URLs.
- **Error records:** Invalid inputs, missing records, and failed requests.

Search and subject results represent works, while ISBN lookups return edition-level records. Author mode returns author records and can optionally include a page of the author's works.

The `bookTitle` field contains the book title and is also duplicated into `title`. Similarly, `bookDescription` is duplicated into `description` when available.

### Use Cases

- **Bookstore and e-commerce catalogs:** Enrich ISBNs with titles, publishers, page counts, and cover links.
- **Publisher and author research:** Compare edition counts, ratings, and reading-shelf activity.
- **Libraries and education:** Create reading lists from subjects such as science fiction.
- **Recommendation systems:** Build datasets containing work identifiers, subjects, and author references.
- **Author research:** Collect biographies, birth and death dates, and external author identifiers.

### Input Parameters

| Parameter | Type | Default | Description |
|---|---|---|---|
| `mode` | string | `search` | Operation mode: `search`, `isbn`, `works`, `authors`, or `subjects`. |
| `query` | string | `the lord of the rings` | Search keyword or author name in author mode. |
| `title` | string | Empty | Title filter for book searches. |
| `author` | string | Empty | Author filter for book searches. |
| `subject` | string | Empty | Search filter or subject slug for subject mode, such as `science_fiction`. |
| `language` | string | Empty | Three-letter language code, such as `eng`. |
| `sort` | string | Empty | Sort order: `new`, `old`, `random`, or `key`. Blank preserves relevance order. |
| `isbns` | array | Empty | ISBN-10 or ISBN-13 values. Dashes are removed. |
| `ids` | array | Empty | Work or author identifiers, such as `OL45804W` or `OL26320A`, or supported Open Library URLs. |
| `includeEditions` | boolean | `false` | Attach up to 20 editions to each work. |
| `includeRatings` | boolean | `true` | Include ratings and reading-shelf counts where supported. Skipped for search and subject runs requesting more than 200 items. |
| `includeAuthorWorks` | boolean | `false` | Attach one page of an author's works. |
| `maxItems` | integer | `100` | Maximum number of output rows. Hard cap: 5,000. |
| `requestsPerSecond` | number | `2` | Request rate. Identified clients may use up to 3 requests per second. |
| `contactEmail` | string | Maintainer contact | Optional contact email used in the request identification. Leave blank to use the default User-Agent. |
| `timeoutSecs` | integer | `300` | Maximum run duration in seconds. |
| `requestTimeoutSecs` | integer | `30` | Maximum duration for an individual request. |

### Example Inputs

#### 1. Search for Books

```json
{
  "mode": "search",
  "query": "the lord of the rings",
  "maxItems": 20,
  "includeRatings": true,
  "requestsPerSecond": 2,
  "timeoutSecs": 300,
  "requestTimeoutSecs": 30
}
```

#### 2. Look Up an ISBN

```json
{
  "mode": "isbn",
  "isbns": ["9780441172719"]
}
```

#### 3. Retrieve Work Details

```json
{
  "mode": "works",
  "ids": ["OL893414W"],
  "includeEditions": true,
  "includeRatings": true
}
```

#### 4. Search for an Author

```json
{
  "mode": "authors",
  "query": "Frank Herbert",
  "includeAuthorWorks": true,
  "maxItems": 20
}
```

#### 5. Search by Subject

```json
{
  "mode": "subjects",
  "subject": "science_fiction",
  "maxItems": 100
}
```

### Output Examples

Results are saved to the default dataset. The following examples illustrate the output structure.

#### Book Search Result

```json
{
  "recordKind": "book",
  "workKey": "/works/OL893414W",
  "workId": "OL893414W",
  "url": "OPEN_LIBRARY_WORK_URL",
  "bookTitle": "Dune",
  "title": "Dune",
  "authors": ["Frank Herbert"],
  "firstPublishYear": 1965,
  "editionCount": 101,
  "isbns": ["9780441172719"],
  "publishers": ["Ace Books"],
  "coverId": 980253,
  "coverUrl": "BOOK_COVER_IMAGE_URL",
  "query": "dune"
}
```

#### Work Details

A work-detail record can include `bookDescription`, subjects, ratings, and reading-shelf counts, along with an optional edition list.

#### ISBN Lookup

An edition record can include:

- `editionKey`
- `isbn10`
- `isbn13`
- `publishDate`
- `numberOfPages`
- `identifiers`

#### Author Record

An author record can include:

- `authorKey`
- `name`
- `bio`
- `remoteIds`
- `photoUrl`
- Birth and death dates, when available

External identifiers may include Wikidata, VIAF, ISNI, Goodreads, and Amazon identifiers when present in the source record.

#### Error Record

If a book cannot be found, the actor can return an error record such as:

```json
{
  "recordKind": "error",
  "input": "9789999999999",
  "error": "NOT_FOUND",
  "statusCode": 404
}
```

### Output Fields

| Field | Type | Description |
|---|---|---|
| `recordKind` | string | Record type, such as `book`, `author`, or `error`. |
| `workKey` | string | Work key, such as `/works/OL45804W`. |
| `workId` | string | Work identifier without the path prefix. |
| `bookTitle` | string | Book title; also stored in `title`. |
| `title` | string | Duplicate title field for convenient dataset access. |
| `authors` | array | Author names associated with a work. |
| `firstPublishYear` | integer | First publication year, when available. |
| `editionCount` | integer | Number of editions associated with the work. |
| `isbns` | array | Up to 20 ISBNs from a search record. |
| `publishers` | array | Publisher names, capped at 10 in search results. |
| `subjects` | array | Associated subjects, capped at 30 in search results. |
| `coverId` | integer | Cover identifier. Invalid cover IDs such as `-1` are discarded. |
| `coverUrl` | string | Cover image URL. The image file is not downloaded. |
| `bookDescription` | string | Work description; also stored in `description` when available. |
| `ratings` | object | Average rating, rating count, and star-count breakdown, when available. |
| `shelves` | object | Counts for want-to-read, currently-reading, and already-read shelves. |
| `authorKey` | string | Author identifier. |
| `bio` | string or object | Author biography, when available. |
| `remoteIds` | object | External identifiers, such as Wikidata, VIAF, ISNI, Goodreads, and Amazon IDs. |
| `photoUrl` | string | Author photo URL, when available. |
| `url` | string | Reference URL for the associated work or record. |
| `error` | string | Error type, such as `NOT_FOUND`, `HTTP_<code>`, or `INVALID_INPUT`. |
| `statusCode` | integer | HTTP status code for a failed request, when available. |

The exact fields depend on the selected mode and the information available for each record.

### Rate Limits and Usage Restrictions

The actor is designed to respect the source's request limits and avoid unnecessary traffic.

- The default request rate is 2 requests per second.
- Identified clients may use up to 3 requests per second.
- Anonymous clients may be limited to approximately 1 request per second.
- HTTP 403 and 429 responses trigger a 60-second wait, followed by a reduction in request rate.
- Repeated requests to the same URL are cached during a run.
- The actor does not rotate proxies or distribute requests across multiple IP addresses.
- The maximum output is 5,000 rows per run.
- Runs stop when the configured item limit or timeout is reached.
- Ratings enrichment is skipped for search and subject runs requesting more than 200 items.
- Cover URLs are stored as references; image files are not downloaded.

For full-catalog research, use the source's designated bulk-data distribution options rather than treating individual requests as a bulk-download mechanism.

### How It Works

1. **Validates the input:** Checks the selected mode and required search terms, ISBNs, identifiers, or subject.
2. **Controls request frequency:** Uses a single request limiter to keep traffic within the configured rate.
3. **Caches repeated requests:** Avoids fetching the same URL repeatedly during a run.
4. **Collects results:** Processes search pages or subject results until the item limit, available result count, or timeout is reached.
5. **Enriches records:** Retrieves optional ratings, shelf counts, edition lists, or author works where requested.
6. **Handles errors:** Converts missing records and invalid inputs into error rows so the run can continue.
7. **Removes duplicate works:** Skips work keys that have already produced an output row.
8. **Saves results:** Writes book, author, and error records to the dataset.

### FAQ

#### Does this actor require an API key?

No. The actor does not require an API key. It identifies requests with a User-Agent and can include a contact email.

#### How many books can one run collect?

The default limit is 100 rows, and the maximum is 5,000. This limit is intentional to avoid excessive requests.

#### Why is a large search slow?

Search responses can take approximately 2–4 seconds. The actor also applies request delays to respect rate limits. Optional ratings and shelf enrichment can require additional requests, so it is skipped for search and subject runs requesting more than 200 items.

#### Can I bulk-download cover images?

No. The dataset contains cover URLs, not downloaded image files. Use the cover links according to the source's applicable usage restrictions.

#### What happens when an ISBN does not exist?

The actor records a `NOT_FOUND` error with the available status code and continues processing the remaining inputs.

#### Why are some fields missing?

Not every work, edition, or author has complete metadata. Missing values reflect unavailable source information and are not fabricated.

#### What does `iaIdentifiers` mean?

Some book records include Internet Archive identifiers that can reference scanned material. These identifiers are metadata references; the actor does not automatically download scanned books.

### Trademark Notice

Open Library, Internet Archive, and their related names, logos, and trademarks belong to their respective owners. Their use in this documentation is solely to identify the data source and does not imply affiliation, sponsorship, endorsement, or partnership.

### Disclaimer

This actor is an independent tool and is not affiliated with, endorsed by, sponsored by, or officially associated with Open Library or the Internet Archive.

### Is Web Scraping Legal?

Collecting information that is already public is generally legal. Scraping is not the same thing as hacking, and there is no single law that bans it. The limits are the usual ones: do not break into accounts, do not take private or confidential data, and be careful with personal data and copyrighted works. A site's terms can also restrict how you access it. Facts such as a public name, price, or rating are not the same thing as republishing someone's article or photo.

This actor collects information from public pages. It does not log in and it does not bypass access controls.

# Actor input Schema

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

Search books, look up ISBNs, fetch one work, search authors, or list books in a subject.

## `query` (type: `string`):

Keyword for book search, or the author name when mode is authors and no author ID is set.

## `title` (type: `string`):

Book title filter for search mode. Sent as the title parameter on search.json.

## `author` (type: `string`):

Author name filter for search mode. Sent as the author parameter on search.json.

## `subject` (type: `string`):

Search filter, or the subject slug in subjects mode, such as science_fiction.

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

Three-letter code such as eng. Passed to search.json as the language parameter. This filter was not re-checked on 2026-10-12.

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

Sort for search.json. Leave blank for relevance. new, old, random, and key are documented sort values.

## `isbns` (type: `array`):

ISBN-10 or ISBN-13 values for isbn mode. Dashes are stripped. Each ISBN calls the verified /isbn/{isbn}.json endpoint.

## `ids` (type: `array`):

Work IDs such as OL45804W, author IDs such as OL26320A, or full openlibrary.org URLs.

## `includeEditions` (type: `boolean`):

On works mode, attach up to 20 editions from /works/{id}/editions.json. Off by default to keep the run small.

## `includeRatings` (type: `boolean`):

Fetch /ratings.json and /bookshelves.json. In search mode this stays off when max results is above 200, because those are two extra calls per book.

## `includeAuthorWorks` (type: `boolean`):

On authors mode, attach one page of works from /authors/{id}/works.json. Off by default.

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

Free cap 5,000. Open Library asks not to use the API for bulk downloads. Use their monthly dumps for a full catalog.

## `requestsPerSecond` (type: `number`):

Open Library allows 3 requests per second for identified clients. Default is 2. A 403 or 429 waits 60 seconds, then cuts this rate in half.

## `contactEmail` (type: `string`):

Open Library asks for a contact in the User-Agent. Leave blank to use BigiByteResearch/1.0 (https://bigibyte.com; research@bigibyte.com).

## `timeoutSecs` (type: `integer`):

Stop the run after this many seconds. Default 300. Maximum 3600.

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

Per-request timeout. Open Library search often takes 2 to 4 seconds, so the default is 30.

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

Optional. Open Library forbids spreading requests across many IPs, so this stays off. If you enable it, the actor uses one proxy URL for the whole run and does not rotate.

## Actor input object example

```json
{
  "mode": "search",
  "query": "the lord of the rings",
  "title": "Dune",
  "author": "Frank Herbert",
  "subject": "science_fiction",
  "language": "eng",
  "sort": "",
  "isbns": [
    "9780441172719"
  ],
  "ids": [
    "OL45804W",
    "OL26320A"
  ],
  "includeEditions": false,
  "includeRatings": true,
  "includeAuthorWorks": false,
  "maxItems": 100,
  "requestsPerSecond": 2,
  "timeoutSecs": 300,
  "requestTimeoutSecs": 30,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `books` (type: `string`):

Work key, book title, first publish year, edition count, and cover URL.

## `authors` (type: `string`):

Author name, key, birth and death dates, and work count.

## `errors` (type: `string`):

Inputs that failed, with the error code and HTTP status.

## `dataset` (type: `string`):

Every row from the run, without a table view applied.

# 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 = {
    "query": "the lord of the rings",
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("zerobreak/open-library-books-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 = {
    "query": "the lord of the rings",
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("zerobreak/open-library-books-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 '{
  "query": "the lord of the rings",
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call zerobreak/open-library-books-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,zerobreak/open-library-books-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/d6uej1POZT01wWIrf/builds/meGMp2nljOB8RrcyT/openapi.json
