# Trusted Shops Scraper: Shop Reviews, Ratings & Shop Leads (`steadyscrape/trusted-shops-scraper`) Actor

Scrape Trusted Shops reviews and the shop directory of trustedshops.de, .at, .ch, .co.uk, .fr, .es, .it, .nl, .pl, .be and .eu: rating, title, comment, date, verified purchase, shop reply; shop legal name, phone, email, address, register number. Export data to JSON, CSV or Excel, or via API.

- **URL**: https://apify.com/steadyscrape/trusted-shops-scraper.md
- **Developed by:** [Steady Scrape](https://apify.com/steadyscrape) (community)
- **Categories:** E-commerce, Lead generation, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.50 / 1,000 reviews

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## Trusted Shops Scraper — shop reviews, ratings and European online-shop leads

Scrape **Trusted Shops reviews** and the **Trusted Shops shop directory** across trustedshops.de, .at, .ch, .co.uk,
.fr, .es, .it, .nl, .pl, .be and .eu (and the shop profiles of .dk, .se, .cz, .fi, .pt and .ro). Every review comes as one clean row with **star rating, title, comment, date,
purchase date (verified purchase), the shop's reply and its date**, and the reviewer's first name and initial when
they made it public. The directory gives **European online shops by category, keyword or search** with name, legal
name, website, rating, review count and certification; optionally each shop's profile adds **postal address, phone,
email, WhatsApp, commercial register court and number, responsible person, buyer protection, rating breakdown and
Trusted Shops' own AI review summary**. No login, no browser. Export data to JSON, CSV or Excel, or via API.

This is an unofficial tool: it is **not affiliated with, endorsed or sponsored by Trusted Shops**.

### Who uses this Trusted Shops scraper

- **E-commerce brands and agencies** tracking their own and their competitors' Trusted Shops reviews: new complaints
  (filter 1–2 stars), replies, the 12-month rating breakdown, the reviews mentioning "Lieferung" or "delivery".
- **Market research** on a category: every pet-food shop in Germany with its rating and review volume, then the
  reviews of the top ones.
- **Lead generation** on certified European online shops: legal name, address, phone, email and register number from
  the shop's own profile, beside our Impressum and Shopify store lead Actors.
- **Reputation and review analytics**: export reviews to sentiment, topic or LLM pipelines.

### How the Trusted Shops scraper works

1. **Paste links** from any Trusted Shops site, or **type shop names** to search:
   - a **shop profile** (`https://www.trustedshops.de/bewertung/info_X7BE3174BD112E62D46696024D6762AF7.html`,
     `https://www.trustedshops.es/evaluacion/brottdog-com-es`, `https://www.trustedshops.co.uk/buyerrating/info_….html`)
     gives its reviews;
   - a **directory page** — a category (`https://www.trustedshops.de/shops/tierbedarf/`), a keyword
     (`…/shops/tierbedarf/hundefutter/`) or a search (`…/shops/?q=reifen`) — gives its shops, page after page;
   - a **search term** (`zooplus`, `futterfreund.de`) looks the shop up in the directory of the site you choose.
2. Reviews are read **newest first** (or in the profile's relevance order), 100 per request, filtered the way the
   profile page filters them: by **stars**, by a **word** they mention, and by a **start date**.
3. Turn on **Shop details** to read each shop's profile, and **reviews of listed shops** to follow every shop of a
   directory list with its reviews.

Every input also gets one free `source` row saying what came of it: how many shops or reviews were available and
delivered, or why there were none.

### Trusted Shops scraper input example

```json
{
    "startUrls": [
        "https://www.trustedshops.de/bewertung/info_X7BE3174BD112E62D46696024D6762AF7.html",
        "https://www.trustedshops.de/shops/tierbedarf/hundefutter/"
    ],
    "searchTerms": ["zooplus"],
    "site": "de",
    "maxReviewsPerShop": 200,
    "reviewStars": ["1", "2"],
    "maxShopsPerList": 50,
    "includeShopDetails": true
}
```

### Trusted Shops reviews and shop data: output example

A review (`rowType: "review"`, charged `review`):

```json
{
    "rowType": "review",
    "reviewId": "rev-1ff858bd-c4c2-4ee2-804e-4870898e5deb",
    "rating": 1,
    "title": "Falsch deklariert",
    "comment": "Es wird als halbfeuchtes Futter deklariert aber dies ist nicht der fall es ist Staub trocken, deswegen sofort zurück gesendet.",
    "createdAt": "2026-10-12T08:56:35.000Z",
    "updatedAt": null,
    "purchaseDate": "2026-10-06T02:22:21.000Z",
    "verifiedPurchase": true,
    "verificationStatus": "MEMBER_VERIFIED",
    "reply": "Vielen Dank für Ihre Bewertung.\nWir bedauern sehr, dass es nur für 1 Stern gereicht hat. …",
    "replyDate": "2026-10-12T11:01:35.000Z",
    "reviewerName": null,
    "photoUrls": [],
    "syndicated": false,
    "originalLanguage": null,
    "shopTsId": "X7BE3174BD112E62D46696024D6762AF7",
    "shopName": "Futterfreund.de",
    "shopWebsite": "https://www.futterfreund.de",
    "profileUrl": "https://www.trustedshops.de/bewertung/info_X7BE3174BD112E62D46696024D6762AF7.html",
    "site": "de",
    "position": 1,
    "scrapedAt": "2026-11-01T12:00:00.000Z"
}
```

A shop with its profile (`rowType: "shop"`, charged `shop-with-details`; without `details` it is a `shop`):

```json
{
    "rowType": "shop",
    "tsId": "X7BE3174BD112E62D46696024D6762AF7",
    "name": "Futterfreund.de",
    "legalName": "Futterfreund GmbH",
    "website": "https://www.futterfreund.de",
    "profileUrl": "https://www.trustedshops.de/bewertung/info_X7BE3174BD112E62D46696024D6762AF7.html",
    "site": "de",
    "rating": 4.93,
    "reviewCount": 75180,
    "certified": true,
    "profileType": "member",
    "categories": ["Tierbedarf"],
    "memberSince": "2015-08-06",
    "details": {
        "addressName": "Futterfreund GmbH",
        "street": "Flurstr. 2",
        "postalCode": "96142",
        "city": "Hollfeld",
        "countryCode": "DEU",
        "phone": "+49927480251",
        "email": "buchhaltung@futterfreund.de",
        "registerCourt": "Amtsgericht Bayreuth",
        "registerNumber": "HRB 5116",
        "responsiblePerson": "Jürgen Schneider",
        "certificationType": "CLASSIC",
        "certifiedSince": "2015-08-16",
        "buyerProtection": { "maxAmount": 100, "currency": "EUR", "days": 30 },
        "reviewsLast12Months": 9914,
        "ratingBreakdown": { "oneStar": 34, "twoStars": 16, "threeStars": 41, "fourStars": 423, "fiveStars": 9400 },
        "keywords": ["Hundefutter", "Katzenfutter", "Hunde", "Katzen"],
        "reviewSummary": "Viele Kunden loben die äußerst schnelle und zuverlässige Lieferung …",
        "reviewTopics": [{ "name": "Liefergeschwindigkeit", "sentiment": "positive", "summary": "…" }],
        "market": "DEU",
        "language": "de"
    }
}
```

#### Review fields (`rowType: review`, charged)

| field | what it is |
|---|---|
| `reviewId` | Trusted Shops' review id |
| `rating` | 1–5 stars |
| `title`, `comment` | as written; `null` for a star-only review |
| `createdAt`, `updatedAt` | when it was written / edited (ISO 8601 UTC) |
| `purchaseDate`, `verifiedPurchase` | the order the review belongs to: Trusted Shops asks for reviews after orders it saw |
| `verificationStatus` | the site's own label (`MEMBER_VERIFIED`, `OPEN_PROFILE_VERIFIED`, …) |
| `reply`, `replyDate` | the shop's public answer |
| `reviewerName` | first name and initial, only when the reviewer made their profile public; otherwise `null` ("Community Member") |
| `photoUrls` | photos attached to the review |
| `syndicated`, `originalLanguage` | shown here translated from the same shop's profile on another country site |
| `shopTsId`, `shopName`, `shopWebsite`, `profileUrl`, `site`, `position` | which shop, and the review's place in this run |

#### Shop fields (`rowType: shop`, charged)

| field | what it is |
|---|---|
| `tsId`, `name`, `legalName`, `website`, `profileUrl`, `site` | who the shop is |
| `rating`, `reviewCount` | as the directory card (or, with details, the profile) states them; a card can count the reviews of all the shop's country profiles together |
| `certified`, `profileType`, `memberSince` | Trusted Shops trustmark, `member` / `non-member` / `free-account`, membership start |
| `categories`, `description`, `logoUrl` | as listed |
| `sourceUrl`, `searchTerm`, `position` | the directory list or search it came from, and its place there |
| `details` | with **Shop details**: address, phone, email, WhatsApp, contact form, register court and number, responsible person, certification type and date, buyer protection, 12-month review count and star breakdown, keywords, social links, the site's AI review summary and topics, the shop's other country profiles |

#### Free rows

`rowType: source`: one per link or search, with `status` `ok`, `not_found` (a profile or category the site answers 404
or 410 for), `no_results` (a search or list with no shop), `no_reviews` (a profile that shows none, or none matching the filters), `invalid` (not a
Trusted Shops profile or directory link), `not_read` (the spending limit came first), `blocked` or `unreadable`, and a
`reason` in plain words.

### Trusted Shops scraper pricing

| event | price | when |
|---|---|---|
| `review` | US$0.0005 | each review |
| `shop` | US$0.001 | a shop as the directory card shows it |
| `shop-with-details` | US$0.002 | instead of `shop`, when its profile was read and states an address, contact or legal line |

1,000 reviews cost US$0.50. 1,000 shops from the directory cost US$1, with their profiles US$2. Free rows cost
nothing. Set a spending limit on the run and the Actor stops before reading anything it would not pay for.

### Limits

- A profile shows the reviews of **about the last 12 months**, and the site's reviews API answers at most 10,000 of
  them: older reviews are not on the page and are not scraped. The shop's all-time count is in `reviewCount`.
- The directory pages through at most 200 pages of 20 shops for a category or keyword and 500 for a search.
- A profile lives on its country site only: the German Futterfreund profile is on trustedshops.de, a UK shop's on
  trustedshops.co.uk. Use the link the site gives, or search on the right site; shops of Denmark, Sweden, Czechia,
  Finland, Portugal and Romania are listed by the .eu directory.
- Plain HTTP at a visitor's pace (one request start every 0.5 s): 1,000 reviews take about 10 requests; 1,000 shops
  with details about 1,050 requests, roughly 10 minutes.
- If Trusted Shops refuses with a firewall answer, the Actor retries twice from another IP; a bot check is never
  solved and never retried. Then it stops asking: the rest are free `blocked` rows and the run still ends successfully.

### Is it legal to scrape Trusted Shops?

This Actor reads only public pages — shop profiles and directory pages that Trusted Shops lists for search engines —
and the reviews API those profile pages call themselves, at a visitor's pace. It follows the sites' robots.txt, never
signs in and never bypasses any protection. **Using the data is your responsibility.** In particular:

- **Reviewer data is personal data under the GDPR.** The Actor outputs only what the page shows — a first name and an
  initial at most, never a reviewer's city or profile link — and you must not try to identify reviewers.
- **Shop contact data** of sole traders and named managing directors is personal data too: you need a legal basis for
  contacting them, and in Germany § 7 UWG forbids advertising emails without prior consent, also to businesses.
- Review texts are their authors' and Trusted Shops'; quote them with care.

This Actor is **not affiliated with, endorsed or sponsored by Trusted Shops GmbH** or any shop it lists. Read more in
Apify's blog post on [the legality of web scraping](https://blog.apify.com/is-web-scraping-legal/).

### Feedback

A link that gives a wrong row, or a field you need? Open an issue with the link: every fix is tested against the real
page.

# Actor input Schema

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

Links copied from any Trusted Shops site (trustedshops.de, .at, .ch, .co.uk, .fr, .es, .it, .nl, .pl, .be, .eu, and the profiles of .dk, .se, .cz, .fi, .pt, .ro), one per line. A <b>shop profile</b> (<code>https://www.trustedshops.de/bewertung/info_X7BE3174BD112E62D46696024D6762AF7.html</code>, <code>https://www.trustedshops.es/evaluacion/brottdog-com-es</code>) gives its reviews (and its profile with <i>Shop details</i>). A <b>directory page</b> (a category <code>https://www.trustedshops.de/shops/tierbedarf/</code>, a keyword <code>…/shops/tierbedarf/hundefutter/</code> or a search <code>…/shops/?q=reifen</code>) gives its shops. Up to 5,000.

## `searchTerms` (type: `array`):

Shop names or websites to look up in the Trusted Shops directory of the site below, one per line: <code>zooplus</code>, <code>futterfreund.de</code>, <code>reifen</code>. Each search gives the shops it lists. Up to 100.

## `site` (type: `string`):

The country directory the searches above look in. Links carry their own site.

## `maxShopsPerList` (type: `integer`):

Stop each directory link and each search after this many shops. The directory shows 20 a page, up to 200 pages for a category and 500 for a search.

## `includeShopDetails` (type: `boolean`):

Read each shop's profile page for its legal name, postal address, phone, email, WhatsApp and contact form, commercial register court and number, responsible person, certification, buyer protection, rating breakdown, keywords, social links and Trusted Shops' review summary. Charged <code>shop-with-details</code> instead of <code>shop</code>; a profile that states none of these (most non-member profiles) stays a plain <code>shop</code>. For a profile link, this adds its shop row.

## `maxReviewsPerShop` (type: `integer`):

Reviews to scrape from each shop profile link (0 = none). A profile shows the reviews of about the last 12 months, and at most 10,000.

## `includeReviewsOfListedShops` (type: `boolean`):

Read the reviews of every shop a directory link or a search delivers too, up to the maximum above each.

## `reviewsSort` (type: `string`):

The order reviews are read in, as the profile page offers it.

## `reviewStars` (type: `array`):

Keep only reviews with these ratings, e.g. 1 and 2 stars for complaints. Empty = all.

## `reviewSearchTerm` (type: `string`):

A word the reviews must contain, searched by Trusted Shops as the profile's own review search does (e.g. <code>Lieferung</code>, <code>delivery</code>).

## `reviewsSince` (type: `string`):

Only reviews written on or after this date (UTC), as YYYY-MM-DD or a full ISO timestamp; reviews are then read newest first. Leave empty for no limit.

## Actor input object example

```json
{
  "startUrls": [
    "https://www.trustedshops.de/bewertung/info_X7BE3174BD112E62D46696024D6762AF7.html"
  ],
  "site": "de",
  "maxShopsPerList": 100,
  "includeShopDetails": false,
  "maxReviewsPerShop": 20,
  "includeReviewsOfListedShops": false,
  "reviewsSort": "date"
}
```

# Actor output Schema

## `rows` (type: `string`):

No description

## `summary` (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": [
        "https://www.trustedshops.de/bewertung/info_X7BE3174BD112E62D46696024D6762AF7.html"
    ],
    "maxReviewsPerShop": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("steadyscrape/trusted-shops-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": ["https://www.trustedshops.de/bewertung/info_X7BE3174BD112E62D46696024D6762AF7.html"],
    "maxReviewsPerShop": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("steadyscrape/trusted-shops-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 '{
  "startUrls": [
    "https://www.trustedshops.de/bewertung/info_X7BE3174BD112E62D46696024D6762AF7.html"
  ],
  "maxReviewsPerShop": 20
}' |
apify call steadyscrape/trusted-shops-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,steadyscrape/trusted-shops-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/LMg0Wc1Sc3xBDoY3f/builds/4CTW6bo5f3gKQzQrf/openapi.json
