# Thalia.de Scraper: Books, Prices, ISBNs & Reviews (`abotapi/thalia-de-scraper`) Actor

Scrape Thalia.de books, eBooks, audiobooks, toys and stationery. Search by keyword or category, browse Schnäppchen deals, or paste product and listing URLs. Get prices, original prices, discounts, ISBN/EAN, author, publisher, format, ratings and full reviews.

- **URL**: https://apify.com/abotapi/thalia-de-scraper.md
- **Developed by:** [Abot API](https://apify.com/abotapi) (community)
- **Categories:** E-commerce, Automation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 76.3% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.50 / 1,000 product 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?

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

## Thalia Books & Media Scraper

Pull rich product data from Thalia (thalia.de), Germany's largest books & media retailer — books, eBooks, audiobooks, toys and stationery. Search by keyword and/or category with real site filters, browse Thalia's own Schnäppchen (sale) collection, or paste product, category, search, and sale links directly. Every record includes current price, the strike-through original price with computed discount when an item is on sale, ISBN/EAN, author/publisher/format, and a full customer review history with rating breakdown.

### Why This Scraper?

- **Was-price and discount, structured from the real Schnäppchen facet.** When a product is on sale, both the current price and the strike-through original price come back, plus the computed discount amount and percentage — never fabricated.
- **A dedicated Specials mode.** `specialsOnly` maps to Thalia's own price-reduction facet, store-wide or scoped to a keyword/category, mirroring thalia.de/themenwelten/sale/.
- **Rich bibliographic identity.** ISBN and EAN/GTIN, full author list, publisher, and format/binding (Taschenbuch, gebundene Ausgabe, ePUB, MP3, Hörbuch-Download, ...) — every high-value field a basic scrape drops.
- **Full technical specifications, not a wall of text.** Each product's "Produktdetails" table (pages, language, release date, dimensions, weight, colour — varies per category) comes back as clean key/value pairs, plus the full breadcrumb category path.
- **Format-variant matrix.** Siblings of the same title in other formats (e.g. the Hardcover and eBook editions of one novel) come back as a linked matrix.
- **Complete review history.** Overall rating, review count, a full 1-to-5 star rating breakdown, and every individual review with author, date, rating, format, title, and body text — Thalia's own native reviews, no third-party vendor.
- **Two ways in.** Keyword search with real filters (format, price range, availability, specials, sort), or paste any product/category/search/sale URL and let pagination continue automatically.
- **Optional export to your apps.** Send results into Notion, Linear, Airtable, or any Apify MCP connector alongside the dataset.

### Data You Get

| Field | Example value |
|---|---|
| productId | `A1000000001` |
| title | `Sample Novel Title` |
| authors | `["Sample Author"]` |
| url | `https://www.thalia.de/shop/home/artikeldetails/A1000000001` |
| price / currency | `12.99`, `EUR` |
| originalPrice | `19.99` |
| discountAmount / discountPercent | `7.0`, `35.0` |
| isOnSpecial | `true` |
| promoLabel | `- 35%` |
| format | `Buch (Taschenbuch)` |
| categoryPath | `["Buch (dtsch)", "Bücher", "Romane & Erzählungen"]` |
| availabilityText / availabilityStatus | `Sofort lieferbar`, `gruen` |
| rating / reviewCount | `4.6`, `215` |
| image | `https://images.thalia.media/-/BF2000-2000/.../sample-cover.jpeg` |
| isbn / ean | `978-1-000-00000-0`, `9781000000000` |
| specifications *(fetchDetails)* | `{"Verlag": "Sample Verlag", "Seitenzahl": "320", "Erscheinungsdatum": "16.07.2024", "Maße (L/B/H)": "21,1/13,7/3,2 cm"}` |
| variants *(fetchDetails)* | `[{"format": "Hardcover", "url": "https://.../"}, {"format": "Taschenbuch", "url": "https://.../"}]` |
| images *(fetchDetails)* | `["https://images.thalia.media/-/BF2000-2000/.../sample-1.jpeg", "..."]` |
| description *(fetchDetails)* | `Sample blurb text describing the book.` |
| reviews.averageRating / reviews.totalReviewCount | `4.6`, `215` |
| reviews.ratingDistribution | `[{"rating": 5, "count": 155}, {"rating": 4, "count": 47}, {"rating": 3, "count": 10}]` |
| reviews.items\[] | `[{"reviewId": "2546014", "author": "Sample User", "authorLocation": "aus Bern", "rating": 5, "date": "21.07.2025", "format": "eBook (ePUB 3)", "title": "Sample title", "body": "Sample review text."}]` |

> Sample shape: values above are illustrative placeholders, not from a live product.

#### Specials, was-price & discount

Thalia's sale surface is a single real facet — **Schnäppchen** (price-reduced) — not a multi-tier promo taxonomy. `specialsOnly: true` scrapes that facet directly (store-wide, or scoped to a keyword/category); pasting the `/themenwelten/sale/` URL in `url` mode reaches the same collection. On any item that is actually reduced, `originalPrice`/`discountAmount`/`discountPercent`/`promoLabel` are populated straight from the site's own strike-through price and badge; on a full-price item they are `null` — never fabricated.

### How to Use

**Basic keyword search**

```json
{
  "mode": "search",
  "searchTerm": "krimi",
  "maxItems": 20
}
```

**Search narrowed by category, format and price, with specials**

```json
{
  "mode": "search",
  "searchTerm": "krimi",
  "category": "3",
  "einband": ["Taschenbuch"],
  "minPrice": 5,
  "maxPrice": 20,
  "specialsOnly": true,
  "sortBy": "sfpa",
  "maxItems": 30
}
```

**Category browse with full detail and review enrichment**

```json
{
  "mode": "search",
  "category": "3",
  "fetchDetails": true,
  "fetchReviews": true,
  "maxReviewsPerProduct": 0,
  "maxItems": 50
}
```

**Paste product, category, search, or sale links**

```json
{
  "mode": "url",
  "urls": [
    "https://www.thalia.de/shop/home/artikeldetails/A1000000001",
    "https://www.thalia.de/kategorie/romane-erzaehlungen-3/",
    "https://www.thalia.de/themenwelten/sale/"
  ],
  "maxItems": 40
}
```

### Input Parameters

| Parameter | Type | Default | Description |
|---|---|---|---|
| `mode` | string | `search` | `search` (keyword/category with filters) or `url` (paste links). |
| `searchTerm` | string | - | Free-text keyword, title, author, or ISBN for search mode. |
| `category` | string | - | A category id, e.g. `3`. Narrows a keyword search or browses a whole category alone. |
| `specialsOnly` | boolean | `false` | Only Schnäppchen (sale) items — real strike-through price + discount. |
| `einband` | array | `[]` | Only these exact binding/format values, e.g. `Taschenbuch`, `ePUB 3`. |
| `minPrice` / `maxPrice` | integer | - | Price range in EUR. |
| `availability` | string | \`\` (any) | `GL` (lieferbar), `SL` (sofort lieferbar), or `VB` (vorbestellbar). |
| `sortBy` | string | `sfmd` | `sfmd` (best match), `sfpa`/`sfpd` (price asc/desc), `sfea`/`sfed` (release date asc/desc), `sfsd` (top rated). |
| `urls` | array | sample URL | Product, category, search, or sale links for URL mode. |
| `fetchDetails` | boolean | `false` | Adds ISBN/EAN, full author list, publisher, description, flattened specifications, breadcrumb path, media gallery, and the format-variant matrix. |
| `fetchReviews` | boolean | `true` | Fetches each product's full review history. |
| `maxReviewsPerProduct` | integer | `20` | Cap on reviews per product; `0` = all. |
| `maxPages` | integer | unlimited | Cap on result pages per search/URL entry. |
| `maxItems` | integer | `20` | Cap on total products; `0` = unlimited. |
| `proxy` | object | Apify default | Connection configuration. |
| `mcpConnectors` | array | `[]` | Optional MCP connectors to also receive results. |
| `notionParentPageUrl` | string | - | Required only when a Notion connector is selected. |
| `maxNotifyListings` | integer | `50` | Cap on items sent to each connector. |

### Output Example

```json
{
  "productId": "A1000000001",
  "title": "Sample Novel Title",
  "authors": ["Sample Author"],
  "url": "https://www.thalia.de/shop/home/artikeldetails/A1000000001",
  "price": 4.99,
  "currency": "EUR",
  "originalPrice": 9.99,
  "discountAmount": 5.0,
  "discountPercent": 50.0,
  "isOnSpecial": true,
  "promoLabel": "- 50%",
  "format": "eBook (ePUB 3)",
  "categoryPath": ["Ebooks", "eBooks", "Krimis & Thriller"],
  "availabilityText": "Sofort per Download lieferbar",
  "availabilityStatus": "gruen",
  "rating": 4.6,
  "reviewCount": 215,
  "isbn": "978-1-000-00000-0",
  "specifications": {
    "Format": "ePUB 3",
    "Verlag": "Sample Verlag",
    "Seitenzahl": "320 (Printausgabe)",
    "Erscheinungsdatum": "16.07.2024"
  },
  "variants": [
    { "format": "Hardcover", "url": "https://www.thalia.de/shop/home/artikeldetails/A1000000002" },
    { "format": "Taschenbuch", "url": "https://www.thalia.de/shop/home/artikeldetails/A1000000003" }
  ],
  "images": ["https://images.thalia.media/-/BF2000-2000/sample/sample-cover.jpeg"],
  "reviews": {
    "averageRating": 4.6,
    "totalReviewCount": 215,
    "ratingDistribution": [
      { "rating": 5, "count": 155 },
      { "rating": 4, "count": 47 },
      { "rating": 3, "count": 10 }
    ],
    "items": [
      {
        "reviewId": "2546014",
        "author": "Sample User",
        "authorLocation": "aus Bern",
        "rating": 5,
        "date": "21.07.2025",
        "format": "eBook (ePUB 3)",
        "title": "Sample review title",
        "body": "Sample review text describing the reading experience."
      }
    ]
  }
}
```

### Send results into your apps (MCP connectors)

Optionally pipe results into an app you already use through a Model Context Protocol connector. Authorize a connector once under your account's Integrations settings, then select it in the input; for Notion, also set the parent page. Each connector receives a condensed, human-readable summary per item (a title plus key fields), not the full JSON record; the complete data always stays in the dataset.

### A Note on Access

Running this actor requires an active account with default proxy access, which is included on every plan. A residential connection is optional and only recommended for very large or sustained runs on the free tier.

# Actor input Schema

## `mode` (type: `string`):

'search' finds products by keyword and/or category with Thalia's own filters, including Schnäppchen (sale) items. 'url' scrapes any product, category, search-result, or sale page URL you paste, walking pagination forward automatically.

## `searchTerm` (type: `string`):

Free-text keyword, title, author, or stichwort, e.g. 'krimi' or 'fantasy roman'. Combine with Category below to narrow, or leave empty and set only Category (and/or Specials only) to browse a whole department.

## `category` (type: `string`):

A Thalia category id, e.g. '3' (Romane & Erzählungen) or '4893' (eBooks). Find it as the trailing number in a category page URL: thalia.de/kategorie/<name>-<id>/. Narrows a keyword search, or browses the whole category when Search keyword is left empty. Search mode only: URL mode reads this from the link you paste.

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

Paste one or more Thalia product pages (/shop/home/artikeldetails/<id>), category pages (/kategorie/<name>-<id>/), search-result pages (/suche?sq=<term>), or the sale page (/themenwelten/sale/). Pagination continues forward automatically from any page number already in the URL. The keyword and category fields are ignored here. The fields in the Filters and sort section still apply to a pasted listing, category, search or specials URL.

## `specialsOnly` (type: `boolean`):

Only return items currently on sale (Thalia's own 'Schnäppchen' price-reduction facet): a real strike-through original price + discount. Combine with a keyword and/or category, or leave those empty to browse all current sale items (mirrors thalia.de/themenwelten/sale/). Applies in BOTH search mode and URL mode: the listing request is rebuilt for a pasted listing, category, search or specials URL, so the filter is sent with it. It does not narrow a pasted product URL, which returns that one product.

## `einband` (type: `array`):

Only return this exact binding/format, e.g. 'Taschenbuch', 'gebundene Ausgabe', 'ePUB 3', 'MP3', 'Hörbuch-Download'. Match the exact value as shown on the site (visible in each result's 'format' field). Leave empty for every format. Applies in BOTH search mode and URL mode: the listing request is rebuilt for a pasted listing, category, search or specials URL, so the filter is sent with it. It does not narrow a pasted product URL, which returns that one product.

## `minPrice` (type: `integer`):

Only return products priced at or above this amount. Applies in BOTH search mode and URL mode: the listing request is rebuilt for a pasted listing, category, search or specials URL, so the filter is sent with it. It does not narrow a pasted product URL, which returns that one product.

## `maxPrice` (type: `integer`):

Only return products priced at or below this amount. Applies in BOTH search mode and URL mode: the listing request is rebuilt for a pasted listing, category, search or specials URL, so the filter is sent with it. It does not narrow a pasted product URL, which returns that one product.

## `availability` (type: `string`):

Narrow by delivery/availability status. Applies in BOTH search mode and URL mode: the listing request is rebuilt for a pasted listing, category, search or specials URL, so the filter is sent with it. It does not narrow a pasted product URL, which returns that one product.

## `sortBy` (type: `string`):

Order of the returned results. Applies in BOTH search mode and URL mode: the listing request is rebuilt for a pasted listing, category, search or specials URL, so the filter is sent with it. It does not narrow a pasted product URL, which returns that one product.

## `fetchDetails` (type: `boolean`):

Adds ISBN/EAN, full author list, publisher, description, flattened technical specifications (pages, language, release date, dimensions — varies per product), full breadcrumb category path, media gallery, and the format-variant matrix (e.g. Hardcover/Taschenbuch/eBook siblings of the same title). Current price, was-price/discount and rating are already included without this toggle on search/category results.

## `fetchReviews` (type: `boolean`):

Fetch each product's full review history: overall rating, review count, 1-5 star rating breakdown, and per-review author/date/rating/title/body. Products with no reviews simply return an empty list.

## `maxReviewsPerProduct` (type: `integer`):

Cap on reviews fetched per product when 'Fetch reviews' is on. 0 = all available reviews.

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

Stop after this many result pages per search/category/URL entry. Leave empty for as many pages as needed (bounded by Max products total).

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

Hard cap on total products returned across every search/category/URL entry. 0 = unlimited (still bounded by Max pages per search).

## `proxy` (type: `object`):

The default connection works on every Apify plan, including the free tier. A residential connection is optional and only needed for very large or sustained runs.

## `mcpConnectors` (type: `array`):

Optionally send the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. Authorize a connector once under Apify -> Settings -> Integrations, then select it here. The connector receives a condensed, human-readable summary per item (title + key fields), not the full JSON; the complete record stays in the dataset. Leave empty to skip. Supported: Notion (https://mcp.notion.com/mcp), Linear (https://mcp.linear.app/sse), Airtable (https://mcp.airtable.com/mcp), Apify (https://mcp.apify.com).

## `notionParentPageUrl` (type: `string`):

URL (or id) of the Notion page under which item pages are created. Required to enable the Notion export; ignored by other connectors.

## `maxNotifyListings` (type: `integer`):

Cap on items written to each connector per run. Does not affect the dataset.

## Actor input object example

```json
{
  "mode": "search",
  "searchTerm": "krimi",
  "urls": [
    "https://www.thalia.de/kategorie/romane-erzaehlungen-3/"
  ],
  "specialsOnly": false,
  "einband": [],
  "availability": "",
  "sortBy": "sfmd",
  "fetchDetails": false,
  "fetchReviews": true,
  "maxReviewsPerProduct": 20,
  "maxItems": 20,
  "proxy": {
    "useApifyProxy": true
  },
  "maxNotifyListings": 50
}
```

# Actor output Schema

## `overview` (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 = {
    "mode": "search",
    "searchTerm": "krimi",
    "urls": [
        "https://www.thalia.de/kategorie/romane-erzaehlungen-3/"
    ],
    "einband": [],
    "proxy": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("abotapi/thalia-de-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 = {
    "mode": "search",
    "searchTerm": "krimi",
    "urls": ["https://www.thalia.de/kategorie/romane-erzaehlungen-3/"],
    "einband": [],
    "proxy": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("abotapi/thalia-de-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 '{
  "mode": "search",
  "searchTerm": "krimi",
  "urls": [
    "https://www.thalia.de/kategorie/romane-erzaehlungen-3/"
  ],
  "einband": [],
  "proxy": {
    "useApifyProxy": true
  }
}' |
apify call abotapi/thalia-de-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,abotapi/thalia-de-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/YAEFRhveS7JtuH5VB/builds/HUHsEPBiczGfad9JP/openapi.json
