# Thomann Product Reviews Scraper (`automation-lab/thomann-product-reviews-scraper`) Actor

🎸 Extract public Thomann customer reviews with full text, ratings, dates, aspect scores, helpful votes, product IDs, and aggregate sentiment context.

- **URL**: https://apify.com/automation-lab/thomann-product-reviews-scraper.md
- **Developed by:** [Stas Persiianenko](https://apify.com/automation-lab) (community)
- **Categories:** E-commerce
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

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 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.

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

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

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python/docs.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/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

## Thomann Product Reviews Scraper

Collect public customer reviews from Thomann product pages as clean, structured data.
Turn product feedback for musical instruments, studio equipment, software, lighting, and accessories into an analysis-ready Apify dataset.

The Actor accepts product pages or dedicated `_reviews.htm` pages from Thomann locale domains.
It returns one row per review, including the full review text, score, reviewer, date, aspect ratings, helpful votes, product metadata, and aggregate rating context.

### What does Thomann Product Reviews Scraper do?

Thomann Product Reviews Scraper converts public Thomann review pages into structured records.
It can:

- 🎸 normalize ordinary product URLs to their customer-review pages
- 🌍 collect reviews across Thomann country and locale domains
- 💬 include every public review language, not only the locale default
- ⭐ extract overall and aspect-level ratings
- 📊 attach product-level rating totals and distributions to every review
- 👍 capture helpful and unhelpful vote counts
- 🗓️ filter results by rating and review date
- 🔗 preserve canonical product, review, and source URLs

No Thomann account is required for reading these public reviews.
The Actor does not submit ratings, vote, report content, or access customer accounts.

### Who is it for?

#### Musical-instrument brands

Track recurring praise, defects, setup friction, and perceived quality for your own products.
Compare launch feedback across markets and languages.

#### Retailers and distributors

Monitor customer sentiment about products you stock.
Use review evidence to improve product selection, merchandising, support articles, and returns analysis.

#### Product and market researchers

Build comparable datasets for competing monitors, microphones, guitars, keyboards, drums, software, and accessories.
Analyze score distributions and detailed review language over time.

#### Data and AI teams

Feed structured customer feedback into sentiment pipelines, topic models, BI dashboards, LLM workflows, or internal search systems.

### Why use this Thomann reviews extractor?

Copying review pages manually is slow and difficult to reproduce.
This Actor provides a consistent contract across Thomann locale domains.

- One dataset row equals one customer review.
- Numeric ratings are ready for aggregation.
- Dates are normalized to `YYYY-MM-DD`.
- Product IDs provide a stable join key.
- Review IDs support deduplication and incremental monitoring.
- Aspect scores remain a flexible object because categories differ by product.
- A global output limit makes trial and scheduled runs predictable.

### Supported Thomann URLs

Use full public URLs from a Thomann locale domain.
Both forms below are accepted:

```text
https://www.thomann.ie/yamaha_hs_5_grey.htm
https://www.thomann.ie/yamaha_hs_5_grey_reviews.htm
````

The first URL is automatically converted to the second form.
Other country domains such as `thomann.de`, `thomann.fr`, `thomann.nl`, and `thomann.co.uk` are supported when they expose the same public product-review page.

URLs from unrelated websites are rejected before any request is made.
This prevents accidental off-target crawling and unexpected proxy spend.

### Input

| Field | Type | Default | Description |
|---|---|---:|---|
| `startUrls` | array | required | Thomann product or review URLs |
| `maxReviews` | integer | `10` | Global maximum review rows across all products |
| `includeAllLanguages` | boolean | `true` | Include every language listed on the page |
| `minRating` | number | none | Minimum overall review rating, inclusive |
| `maxRating` | number | none | Maximum overall review rating, inclusive |
| `dateFrom` | string | none | Earliest review date, `YYYY-MM-DD` |
| `dateTo` | string | none | Latest review date, `YYYY-MM-DD` |
| `proxyConfiguration` | object | Residential | Apify or custom proxy settings |

The `maxReviews` limit applies across all supplied products.
For example, a limit of 100 stops after 100 saved review rows even when five product URLs are supplied.

### Quick-start input

```json
{
  "startUrls": [
    { "url": "https://www.thomann.ie/yamaha_hs_5_grey_reviews.htm" }
  ],
  "maxReviews": 10,
  "includeAllLanguages": true
}
```

Run this example from Apify Console to collect a small export-ready dataset.
The default is intentionally small for an inexpensive first run.

### Rating-filter example

Collect only critical and mixed reviews:

```json
{
  "startUrls": [
    { "url": "https://www.thomann.ie/yamaha_hs_5_grey.htm" }
  ],
  "maxReviews": 100,
  "maxRating": 3,
  "includeAllLanguages": true
}
```

Rating bounds are inclusive.
If `minRating` is greater than `maxRating`, the run fails with a clear validation error.

### Date-filter example

Collect recent feedback for launch monitoring:

```json
{
  "startUrls": [
    { "url": "https://www.thomann.de/example_product_reviews.htm" }
  ],
  "maxReviews": 250,
  "dateFrom": "2026-01-01",
  "dateTo": "2026-12-31"
}
```

Dates are compared after conversion from Thomann's displayed day-month-year format.

### Output data

Each item contains review data and the product context needed for downstream analysis.

| Field | Type | Meaning |
|---|---|---|
| `reviewId` | string | Thomann review identifier |
| `productId` | string or null | Thomann article/SKU identifier |
| `productName` | string | Displayed product name |
| `productUrl` | string | Canonical product page |
| `reviewsUrl` | string | Canonical reviews page |
| `locale` | string | Locale inferred from the source domain |
| `aggregateRating` | number or null | Product average score |
| `aggregateReviewCount` | integer | Product rating count |
| `ratingDistribution` | object | Counts for ratings 1 through 5 |
| `reviewTitle` | string | Review headline |
| `reviewBody` | string | Full public review text |
| `reviewer` | string or null | Public reviewer display name |
| `reviewDate` | string or null | ISO date |
| `rating` | number or null | Overall review rating from 1 to 5 |
| `aspectRatings` | object | Named scores such as sound, quality, or features |
| `helpfulVotes` | integer | Positive feedback votes |
| `unhelpfulVotes` | integer | Negative feedback votes |
| `reportAvailable` | boolean | Whether the public report control is shown |
| `sourceUrl` | string | Source review page |
| `scrapedAt` | string | UTC extraction timestamp |

### Output example

```json
{
  "reviewId": "4563853",
  "productId": "463834",
  "productName": "Yamaha HS 5 SG",
  "locale": "ie",
  "aggregateRating": 4.9,
  "aggregateReviewCount": 7,
  "reviewTitle": "Super crisp monitors with shifting grey colour",
  "reviewer": "Norbe",
  "reviewDate": "2022-09-14",
  "rating": 5,
  "aspectRatings": {
    "features": 5,
    "quality": 5,
    "sound": 5
  },
  "helpfulVotes": 0,
  "unhelpfulVotes": 1,
  "reportAvailable": true
}
```

Fields not present on a particular public card are returned as nullable values or empty objects rather than invented data.

### How pagination works

Thomann review pages expose a server-rendered first page and a paging route.
The Actor requests pages sequentially and stops when:

1. `maxReviews` has been reached,
2. the source has no more pages, or
3. a page contains no review cards.

Review IDs are deduplicated within a run.
Only records that pass all filters count toward the saved limit.

### Language and locale behavior

With `includeAllLanguages: true`, the Actor asks Thomann for all public review languages.
The review body remains in the language published by the reviewer.
The Actor does not machine-translate or rewrite customer text.

Set `includeAllLanguages` to `false` when you only want the review selection served by that locale page.
The `locale` output field records the country-domain suffix for segmentation.

### Proxy and reliability

Thomann may rate-limit datacenter traffic.
The default input therefore uses Apify Residential Proxy and infers a matching country from common locale domains.

The Actor uses:

- sequential requests for conservative load,
- a stable browser-like HTTP client,
- normal language and document headers,
- rotated sessions after blocked or incomplete responses,
- bounded retries with short backoff,
- explicit failure when the source never returns usable review HTML.

You can override the proxy configuration, but disabling proxy access may produce HTTP 429 responses.

### How much does it cost to scrape Thomann reviews?

This Actor uses pay-per-event pricing:

- one small **Actor start** charge per run,
- one **review item** charge per saved review.

The start fee is **$0.005**. Per-review prices decrease by Apify plan:

| Plan | Price per saved review |
|---|---:|
| Free | $0.00064477 |
| Bronze | $0.00056067 |
| Silver | $0.00043732 |
| Gold | $0.00033640 |
| Platinum | $0.00022427 |
| Diamond | $0.00015699 |

The final amount is visible before starting a run in Apify Console and depends mainly on the number of reviews saved.
Filtering does not charge for discarded records.
Use a low `maxReviews` value for initial validation, then scale scheduled workflows after reviewing your dataset.

### Export and integrations

Apify datasets can be exported as JSON, CSV, Excel, XML, or RSS.
Common workflows include:

- Send new review rows to Google Sheets with Make.
- Load review records into BigQuery, Snowflake, or PostgreSQL.
- Trigger Slack alerts for low-rating reviews through Zapier.
- Build a Power BI or Looker Studio sentiment dashboard.
- Enrich a product catalog by joining on `productId`.
- Store review embeddings in a vector database for semantic search.
- Schedule weekly monitoring and compare unseen `reviewId` values.

### API usage with Node.js

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation-lab/thomann-product-reviews-scraper').call({
  startUrls: [{ url: 'https://www.thomann.ie/yamaha_hs_5_grey_reviews.htm' }],
  maxReviews: 25,
  includeAllLanguages: true,
});

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

### API usage with Python

```python
from apify_client import ApifyClient

client = ApifyClient(token="YOUR_APIFY_TOKEN")
run = client.actor("automation-lab/thomann-product-reviews-scraper").call(run_input={
    "startUrls": [{"url": "https://www.thomann.ie/yamaha_hs_5_grey_reviews.htm"}],
    "maxReviews": 25,
    "includeAllLanguages": True,
})
items = client.dataset(run["defaultDatasetId"]).list_items().items
print(items)
```

### API usage with cURL

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/automation-lab~thomann-product-reviews-scraper/runs?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "startUrls": [{"url":"https://www.thomann.ie/yamaha_hs_5_grey_reviews.htm"}],
    "maxReviews": 25,
    "includeAllLanguages": true
  }'
```

Read the run's default dataset after it succeeds.
For production integrations, keep the token in a secret manager rather than source code.

### Use with Apify MCP

Connect AI assistants through Apify MCP using the Actor-specific tool URL.

#### Claude Code

```bash
claude mcp add --transport http thomann-reviews "https://mcp.apify.com?tools=automation-lab/thomann-product-reviews-scraper"
```

#### Claude Desktop, Cursor, and VS Code

Add an HTTP MCP server through each client's MCP settings. Claude Desktop and Cursor can use this `mcpServers` JSON; VS Code users can enter the same URL in the MCP server setup:

```json
{
  "mcpServers": {
    "thomann-reviews": {
      "url": "https://mcp.apify.com?tools=automation-lab/thomann-product-reviews-scraper"
    }
  }
}
```

Restart the client after saving the configuration and confirm the Actor tool appears.

Example prompts:

- “Collect the latest 50 reviews for these Thomann product URLs and summarize recurring quality complaints.”
- “Compare sound and features ratings for these competing studio monitors.”
- “Find reviews rated three stars or below since January and group issues by topic.”

### Scheduling a review monitor

Create an Apify schedule with a stable list of product URLs.
Save the resulting dataset or send it to your destination integration.
Use `reviewId` as the unique key when comparing runs.

A practical weekly workflow is:

1. run every Monday,
2. collect a bounded recent product set,
3. compare IDs against your warehouse,
4. alert on unseen low-rating records,
5. update a sentiment dashboard.

The Actor does not maintain cross-run state itself, so your destination controls retention and alerting policy.

### Tips for better results

- Start with one known review URL and a limit of 10.
- Keep `includeAllLanguages` enabled for international research.
- Segment analysis using `locale` and review language in the text.
- Supply product URLs from the same locale when comparing prices or launches.
- Use both rating and date filters for targeted monitoring.
- Prefer stable product URLs over temporary campaign links.
- Increase limits gradually when using residential proxy traffic.

### Troubleshooting

#### Why did the run receive HTTP 429 or an unusable response?

Thomann may be rate-limiting the selected connection.
Keep the default Residential proxy configuration enabled.
If you override it, use a supported geographic exit and avoid high parallel request rates.

#### Why did the run fail with “No reviews matched”?

The product may have no public reviews, or every review may have been removed by your rating/date filters.
Confirm the source page in a browser and retry with filters omitted.
The Actor fails rather than reporting a misleading successful empty extraction.

#### Why are some aspect ratings absent?

Thomann shows aspect categories only for products and reviews where those scores were collected.
An empty object means the source card did not expose aspect ratings.

#### Can I enter a category or search page?

No.
This Actor is intentionally scoped to individual product and review URLs so every output row has precise product context.
Use a product catalog scraper first when you need to discover URLs at category scale.

### Responsible use and legality

The Actor collects information displayed publicly on Thomann product review pages.
Public availability does not remove your responsibility to follow applicable laws, contractual requirements, privacy rules, intellectual-property rights, and Thomann's terms.

Do not use output to harass reviewers, infer sensitive traits, republish personal information improperly, or automate interactions with Thomann.
Collect only what you need, apply appropriate retention limits, and honor valid deletion or access requests in your downstream systems.
This is not legal advice.

### Data quality notes

Review text and display names are user-generated source data.
They may contain opinions, mistakes, formatting differences, or multiple languages.
Aggregate counts can change as Thomann moderates or receives ratings.
Helpful votes can also change after extraction.

For reproducible analysis, retain `sourceUrl`, `reviewId`, `productId`, and `scrapedAt`.
Treat nullable fields as source absence, not a zero value.

### Related scrapers

Combine this Actor with other automation-lab review products when you need cross-retailer context:

- [Amazon Reviews Scraper](https://apify.com/automation-lab/amazon-reviews-scraper)
- [Walmart Reviews Scraper](https://apify.com/automation-lab/walmart-reviews-scraper)
- [Steam Reviews Scraper](https://apify.com/automation-lab/steam-reviews-scraper)

Use source-specific actors rather than assuming that ratings are directly comparable across retailers.

### FAQ

#### Does the Actor require a Thomann login?

No. It reads public review pages anonymously.
Submitting ratings and accessing customer-account pages are outside scope.

#### Does it scrape multiple products?

Yes. Add multiple entries to `startUrls`.
The global `maxReviews` limit is shared across them.

#### Does it translate reviews?

No. Original public text is preserved.
Use a downstream translation service if translated text is part of your workflow.

#### Are product pages accepted?

Yes. Standard `.htm` product URLs are normalized automatically to `_reviews.htm`.

#### How are duplicates handled?

The Actor deduplicates by Thomann review ID during each run.
For recurring schedules, deduplicate by `reviewId` in your destination.

#### Can I scrape reviews from another retailer?

No. Only public `thomann.*` product/review URLs are accepted.
Choose a source-specific related scraper for other websites.

### Build reliable product-feedback datasets

Start with one product and a small limit.
Inspect the structured dataset, connect the export to your analysis workflow, and then add the products that matter to your market.

Thomann Product Reviews Scraper is designed for repeatable review intelligence: stable identifiers, clear provenance, useful rating context, conservative requests, and predictable output limits.

# Actor input Schema

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

Public thomann.\* product URLs ending in .htm or review URLs ending in \_reviews.htm.

## `maxReviews` (type: `integer`):

Global maximum number of review rows saved across all products.

## `includeAllLanguages` (type: `boolean`):

Return every public review language shown by Thomann instead of only the locale default.

## `minRating` (type: `number`):

Keep reviews at or above this overall rating.

## `maxRating` (type: `number`):

Keep reviews at or below this overall rating.

## `dateFrom` (type: `string`):

Keep reviews on or after this date (YYYY-MM-DD).

## `dateTo` (type: `string`):

Keep reviews on or before this date (YYYY-MM-DD).

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

Residential Apify Proxy is recommended because Thomann rate-limits datacenter traffic. Country is inferred from each locale URL unless overridden.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.thomann.ie/yamaha_hs_5_grey_reviews.htm"
    }
  ],
  "maxReviews": 10,
  "includeAllLanguages": true,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# 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 = {
    "startUrls": [
        {
            "url": "https://www.thomann.ie/yamaha_hs_5_grey_reviews.htm"
        }
    ],
    "maxReviews": 10,
    "includeAllLanguages": true,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation-lab/thomann-product-reviews-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 = {
    "startUrls": [{ "url": "https://www.thomann.ie/yamaha_hs_5_grey_reviews.htm" }],
    "maxReviews": 10,
    "includeAllLanguages": True,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("automation-lab/thomann-product-reviews-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 '{
  "startUrls": [
    {
      "url": "https://www.thomann.ie/yamaha_hs_5_grey_reviews.htm"
    }
  ],
  "maxReviews": 10,
  "includeAllLanguages": true,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call automation-lab/thomann-product-reviews-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=automation-lab/thomann-product-reviews-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Thomann Product Reviews Scraper",
        "description": "🎸 Extract public Thomann customer reviews with full text, ratings, dates, aspect scores, helpful votes, product IDs, and aggregate sentiment context.",
        "version": "0.1",
        "x-build-id": "7cMq84VgqXbqLDxKR"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/automation-lab~thomann-product-reviews-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-automation-lab-thomann-product-reviews-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/automation-lab~thomann-product-reviews-scraper/runs": {
            "post": {
                "operationId": "runs-sync-automation-lab-thomann-product-reviews-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/automation-lab~thomann-product-reviews-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-automation-lab-thomann-product-reviews-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",
                "required": [
                    "startUrls"
                ],
                "properties": {
                    "startUrls": {
                        "title": "🎸 Thomann product or review URLs",
                        "type": "array",
                        "description": "Public thomann.* product URLs ending in .htm or review URLs ending in _reviews.htm.",
                        "items": {
                            "type": "object",
                            "required": [
                                "url"
                            ],
                            "properties": {
                                "url": {
                                    "type": "string",
                                    "title": "URL of a web page",
                                    "format": "uri"
                                }
                            }
                        }
                    },
                    "maxReviews": {
                        "title": "Maximum reviews",
                        "minimum": 1,
                        "maximum": 10000,
                        "type": "integer",
                        "description": "Global maximum number of review rows saved across all products.",
                        "default": 10
                    },
                    "includeAllLanguages": {
                        "title": "Include reviews in all languages",
                        "type": "boolean",
                        "description": "Return every public review language shown by Thomann instead of only the locale default.",
                        "default": true
                    },
                    "minRating": {
                        "title": "Minimum review rating",
                        "minimum": 1,
                        "maximum": 5,
                        "type": "number",
                        "description": "Keep reviews at or above this overall rating."
                    },
                    "maxRating": {
                        "title": "Maximum review rating",
                        "minimum": 1,
                        "maximum": 5,
                        "type": "number",
                        "description": "Keep reviews at or below this overall rating."
                    },
                    "dateFrom": {
                        "title": "Reviews from date",
                        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                        "type": "string",
                        "description": "Keep reviews on or after this date (YYYY-MM-DD)."
                    },
                    "dateTo": {
                        "title": "Reviews to date",
                        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                        "type": "string",
                        "description": "Keep reviews on or before this date (YYYY-MM-DD)."
                    },
                    "proxyConfiguration": {
                        "title": "🌐 Proxy configuration",
                        "type": "object",
                        "description": "Residential Apify Proxy is recommended because Thomann rate-limits datacenter traffic. Country is inferred from each locale URL unless overridden.",
                        "default": {
                            "useApifyProxy": true,
                            "apifyProxyGroups": [
                                "RESIDENTIAL"
                            ]
                        }
                    }
                }
            },
            "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
