# Goodreads Scraper (`datapilot/goodreads-scraper`) Actor

It extracts title, author, ISBN, publisher, publish year, pages, categories, ratings, description, cover image, and preview link. Outputs structured JSON for catalogs, apps, and research use.

- **URL**: https://apify.com/datapilot/goodreads-scraper.md
- **Developed by:** [Data Pilot](https://apify.com/datapilot) (community)
- **Categories:** Other, Social media
- **Stats:** 2 total users, 0 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 scraped results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

📚 **Goodreads Scraper** is a powerful Apify Actor designed to discover, track, and collect book data directly from Goodreads' own book pages using fast HTTP requests. This tool provides comprehensive **Goodreads Scraper** intelligence including book title, author name, rating, description, and cover image for any accessible Goodreads book page. Whether you're building a reading list app, tracking book catalog data, or conducting literary research, the Goodreads Scraper delivers actionable **Goodreads Scraper** insights efficiently.

With direct HTML parsing, targeted CSS selector extraction, anti-blocking pacing, and reliable Apify Dataset delivery, the Goodreads Scraper ensures comprehensive **Goodreads Scraper** coverage across any list of book URLs. It focuses on key **Goodreads Scraper** signals including rating, author, and description, making it an essential tool for book cataloging and literary content research.

***

### 📋 Table of Contents

- [Features](#-features)
- [Data Source](#-data-source)
- [How It Works](#-how-it-works)
- [Input](#-input)
- [Output](#-output)
- [Technical Stack](#-technical-stack)
- [Data Fields](#-data-fields-explained)
- [Use Cases](#-use-cases)
- [Quick Start](#-quick-start)
- [Configuration](#-configuration)
- [Performance](#-performance)
- [Important Notes](#-important-notes)
- [License & Legal](#-license--legal)

***

### 🔥 Features

- **Fast HTTP Scraping** – Uses parsing for lightweight, direct access to each **Goodreads Scraper** target page without a full browser.
- **Targeted CSS Selector Extraction** – Pulls title, author, rating, description, and cover image using precise, page-specific selectors.
- **Batch URL Processing** – Scrapes any number of Goodreads book URLs in a single run.
- **Anti-Blocking Pacing** – Applies a randomized delay between requests to reduce the chance of being rate-limited or blocked.
- **Proxy Group & Country Targeting** – Supports configurable Apify proxy groups and country-specific proxy routing.
- **Graceful Error Handling** – Skips a failing URL or HTTP error without stopping the whole run.
- **Real-Time Dataset Push** – Pushes each **Goodreads Scraper** record to Apify Dataset immediately after extraction.
- **Missing-Field Safety** – Returns empty strings or `null` for any field that isn't found rather than failing the whole record.

***

### 📊 Data Source

#### **Goodreads Public Book Pages**

- **Authority**: Goodreads' own public-facing book detail pages
- **Access Method**: Direct HTTP GET requests via , with \` parsing the rendered HTML
- **Coverage**: Any publicly accessible Goodreads book page URL provided as input
- **Data**: Title, author, rating, description, and cover image scraped directly from the page's HTML structure
- **Access**: Public pages, no API key required
- **Update Frequency**: Reflects each book page's current live state at time of run

***

### ⚙️ How It Works

The Goodreads Scraper accepts a list of Goodreads book URLs and fetches each page directly via HTTP, optionally routed through an Apify proxy with configurable group and country settings. For each successfully fetched page, the Actor parses the HTML with BeautifulSoup and extracts the book title from the page's `h1`, the author name from the contributor link element, the rating from the rating statistics element, the description from its data-testid container, and the cover image URL from the responsive image element. Each extracted record is mapped into a consistent output structure — including fixed `language` and `currency` defaults — and pushed to the Apify Dataset immediately. A randomized delay between requests helps reduce the chance of blocking across a batch run.

**Key Processing Steps:**

1. **Input Parsing** – Accept a list of **Goodreads Scraper** target URLs
2. **Proxy Setup** – Configure Apify proxy with optional group and country targeting
3. **URL Loop** – Iterate through each provided Goodreads book URL
4. **Page Fetch** – Request the book page's HTML with the configured headers and proxy
5. **Status Check** – Skip and log any URL that doesn't return a successful HTTP status
6. **HTML Parsing** – Parse the response with BeautifulSoup using the \`\` parser
7. **Field Extraction** – Pull title, author, rating, description, and cover image via CSS selectors
8. **Output Mapping** – Build the final record, including fixed language/currency defaults and source labeling
9. **Dataset Push** – Push each successfully extracted record to the Dataset immediately
10. **Anti-Blocking Pacing** – Sleep a random 2–4 seconds between requests

**Key Benefits:**

- Pull **Goodreads Scraper** book data for any list of URLs without manual lookups
- Get a consistent, ready-to-use record structure for every book, even with partial data
- Batch-process large URL lists with built-in pacing to reduce blocking
- Feed reading list apps, book cataloging tools, or literary research pipelines
- Automate recurring **Goodreads Scraper** checks as book pages are updated

***

### 📥 Input

The Actor accepts the following input parameters:

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `urls` | array | *(required)* | List of Goodreads book page URLs to scrape. |
| `proxyConfiguration` | object | *(none)* | Optional Apify proxy configuration, with `proxyGroups` and `apifyProxyCountry` sub-fields. |

**Example Input:**

```json
{
  "urls": [
    "https://www.goodreads.com/book/show/5470.1984",
    "https://www.goodreads.com/book/show/2657.To_Kill_a_Mockingbird"
  ],
  "proxyConfiguration": {
    "proxyGroups": ["RESIDENTIAL"],
    "apifyProxyCountry": "US"
  }
}
```

**Scrape a Single Book:**

```json
{
  "urls": ["https://www.goodreads.com/book/show/5470.1984"]
}
```

**Scrape Without Proxy:**

```json
{
  "urls": ["https://www.goodreads.com/book/show/5470.1984"],
  "proxyConfiguration": {}
}
```

***

### 📤 Output

The Actor pushes **Goodreads Scraper** records with the following structure:

| Field | Type | Description |
|-------|------|-------------|
| `title` | string | The book's title |
| `authorName` | string | Name of the book's author |
| `rating` | string/null | The book's average rating as displayed on the page |
| `description` | string | The book's description/summary text |
| `language` | string | Fixed default value: `"ENG"` |
| `currency` | string | Fixed default value: `"USD"` |
| `cover_image` | string | URL of the book's cover image |
| `source` | string | Always `"Goodreads"` |
| `preview_link` | string | The original book page URL |
| `url` | string | The original book page URL |

**Example Goodreads Scraper Record:**

```json
{
  "title": "1984",
  "authorName": "George Orwell",
  "rating": "4.19",
  "description": "Among the seminal texts of the 20th century...",
  "language": "ENG",
  "currency": "USD",
  "cover_image": "https://images-na.ssl-images-amazon.com/...",
  "source": "Goodreads",
  "preview_link": "https://www.goodreads.com/book/show/5470.1984",
  "url": "https://www.goodreads.com/book/show/5470.1984"
}
```

***

### 🧰 Technical Stack

- **HTTP Client:** \` for direct HTTP access to Goodreads book pages
- **HTML Parsing:** `with the` parser for fast, precise CSS selector extraction
- **Randomization:** `random` for anti-blocking request pacing
- **Async:** `asyncio` for the Actor's run loop and pacing delays
- **Proxy:** Apify Proxy with configurable groups and country targeting
- **Logging:** Apify Actor logging system
- **Platform:** Apify Actor serverless environment

***

### 📊 Data Fields Explained

#### **Book Identity**

- **title**: The book's title as shown on its Goodreads page
- **authorName**: The name of the book's author or contributor

#### **Content Details**

- **rating**: The book's average Goodreads rating, if available
- **description**: The book's summary/description text
- **cover\_image**: Direct link to the book's cover image

#### **Metadata**

- **language / currency**: Fixed default values included in every record for downstream schema consistency
- **source**: Always `"Goodreads"`, identifying the data origin
- **preview\_link / url**: The original book page URL, included under both field names

***

### 🎯 Use Cases

- **Reading List Apps** – Populate book details automatically from a list of Goodreads URLs
- **Book Cataloging** – Build an internal database of titles, authors, and ratings
- **Literary Research** – Study ratings and descriptions across a curated set of books
- **Content Aggregation** – Feed book summaries and cover art into a content platform
- **Academic Research** – Study public book metadata patterns at scale
- **Comparison Tools** – Gather consistent book data for side-by-side comparisons

***

### 🚀 Quick Start

#### **1. Prepare Input**

Go to Apify Console and enter:

```json
{
  "urls": ["https://www.goodreads.com/book/show/5470.1984"]
}
```

#### **2. Run the Actor**

Click **Start**. The Actor will:

- Fetch each book page's HTML directly
- Parse title, author, rating, description, and cover image
- Map the results into a consistent output structure
- Push each record to the Dataset immediately

#### **3. Monitor Progress**

Console shows:

```
Scraping: https://www.goodreads.com/book/show/5470.1984
```

#### **4. View & Download Results**

- **Results Tab**: All **Goodreads Scraper** records
- **Export**: JSON, CSV, Excel, or HTML
- **Filter**: By author or rating
- **API Access**: Available via the Apify API

***

### ⚙️ Configuration

Single book URL:

```json
{
  "urls": ["https://www.goodreads.com/book/show/5470.1984"]
}
```

Multiple book URLs:

```json
{
  "urls": [
    "https://www.goodreads.com/book/show/5470.1984",
    "https://www.goodreads.com/book/show/2657.To_Kill_a_Mockingbird"
  ]
}
```

Country-specific proxy:

```json
{
  "urls": ["https://www.goodreads.com/book/show/5470.1984"],
  "proxyConfiguration": {
    "proxyGroups": ["RESIDENTIAL"],
    "apifyProxyCountry": "GB"
  }
}
```

***

### 📈 Performance

#### **Processing Speed**

- One HTTP request per book URL, no browser rendering required
- 2–4 second randomized delay between requests to reduce blocking
- Faster than browser-based scraping since no rendering engine is launched

#### **Resource Usage**

- Memory: Low, since no browser instance is launched
- Network: One request per book URL
- Proxy: One proxy connection per request, if configured

***

### ⚠️ Important Notes

#### **Legal & Compliance**

- **Public Data Only**: Retrieves only publicly visible **Goodreads Scraper** data exposed on the book's own page
- **Privacy & ToS**: Collecting book data may be subject to Goodreads' Terms of Service — use only for legitimate purposes
- **Legal**: Not legal advice — consult qualified professionals before using this data for compliance-sensitive decisions

#### **Data Quality**

- **Freshness**: Reflects each book page's live state at time of run
- **Completeness**: Fields depend on Goodreads' current page structure; a redesign may cause selectors to miss some fields
- **Accuracy**: Sourced directly from Goodreads' own rendered pages
- **Verification**: Cross-check high-stakes figures against the live Goodreads website

#### **Best Practices**

- Provide full, direct book page URLs rather than search or list pages
- Use a residential proxy with country targeting for the most reliable access
- Re-run periodically to track changes in ratings or descriptions over time
- Expect `rating` to occasionally return `null` if the page structure doesn't match the expected selector
- Monitor for Goodreads page redesigns, which may require selector updates over time

***

### 📄 License & Legal

**Terms of Use:**

- Use for legitimate research, cataloging, and personal reading-list purposes
- Respect Goodreads' Terms of Service
- Use **Goodreads Scraper** data responsibly and in compliance with applicable laws

**Disclaimer:**
Goodreads Scraper is provided as-is for research and cataloging purposes. Users are responsible for compliance with Goodreads' ToS and all applicable laws. This is not legal advice.

***

### ⚖️ Goodreads Scraper Excellence

This Actor is optimized for **Goodreads Scraper** research with:

- ✅ Fast, direct HTTP scraping — no browser overhead
- ✅ Targeted CSS selector extraction
- ✅ Anti-blocking randomized pacing
- ✅ Consistent output structure with missing-field safety
- ✅ Real-time Dataset push
- ✅ Production-ready code

# Actor input Schema

## `urls` (type: `array`):

List of Goodreads book page URLs to scrape.

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

Recommended to bypass Goodreads bot detection.

## Actor input object example

```json
{
  "urls": [
    "https://www.goodreads.com/book/show/40605285-atomic-habits"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# 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 = {
    "urls": [
        "https://www.goodreads.com/book/show/40605285-atomic-habits"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("datapilot/goodreads-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 = { "urls": ["https://www.goodreads.com/book/show/40605285-atomic-habits"] }

# Run the Actor and wait for it to finish
run = client.actor("datapilot/goodreads-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 '{
  "urls": [
    "https://www.goodreads.com/book/show/40605285-atomic-habits"
  ]
}' |
apify call datapilot/goodreads-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,datapilot/goodreads-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/9ijhARdu6dNUNNRuO/builds/oxPGbnZjzZGxqLtxw/openapi.json
