# Open Library Books Search (`grit-77/open-library-books`) Actor

Open Library book metadata scraper for catalog enrichment. Search books or look up ISBNs and Open Library IDs; export titles, authors, editions and source links as JSON.

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

## Pricing

$1.00 / 1,000 books

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## What's an Apify Actor?

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

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

## How to integrate an Actor?

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

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

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

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

# README

## Open Library Books Search

Open Library books scraper returns book and edition metadata for searches, ISBNs, and Open Library identifiers. Open Library books API results include titles, authors, publication details, covers, and source links when available.

### Input example

```json
{
  "isbns": [
    "9780261103344"
  ],
  "maxItems": 20
}
```

The input keys and allowed values follow [input_schema.json](.actor/input_schema.json).

### Output fields

| Field | Type | Example or excerpt from sample |
|---|---|---|
| `status` | string | `"ok"` |
| `title` | string | `"The Hobbit"` |
| `subtitle` | string or null | `"or There and Back Again"` |
| `workId` | string | `"OL27482W"` |
| `editionId` | string or null | `"OL10236414M"` |
| `openLibraryUrl` | string | `"https://openlibrary.org/books/OL10236414M"` |
| `authorNames` | array | `["J.R.R. Tolkien"]` |
| `authorIds` | array | `["OL26320A"]` |
| `authors` | array | `[{"authorId": "OL26320A", "name": "J.R.R. Tolkien", "url": "https://openlibrary.org/a…` |
| `firstPublishYear` | integer or null | `1965` |
| `firstPublishDate` | string or null | `"January 1938"` |
| `publishDate` | string or null | `"2011"` |
| `description` | string | `"Bilbo Baggins is a hobbit who enjoys a comfortable, unambitious life, rarely travell…` |
| `subjects` | array | `["Fantasy"]` |
| `languages` | array | `["eng"]` |
| `publishers` | array | `["HarperCollins Publishers"]` |
| `isbn10` | array | `["0261103342"]` |
| `isbn13` | array | `["9780261103344"]` |
| `editionCount` | integer | `482` |
| `numberOfPages` | integer or null | `96` |
| `editions` | array | `[{"editionId": "OL62623719M", "workId": "OL27482W", "title": "Hobit ali Tja in spet n…` |
| `editionsTruncated` | boolean | `true` |
| `errors` | array | `[]` |
| `coverId` | integer | `10522108` |
| `coverUrl` | string | `"https://covers.openlibrary.org/b/id/10522108-L.jpg?default=false"` |
| `coverUrls` | object | `{"S": "https://covers.openlibrary.org/b/id/10522108-S.jpg?default=false", "M": "https…` |
| `source` | string | `"isbn"` |
| `input` | string | `"9780261103344"` |
| `sourceUrls` | array | `["https://openlibrary.org/isbn/9780261103344.json", "https://openlibrary.org/works/OL…` |
| `retrievedAt` | string | `"2026-10-05T14:57:43.535747+00:00"` |

### Output example

Trimmed from [sample_output.json](sample_output.json); omitted fields remain available in the dataset.

```json
{
  "status": "ok",
  "title": "The Hobbit",
  "subtitle": "or There and Back Again",
  "workId": "OL27482W",
  "editionId": "OL10236414M",
  "openLibraryUrl": "https://openlibrary.org/books/OL10236414M",
  "authorNames": [
    "J.R.R. Tolkien"
  ]
}
```

### Limits and source behavior

- The actor uses [official Open Library APIs](https://openlibrary.org/developers/api) for search, works, editions, ISBN resolution and authors. It retrieves metadata, not book files or reader accounts.
- Starts of API requests are globally spaced at least 1.05 seconds apart, including retries. Timeout, malformed JSON, rate-limit and server failures receive up to three retries after the initial attempt, with exponential delay and bounded `Retry-After` handling. Permanent missing resources become error rows.
- Optional author, work or edition enrichment failures leave the resolved book usable and record the failure in `errors`. Missing optional fields remain empty.
- Cover URLs use [the Covers API's documented format](https://openlibrary.org/dev/docs/api/covers) with `default=false`; a missing image returns 404. Image URLs are not downloaded or checked by this actor. Cover availability and usage rights depend on the source.
- Search is paginated until the output cap or source exhaustion. Editions are a sample in the API's order; `editionsTruncated` indicates omissions. The catalog is community maintained, so titles, dates, ISBN associations and descriptions can be incomplete or inconsistent.
- Use modest result caps for API queries. Open Library recommends [data dumps for bulk collection](https://openlibrary.org/developers/dumps); this actor is not a whole-catalog export tool.

### FAQ

**What are the output limits?** `maxItems` caps records and errors; optional authors and editions may be incomplete when source requests fail.

**Do I need a proxy or login?** Public Open Library endpoints need no login or proxy.

**How is this priced?** Proposed pay per event: $0.001 for each resolved, deduplicated `book` row. Error rows and suppressed duplicates are uncharged. These are proposals in [PRICING.md](PRICING.md); the owner must configure Store billing.

**How are rate limits handled?** The client limits concurrent requests with `concurrency` and retries transient responses with backoff and `Retry-After`.

**How fresh is the data?** Open Library records are community maintained and can be incomplete or change. `retrievedAt` shows collection time; original source URLs remain in each row.

### Use with AI agents / MCP

After the actor is published, connect your agent to the [Apify MCP server](https://docs.apify.com/integrations/mcp) with an Apify API token. Use `call-actor` with the published actor identifier and the JSON input shown above. Read the returned dataset with `get-dataset-items`; the run response itself contains status and storage IDs, not the result rows. Alternatively, use the [Apify API](https://docs.apify.com/api/v2) to start a run and read its default dataset. Keep the actor input bounded with `maxItems`, and inspect source links and any error fields before using results in an answer.

# Actor input Schema

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

Open Library search text or field query, e.g. title:the hobbit or author:tolkien language:eng. Leave empty for direct lookups.

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

ISBN-10 or ISBN-13 strings. Hyphens/spaces are removed, check digits validated, duplicates removed. Preserve leading zeros by using strings.

## `workIds` (type: `array`):

Open Library work IDs such as OL27482W or /works/OL27482W.

## `editionIds` (type: `array`):

Open Library edition IDs such as OL10236414M or /books/OL10236414M.

## `authorIds` (type: `array`):

Author IDs such as OL26320A or /authors/OL26320A. Returns work rows from each author's bibliography; does not emit standalone author rows.

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

Global cap across all sources, including error rows. Nested editions are limited separately and do not add book events.

## `includeWorkDetails` (type: `boolean`):

Fetch work descriptions, subjects and first publication dates. Edition-specific titles and ISBNs remain attached to their edition.

## `includeAuthors` (type: `boolean`):

Include published author names, biographies and dates. Author IDs remain available when disabled.

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

Fetch a bounded sample of editions for each work. They may be in different languages and do not inherit search filters. Adds requests but no separate event charge.

## `editionsLimit` (type: `integer`):

Maximum nested editions per book when includeEditions is enabled. editionsTruncated indicates additional or unavailable editions.

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

Ordering for query searches. Direct ID/ISBN lookups keep input order.

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

Optional two-letter preference such as en or fr. This ranks results; to require a language use a query term such as language:eng.

## `concurrency` (type: `integer`):

Maximum in-flight requests and book tasks. All request starts, including retries, remain globally spaced at least 1.05 seconds apart.

## Actor input object example

```json
{
  "query": "title:the hobbit",
  "maxItems": 100,
  "includeWorkDetails": true,
  "includeAuthors": true,
  "includeEditions": false,
  "editionsLimit": 5,
  "sort": "relevance",
  "language": "",
  "concurrency": 3
}
```

# Actor output Schema

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

Download the book results and per-item error rows as dataset items.

# 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": "title:the hobbit"
};

// Run the Actor and wait for it to finish
const run = await client.actor("grit-77/open-library-books").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": "title:the hobbit" }

# Run the Actor and wait for it to finish
run = client.actor("grit-77/open-library-books").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": "title:the hobbit"
}' |
apify call grit-77/open-library-books --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,grit-77/open-library-books"
        }
    }
}
```

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/9zkIlq1XGR2aOrUei/builds/q0DfabhdZF36HMGTN/openapi.json
