# Books to Scrape API

> Books to Scrape returns catalog listings, prices, and stock status as a workflow and API.

Books to Scrape returns the 20 products on the first catalog page, in page order, with no input required. Get first catalog products returns each product’s title, detail page link, displayed price, and stock status.

- Page: https://fous.com/workflows/books-to-scrape
- Handle: `@books-to-scrape`
- Category: [Commerce](https://fous.com/workflows/category/commerce)
- Source website: https://books.toscrape.com
- Last verified: Sep 29, 2026
- Fous is not affiliated with Books to Scrape.

## Methods

### Get first catalog products

Operation `get_first_catalog_products`, version 1. 1 credit per call.

Get the 20 products shown on the first Books to Scrape catalog page, with each product’s page link, full title, displayed price, and stock status. Prices are synthetic.

**Input**

No input.

**Output**

| Field | Type | Example | Description |
|---|---|---|---|
| `products` | array |  | The 20 products displayed on the first catalog page, in page order. |
| `products[].name` | string | `"A Light in the Attic"` | Complete product title from its catalog listing. |
| `products[].product_url` | string | `"https://books.toscrape.com/catalogue/a-light-in-the-attic_1000/index.html"` | Absolute URL of the book’s detail page. |
| `products[].availability` | string | `"In stock"` | Displayed stock status without extra whitespace. |
| `products[].published_price` | string | `"£51.77"` | Price exactly as displayed, including currency symbol. |

**Example input**

```json
{}
```

**Example output**

```json
{
  "products": [
    {
      "name": "A Light in the Attic",
      "product_url": "https://books.toscrape.com/catalogue/a-light-in-the-attic_1000/index.html",
      "availability": "In stock",
      "published_price": "£51.77"
    },
    {
      "name": "Tipping the Velvet",
      "product_url": "https://books.toscrape.com/catalogue/tipping-the-velvet_999/index.html",
      "availability": "In stock",
      "published_price": "£53.74"
    },
    {
      "name": "Soumission",
      "product_url": "https://books.toscrape.com/catalogue/soumission_998/index.html",
      "availability": "In stock",
      "published_price": "£50.10"
    }
  ]
}
```

## Quick start

Call the API with a Fous API key (`FOUS_API_KEY`).

```bash
# First set your key: export FOUS_API_KEY='YOUR_FOUS_API_KEY'
: "${FOUS_API_KEY:?Set FOUS_API_KEY before running this example}"

curl 'https://api.fous.com/v1/query' \
  --fail-with-body --silent --show-error --max-time 120 \
  -H "Authorization: Bearer $FOUS_API_KEY" \
  -H 'Content-Type: application/json' \
  --data-raw '{
  "api": "@books-to-scrape",
  "visibility": "public",
  "operation": "get_first_catalog_products",
  "version": 1,
  "input": {},
  "response": {
    "format": "json"
  }
}'
```

```python
# Save as fous.py and run with python3 fous.py. No packages needed.
# First set your key: export FOUS_API_KEY='YOUR_FOUS_API_KEY'
import json
import os
import urllib.error
import urllib.request

api_key = os.environ.get("FOUS_API_KEY")
if not api_key:
    raise RuntimeError("Set FOUS_API_KEY before running this example")

body = json.loads("{\n  \"api\": \"@books-to-scrape\",\n  \"visibility\": \"public\",\n  \"operation\": \"get_first_catalog_products\",\n  \"version\": 1,\n  \"input\": {},\n  \"response\": {\n    \"format\": \"json\"\n  }\n}")
request = urllib.request.Request(
    "https://api.fous.com/v1/query",
    data=json.dumps(body).encode("utf-8"),
    headers={
        "Authorization": f"Bearer {api_key}",
        "Content-Type": "application/json",
    },
    method="POST",
)
try:
    with urllib.request.urlopen(request, timeout=120) as response:
        result = json.load(response)
except urllib.error.HTTPError as error:
    raise RuntimeError(f"HTTP {error.code}: {error.read().decode('utf-8', errors='replace')}") from error
if result.get("success") is False:
    raise RuntimeError(result.get("error", {}).get("message", "Request failed"))
print(json.dumps(result["data"]["output"], indent=2))
```

```typescript
// Save as fous.mts and run with npx tsx fous.mts.
// First set your key: export FOUS_API_KEY='YOUR_FOUS_API_KEY'
const apiKey = process.env.FOUS_API_KEY;
if (!apiKey) throw new Error("Set FOUS_API_KEY before running this example");

const response = await fetch("https://api.fous.com/v1/query", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${apiKey}`,
    "Content-Type": "application/json",
  },
  signal: AbortSignal.timeout(120_000),
  body: JSON.stringify({
  "api": "@books-to-scrape",
  "visibility": "public",
  "operation": "get_first_catalog_products",
  "version": 1,
  "input": {},
  "response": {
    "format": "json"
  }
}),
});
type ApiResult = { success: boolean; data?: { output: unknown }; error?: { message: string } };
const result: ApiResult = await response.json();
if (!response.ok || result.success === false) {
  throw new Error(result.error?.message ?? `HTTP ${response.status}`);
}
if (!result.data) throw new Error("Missing API response data");
console.log(result.data.output);
```

## Use cases

- Review book titles and displayed prices
- Check displayed stock status for listed books
- Collect book detail page links
- Compare the first-page catalog listings

## FAQ

### Is Fous affiliated with Books to Scrape?

No. Fous is not affiliated with Books to Scrape. This workflow reads the public books.toscrape.com website and returns its data.

### How much does it cost?

Each run costs 1 credit. With pay-as-you-go, a credit costs 1¢; monthly plans cost less per credit.

### Do I need a Books to Scrape account?

No. You only need a Fous account.

### How current is the data?

Fous gets the data from books.toscrape.com when you run it; repeating the same request within a day may return the saved result. Fous checks this workflow automatically; it last passed a check on Sep 29, 2026.

### What books appear on the first catalog page?

Get first catalog products returns the 20 listed products in page order, with their full titles.

### What price and stock status are displayed for each book?

Get first catalog products returns each displayed price and stock status. Prices are synthetic.

## Related

- [All Commerce workflows](https://fous.com/workflows/category/commerce)
