# Books Fixture (`saffo/books-fixture`) Actor

Book titles, prices, stock and ratings from the category pages of books.toscrape.com, a public sandbox site made for scraping practice.

- **URL**: https://apify.com/saffo/books-fixture.md
- **Developed by:** [Anton Mendelson](https://apify.com/saffo) (community)
- **Categories:** E-commerce
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.00 / 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

## Book Scraper for books.toscrape.com: Titles, Prices and Stock

Book titles, prices, stock and ratings from the category pages of books.toscrape.com, a public sandbox site made for scraping practice.

### What it does

Reads category pages of [books.toscrape.com](https://books.toscrape.com), follows their next-page links and saves one result per book: title, price, currency, stock state, star rating and the book's page URL. The data is read live at run time.

books.toscrape.com is a sandbox made for scraping practice, so this actor is a safe, cheap way to try pay-per-event scraping, or to test a data pipeline or an AI agent's tool call before you point it at a real catalogue.

### Who it is for

- Developers who need a small, predictable dataset to test an import, a pipeline or a dashboard.
- Builders of AI agents who want a cheap tool call to try the Apify MCP server.
- Anyone learning how a pay-per-event actor works and what it charges.

### How to use it

1. Open the actor on [Apify Store](https://apify.com/saffo/books-fixture) and go to its Input tab.
2. Fill in `startUrls`; every other field has a default (see Input below).
3. Click **Start**. The run ends at the limits below, or earlier at the "Maximum cost per run" you set.
4. When the run ends, open the Output tab: view the results as a table, or export them as JSON, CSV or Excel.

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `startUrls` | array | required | Category pages of books.toscrape.com (the actor follows their next-page links). |
| `maxItems` | integer | `100` | Stop after this many results. At most 1000 per run. |

Example input:

```json
{}
```

### Output

Each result is one dataset item:

| Field | Type | Description |
|---|---|---|
| `url` | string | Web address of the item: its own page, or the page it was read from. |
| `title` | string | Title of the item as shown on the page. |
| `price` | number or null | Price as a number, in `currency`; null when the page shows none. |
| `currency` | string or null | ISO 4217 currency code of `price`, for example USD. |
| `inStock` | boolean | True when the listing shows the book as in stock. |
| `rating` | integer or null | Star rating (1–5) shown on the listing; null when missing. |
| `fetchedAt` | string | When the page was read (ISO 8601, UTC). |

Example output (real items from a test run):

```json
[
  {
    "url": "https://books.toscrape.com/catalogue/sharp-objects_997/index.html",
    "title": "Sharp Objects",
    "price": 47.82,
    "currency": "GBP",
    "inStock": true,
    "rating": 4,
    "fetchedAt": "2026-11-04T21:53:08.784Z"
  },
  {
    "url": "https://books.toscrape.com/catalogue/in-a-dark-dark-wood_963/index.html",
    "title": "In a Dark, Dark Wood",
    "price": 19.63,
    "currency": "GBP",
    "inStock": true,
    "rating": 1,
    "fetchedAt": "2026-11-04T21:53:08.784Z"
  }
]
```

Download the dataset as JSON, CSV or Excel, or read it through the Apify API.

### Pricing

Pay per event: a small fee per run plus a fee per result saved. Platform usage is included in these prices.

| Event | When it is charged | Free plan | Bronze plan | Silver plan | Gold plan | Platinum plan | Diamond plan |
|---|---|---|---|---|---|---|---|
| Run started (`run-started`) | Flat fee once per run; covers starting the run. | $0.0625 | $0.05 | $0.045 | $0.04 | $0.04 | $0.04 |
| Result (`result-item`) | One result saved to the dataset. | $0.0063 | $0.005 | $0.0045 | $0.004 | $0.004 | $0.004 |

Example (lowest plan price): a run that saves 100 results costs $0.04 + 100 × $0.004 = **$0.44**. That is $4.00 per 1,000 results plus $0.04 per run. You pay only for results saved to the dataset; set "Maximum cost per run" in the run options and the actor stops there.

### Limits

- One run saves at most 1,000 results and loads at most 60 pages. Larger jobs: split the start URLs over several runs.
- Default memory 512 MB; no proxy.
- When a limit is reached, the run ends normally and keeps every result saved so far; the status message says which limit it was.

The site has 1,000 books in 50 categories; it reads listing pages only, not the book detail pages.

### Use with AI agents

AI agents can call this actor as a tool through the Apify MCP server. Add it to an MCP client (Claude Desktop, Cursor, VS Code and others):

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com/?tools=saffo/books-fixture"
    }
  }
}
```

Or call it over HTTP and get the results in the response:

```sh
curl -X POST "https://api.apify.com/v2/acts/saffo~books-fixture/run-sync-get-dataset-items" \
  -H "Authorization: Bearer $APIFY_TOKEN" -H "Content-Type: application/json" \
  -d '{}'
```

### FAQ

#### How much does it cost?

You pay per event: from $0.004 per result plus $0.04 per run. The Pricing section lists the price on every Apify plan. Platform usage is included, and the run stops at the maximum cost per run you set.

#### Can I use it from an AI agent or my own code?

Yes. Add it to any MCP client through the Apify MCP server, or call the Apify API; the examples under Use with AI agents show both. Results come back as JSON.

#### How many results can one run return?

Up to 1,000 results from at most 60 pages. For more, split the input over several runs.

#### Does it collect personal data?

No. It saves only the fields listed under Output and leaves out names, e-mail addresses, phone numbers and profiles of private persons.

#### Is this real shop data?

No. books.toscrape.com is a demo shop built for scraping practice: its prices and ratings were assigned at random and have no real meaning. Use the actor to try pay-per-event scraping or to test a pipeline, not for market research.

#### Why are the prices in pounds?

The sandbox lists every book in GBP. The actor saves the price as a number and the currency code next to it, so your code never parses a "£" sign.

### Support

Open an issue on the actor's Issues tab.

### Changelog

#### 0.6 (2026-11-05)

- README: the search keyword in the title, how-to steps and a FAQ; SEO title and description for search engines.

#### 0.5 (2026-11-05)

- Maintenance release.

#### 0.4 (2026-11-05)

- Maintenance release.

#### 0.1 (2026-11-04)

- First release.

# Changelog

This Actor's version history is a separate document: https://apify.com/saffo/books-fixture/changelog.md

# Actor input Schema

## `startUrls` (type: `array`):

Category pages of books.toscrape.com (the actor follows their next-page links).

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

Stop after this many results. At most 1000 per run.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://books.toscrape.com/catalogue/category/books/travel_2/index.html"
    }
  ],
  "maxItems": 100
}
```

# Actor output Schema

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

No description

# 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 = {
    "startUrls": [
        {
            "url": "https://books.toscrape.com/catalogue/category/books/travel_2/index.html"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("saffo/books-fixture").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 = { "startUrls": [{ "url": "https://books.toscrape.com/catalogue/category/books/travel_2/index.html" }] }

# Run the Actor and wait for it to finish
run = client.actor("saffo/books-fixture").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 '{
  "startUrls": [
    {
      "url": "https://books.toscrape.com/catalogue/category/books/travel_2/index.html"
    }
  ]
}' |
apify call saffo/books-fixture --silent --output-dataset

```

## MCP server setup

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

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/xFgCXlAvfhSMQnAat/builds/mFDjzcenpf9tl8Jgd/openapi.json
