# Goodreads Book Scraper (`sian.agency/goodreads-book-scraper`) Actor

Scrape books from Goodreads by search or book page — title, author, average rating, ratings & reviews count, ISBN/ISBN13, ASIN, pages, publisher, language, genres, series and description. Clean JSON/CSV, no code.

- **URL**: https://apify.com/sian.agency/goodreads-book-scraper.md
- **Developed by:** [SIÁN OÜ](https://apify.com/sian.agency) (community)
- **Categories:** E-commerce, Business, Other
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.40 / 1,000 book overview extracteds

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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use 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

## Goodreads Book Scraper — Ratings, ISBN, Genres & Reviews 📚

[![SIÁN Agency Store](https://img.shields.io/badge/Store-SI%C3%81N%20Agency-1AE392)](https://apify.com/sian.agency?fpr=sian) [![Store-Taobao Tmall Product Scraper](https://img.shields.io/badge/Store-Taobao%20%26%20Tmall%20Scraper-FF4F00)](https://apify.com/sian.agency/taobao-tmall-product-scraper?fpr=sian) [![Store-Smart Idealista Scraper](https://img.shields.io/badge/Store-Idealista%20Scraper-E60023)](https://apify.com/sian.agency/smart-idealista-scraper?fpr=sian) [![Store-Xiaohongshu RedNote Scraper](https://img.shields.io/badge/Store-Xiaohongshu%20Scraper-FF2442)](https://apify.com/sian.agency/xiaohongshu-rednote-scraper?fpr=sian)

#### 🎉 Turn the world's largest book catalog into clean, structured data — search results or full book records, no code
##### Built for publishers, booksellers, librarians, data teams and book-app builders who need ratings, ISBNs, genres and reviews at scale

---

### 📋 Overview

**Pull book data straight from Goodreads** — search any topic, author or title and get a clean dataset of books, or fetch full records for exact titles. Built for anyone who needs reliable, structured book metadata without writing a scraper.

**Why thousands of professionals choose us:**
- ✅ **Two extraction modes**: a fast, cheap *overview* of search results, or a rich *detail* record per book — pick what you need
- ⚡ **45+ data points per book**: title, author, average rating, ratings & reviews count, ISBN/ISBN13, ASIN, pages, publisher, language, genres, series and full description
- 🎯 **Search the way you want**: by free-text query, by pasted Goodreads search URL, or by exact book id
- 💰 **Pay-per-result pricing**: only charged for the books you actually extract — no subscriptions, no waste
- 💎 **Clean JSON/CSV/Excel out**: ready for spreadsheets, BI tools, databases and recommendation engines
- ✨ **No code, no account, no API key** — run it from the Apify Console or call it from your own app

---

### ✨ Features

- 📚 **Catalog search**: extract every book that matches a query or search URL, across multiple result pages
- 📖 **Full book records**: ISBN13, ASIN, page count, publisher, language, edition format, genres, series and description
- ⭐ **Ratings & reviews**: average rating, total ratings and total reviews for benchmarking and ranking
- 🏷️ **Genre & series tagging**: the Goodreads genre shelves and series position for each book
- 🖼️ **Cover images**: thumbnail and full-resolution cover URLs for every title
- 🆔 **Precise targeting**: fetch exact titles by Goodreads book id or `/book/show/` URL
- 🔢 **Tier-aware limits**: free trial up to 25 books per run; unlimited on the paid tier
- 📄 **Built-in run report**: an HTML summary of every run with a sample of the data

---

### 🎬 Quick Start

Choose a scrape mode (`overview` or `detail`), tell it what to search, and run. Results land in the Apify dataset, ready to export.

```bash
curl -X POST "https://api.apify.com/v2/acts/sian.agency~goodreads-book-scraper/runs?token=YOUR_TOKEN" \
-H 'Content-Type: application/json' \
-d '{"scrapeMode": "overview", "searchMode": "byQuery", "query": "dune", "maxResults": 50}'
````

***

### 🚀 Getting Started (3 Simple Steps)

#### Step 1: Pick your mode

Choose **Overview** for fast search rows, or **Detail** for full book records.

#### Step 2: Tell it what to fetch

Enter a search query, paste Goodreads search URLs, or list exact book ids.

#### Step 3: Run and export

Start the run and download the results as JSON, CSV or Excel.

**That's it! In a couple of minutes, you'll have:**

- A clean dataset of books with ratings and metadata
- ISBNs, genres, series and descriptions ready for enrichment
- Cover images and direct Goodreads links for every title

***

### 📥 Input Configuration

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `scrapeMode` | string | No | `overview` (search rows) or `detail` (full book records) |
| `searchMode` | string | No | `byQuery`, `bySearchUrl`, or `byBookId` (detail only) |
| `query` | string | No | Free-text search term (used with `byQuery`) |
| `searchUrls` | array | No | One or more Goodreads search URLs (used with `bySearchUrl`) |
| `bookIds` | array | No | Book ids or `/book/show/<id>` URLs (used with `byBookId`) |
| `maxResults` | integer | No | Max books to return (FREE: 25, PAID: unlimited) |
| `maxPages` | integer | No | Max search-result pages to walk per query/URL |

**Example — search overview:**

```json
{
  "scrapeMode": "overview",
  "searchMode": "byQuery",
  "query": "atomic habits",
  "maxResults": 100
}
```

**Example — full details by book id:**

```json
{
  "scrapeMode": "detail",
  "searchMode": "byBookId",
  "bookIds": ["5907", "44767458"]
}
```

***

### 📤 Output

Results are saved to the Apify dataset with **20+ fields** including:

| Field | Type | Description |
|-------|------|-------------|
| `title` | string | Book title |
| `author` | string | Primary author |
| `avg_rating` | number | Average Goodreads rating (0–5) |
| `ratings_count` | number | Number of ratings |
| `reviews_count` | number | Number of text reviews (detail mode) |
| `isbn13` | string | ISBN-13 (detail mode, when available) |
| `isbn` | string | ISBN-10 (detail mode, when available) |
| `asin` | string | Amazon ASIN (detail mode, when available) |
| `num_pages` | number | Page count (detail mode) |
| `publication_year` | number | Publication year (detail mode) |
| `publisher` | string | Publisher (detail mode) |
| `language` | string | Book language (detail mode) |
| `genres` | array | Genre/shelf tags (detail mode) |
| `series` | string | Series name (detail mode) |
| `description` | string | Synopsis (detail mode) |
| `cover_image` | string | Full-resolution cover image URL |
| `url` | string | Canonical Goodreads book URL |

**Example:**

```json
{
  "id": 5907,
  "title": "The Hobbit, or There and Back Again",
  "author": "J.R.R. Tolkien",
  "avg_rating": 4.28,
  "ratings_count": 3800000,
  "reviews_count": 75000,
  "isbn13": "9780618260300",
  "num_pages": 366,
  "publication_year": 2002,
  "publisher": "Houghton Mifflin",
  "language": "English",
  "genres": ["Fantasy", "Classics", "Fiction", "Adventure"],
  "series": "Middle Earth",
  "series_position": "1",
  "description": "In a hole in the ground there lived a hobbit...",
  "cover_image": "https://.../5907.jpg",
  "url": "https://www.goodreads.com/book/show/5907"
}
```

***

### 💼 Use Cases & Examples

#### 1. Competitive Publishing Research

**Publishers and indie authors benchmarking a genre or comp titles.**

**Input:** A genre or topic query (e.g. `space opera`)
**Output:** Every matching book with ratings, review counts and publication years
**Use:** Spot the best-performing titles and gaps in a category before you publish.

#### 2. Bookstore & Catalog Building

**Booksellers and book-app builders assembling a product catalog.**

**Input:** Search URLs for the shelves you stock
**Output:** Titles, authors, ISBNs, covers and descriptions
**Use:** Seed a storefront or recommendation engine with clean, structured book data.

#### 3. ISBN & Metadata Enrichment

**Data teams matching internal catalogs to canonical book metadata.**

**Input:** A list of Goodreads book ids
**Output:** ISBN13, ASIN, pages, publisher, language and genres per title
**Use:** Fill gaps in your library or e-commerce metadata in one run.

#### 4. Author & Series Tracking

**Researchers and fans mapping an author's bibliography or a series.**

**Input:** An author or series query
**Output:** Every book with series name and position
**Use:** Build a complete, ordered reading list or bibliography.

#### 5. Rating & Review Benchmarking

**Marketers and analysts ranking titles by reception.**

**Input:** A topic query across multiple pages
**Output:** Average rating, ratings count and reviews count per book
**Use:** Rank and compare titles by real reader sentiment at scale.

#### 6. Academic & Library Datasets

**Librarians and academics compiling reading datasets.**

**Input:** Subject queries or curated book-id lists
**Output:** Bibliographic records ready for analysis
**Use:** Power literature reviews, syllabi and library acquisitions.

***

### 🔗 Integration Examples

#### JavaScript/Node.js

```javascript
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_TOKEN' });

const run = await client.actor('sian.agency/goodreads-book-scraper').call({
  scrapeMode: 'overview',
  searchMode: 'byQuery',
  query: 'dune',
  maxResults: 50,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items[0]);
```

#### Python

```python
from apify_client import ApifyClient
client = ApifyClient('YOUR_TOKEN')

run = client.actor('sian.agency/goodreads-book-scraper').call(
    run_input={
        'scrapeMode': 'detail',
        'searchMode': 'byBookId',
        'bookIds': ['5907', '44767458'],
    }
)

for item in client.dataset(run['defaultDatasetId']).iterate_items():
    print(item)
```

#### cURL

```bash
curl -X POST 'https://api.apify.com/v2/acts/sian.agency~goodreads-book-scraper/runs?token=YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{"scrapeMode": "overview", "searchMode": "byQuery", "query": "atomic habits"}'
```

#### Automation Workflows (N8N / Zapier / Make)

1. **Trigger**: Schedule or webhook
2. **HTTP Request**: Call the actor API
3. **Process**: Handle the JSON book records
4. **Action**: Save to a database, sheet or recommendation engine

***

### 📊 Performance & Pricing

#### FREE Tier (Try It Now)

- **25 books** per run — full feature access, same quality
- No credit card required
- Perfect for testing and small projects

#### PAID Tier (Production Ready)

- **Unlimited** books per run
- Faster processing, no caps
- Pay-per-result: only charged for the books you extract

💰 **Transparent pricing** — a low per-book rate for fast search rows, and a slightly higher rate for full book records.

🔗 [View current pricing](https://apify.com/sian.agency/goodreads-book-scraper?fpr=sian)

***

### ❓ Frequently Asked Questions

**Q: How many books can I extract?**
A: FREE tier: 25 per run. PAID tier: unlimited.

**Q: What's the difference between overview and detail mode?**
A: Overview returns fast, cheap search rows (title, author, rating, ratings count, cover). Detail returns the full book record (ISBN, pages, publisher, genres, series, description and more).

**Q: Can I fetch specific books?**
A: Yes — use `byBookId` with detail mode and a list of Goodreads book ids or `/book/show/` URLs.

**Q: What output formats are available?**
A: JSON, CSV and Excel — export directly from the Apify dataset.

**Q: Does it work with private content?**
A: No — only publicly available book pages and search results are supported.

**Q: How fresh is the data?**
A: Every run fetches live data at the moment it runs.

***

### 🐛 Troubleshooting

**No books returned**

- Check your query spelling, or open the search on Goodreads to confirm it returns results
- For `byBookId`, make sure the ids are valid Goodreads book ids

**Some detail fields are empty**

- Not every book page lists an ISBN, ASIN or publisher — those fields are returned as `null` when Goodreads doesn't publish them

**Hit the free limit**

- The FREE tier is capped at 25 books per run. Upgrade to the paid tier for unlimited results.

***

### ⚖️ Is it legal to scrape data?

Our actors are ethical and do not extract any private user data, such as email addresses, gender, or location. They only extract what has been chosen to share publicly. We therefore believe that our actors, when used for ethical purposes by Apify users, are safe.

However, you should be aware that your results could contain personal data. Personal data is protected by the **GDPR** in the European Union and by other regulations around the world. You should not scrape personal data unless you have a legitimate reason to do so. If you're unsure whether your reason is legitimate, consult your lawyers.

You can also read Apify's blog post on the [legality of web scraping](https://blog.apify.com/is-web-scraping-legal/).

**Trademark notice:** *Goodreads* is a registered trademark of Goodreads, Inc. / Amazon.com, Inc. This actor is an independent tool and is **not** affiliated with, endorsed by, or sponsored by Goodreads or Amazon. It accesses only publicly available data and is provided for lawful research and data-analysis purposes.

***

### 🤝 Support

[![Telegram Support](https://img.shields.io/badge/Telegram-Support%20Group-0088cc?logo=telegram)](https://t.me/+vyh1sRE08sAxMGRi)

**Join our active support community**

- For issues or questions, open an issue in the actor's Issues tab
- Check the [SIÁN Agency Store](https://apify.com/sian.agency?fpr=sian) for more automation tools
- 📧 <apify@sian-agency.online>

***

**Built by [SIÁN Agency](https://www.sian-agency.online)** | **[More Tools](https://apify.com/sian.agency?fpr=sian)**

# Actor input Schema

## `scrapeMode` (type: `string`):

🔎 **OVERVIEW** — fast, cheap search rows: title, author, average rating, ratings count, cover. Best for building book lists at scale.

📖 **DETAIL** — full book records: ISBN/ISBN13, ASIN, pages, publisher, language, description, genres, series, publication year and reviews count. Best for metadata enrichment.

## `searchMode` (type: `string`):

How you tell the actor which books to fetch.

- **By query** — free-text search (e.g. `dune`).
- **By search URL** — paste one or more Goodreads `/search` URLs.
- **By book id** — exact Goodreads book ids or `/book/show/<id>` URLs (requires **Detail** scrape mode).

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

🔍 **BY QUERY:** free-text search term, exactly as you'd type it on Goodreads (e.g. `dune`, `stephen king`, `atomic habits`). Used when **Search mode** is *By query*.

## `searchUrls` (type: `array`):

🔗 **BY SEARCH URL:** paste one or more Goodreads search URLs (the page you land on after searching). Used when **Search mode** is *By search URL*.

💡 **TIP:** Click "Bulk edit" to paste one URL per line.

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

🆔 **BY BOOK ID:** exact Goodreads book ids (e.g. `5907`) or full `/book/show/<id>` URLs. Used when **Search mode** is *By book id* with **Detail** scrape mode.

💡 **TIP:** Click "Bulk edit" to paste one id or URL per line.

## `maxResults` (type: `integer`):

🔢 Maximum number of books to return.

**FREE users:** capped at 25 per run (free-trial courtesy).
**PAID users:** unlimited — set as high as you need.

## `maxPages` (type: `integer`):

📄 Maximum number of search-result pages to walk per query/URL (~20 books per page). Only applies to **By query** / **By search URL** modes.

## Actor input object example

```json
{
  "scrapeMode": "overview",
  "searchMode": "byQuery",
  "query": "dune",
  "searchUrls": [
    "https://www.goodreads.com/search?q=dune&tab=books"
  ],
  "bookIds": [
    "5907",
    "44767458"
  ],
  "maxResults": 100,
  "maxPages": 5
}
```

# Actor output Schema

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

The extracted Goodreads books — title, author, rating, ISBN, pages, genres, series and more.

## `scrapingSummary` (type: `string`):

HTML summary of the run — books extracted, pages fetched, failures and a sample.

# 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 = {
    "scrapeMode": "overview",
    "searchMode": "byQuery",
    "query": "dune",
    "searchUrls": [
        "https://www.goodreads.com/search?q=dune&tab=books"
    ],
    "bookIds": [
        "5907",
        "44767458"
    ],
    "maxResults": 100,
    "maxPages": 5
};

// Run the Actor and wait for it to finish
const run = await client.actor("sian.agency/goodreads-book-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 = {
    "scrapeMode": "overview",
    "searchMode": "byQuery",
    "query": "dune",
    "searchUrls": ["https://www.goodreads.com/search?q=dune&tab=books"],
    "bookIds": [
        "5907",
        "44767458",
    ],
    "maxResults": 100,
    "maxPages": 5,
}

# Run the Actor and wait for it to finish
run = client.actor("sian.agency/goodreads-book-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "scrapeMode": "overview",
  "searchMode": "byQuery",
  "query": "dune",
  "searchUrls": [
    "https://www.goodreads.com/search?q=dune&tab=books"
  ],
  "bookIds": [
    "5907",
    "44767458"
  ],
  "maxResults": 100,
  "maxPages": 5
}' |
apify call sian.agency/goodreads-book-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=sian.agency/goodreads-book-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Goodreads Book Scraper",
        "description": "Scrape books from Goodreads by search or book page — title, author, average rating, ratings & reviews count, ISBN/ISBN13, ASIN, pages, publisher, language, genres, series and description. Clean JSON/CSV, no code.",
        "version": "1.0",
        "x-build-id": "N2KCd5xBiDyqNsmDR"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/sian.agency~goodreads-book-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-sian.agency-goodreads-book-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/sian.agency~goodreads-book-scraper/runs": {
            "post": {
                "operationId": "runs-sync-sian.agency-goodreads-book-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/sian.agency~goodreads-book-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-sian.agency-goodreads-book-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "scrapeMode": {
                        "title": "📦 Scrape mode",
                        "enum": [
                            "overview",
                            "detail"
                        ],
                        "type": "string",
                        "description": "🔎 **OVERVIEW** — fast, cheap search rows: title, author, average rating, ratings count, cover. Best for building book lists at scale.\n\n📖 **DETAIL** — full book records: ISBN/ISBN13, ASIN, pages, publisher, language, description, genres, series, publication year and reviews count. Best for metadata enrichment.",
                        "default": "overview"
                    },
                    "searchMode": {
                        "title": "🎛️ Search mode",
                        "enum": [
                            "byQuery",
                            "bySearchUrl",
                            "byBookId"
                        ],
                        "type": "string",
                        "description": "How you tell the actor which books to fetch.\n\n- **By query** — free-text search (e.g. `dune`).\n- **By search URL** — paste one or more Goodreads `/search` URLs.\n- **By book id** — exact Goodreads book ids or `/book/show/<id>` URLs (requires **Detail** scrape mode).",
                        "default": "byQuery"
                    },
                    "query": {
                        "title": "🔍 Search query",
                        "type": "string",
                        "description": "🔍 **BY QUERY:** free-text search term, exactly as you'd type it on Goodreads (e.g. `dune`, `stephen king`, `atomic habits`). Used when **Search mode** is *By query*.",
                        "default": "dune"
                    },
                    "searchUrls": {
                        "title": "🔗 Goodreads search URLs",
                        "uniqueItems": true,
                        "type": "array",
                        "description": "🔗 **BY SEARCH URL:** paste one or more Goodreads search URLs (the page you land on after searching). Used when **Search mode** is *By search URL*.\n\n💡 **TIP:** Click \"Bulk edit\" to paste one URL per line.",
                        "default": [],
                        "items": {
                            "type": "string"
                        }
                    },
                    "bookIds": {
                        "title": "🆔 Book ids or /book/show URLs",
                        "uniqueItems": true,
                        "type": "array",
                        "description": "🆔 **BY BOOK ID:** exact Goodreads book ids (e.g. `5907`) or full `/book/show/<id>` URLs. Used when **Search mode** is *By book id* with **Detail** scrape mode.\n\n💡 **TIP:** Click \"Bulk edit\" to paste one id or URL per line.",
                        "default": [],
                        "items": {
                            "type": "string"
                        }
                    },
                    "maxResults": {
                        "title": "🔢 Max results",
                        "minimum": 1,
                        "type": "integer",
                        "description": "🔢 Maximum number of books to return.\n\n**FREE users:** capped at 25 per run (free-trial courtesy).\n**PAID users:** unlimited — set as high as you need.",
                        "default": 100
                    },
                    "maxPages": {
                        "title": "📄 Max search pages",
                        "minimum": 1,
                        "type": "integer",
                        "description": "📄 Maximum number of search-result pages to walk per query/URL (~20 books per page). Only applies to **By query** / **By search URL** modes.",
                        "default": 5
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
