# Trusted Shops Scraper — Shop Trust Ratings & Customer Reviews (`studio-amba/trustedshops-scraper`) Actor

Scrape shop trust profiles and customer reviews from trustedshops.de by shop domain — overall rating, star distribution, certification status and individual reviews with text, rating and date. No login required.

- **URL**: https://apify.com/studio-amba/trustedshops-scraper.md
- **Developed by:** [Studio Amba](https://apify.com/studio-amba) (community)
- **Categories:** Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.00 / 1,000 result scrapeds

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

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

### What does Trusted Shops Scraper do?

Trusted Shops Scraper extracts shop trust ratings and customer reviews from [trustedshops.de](https://www.trustedshops.de) — the German/EU platform behind the "Trusted Shops" certification seal that thousands of online shops display at checkout, and the review site where their customers rate them.

Give it a shop's own domain — the one you already know, like `zalando.de` or `otto-office.com` — and the actor resolves it to that shop's Trusted Shops profile automatically, then scrapes the overall rating, star distribution, certification status and individual reviews.

### Why use Trusted Shops Scraper?

Trusted Shops covers ecommerce shops across Germany and the wider EU that Trustpilot doesn't always reach as deeply — it's the default trust seal for a large share of German online retail. Use this actor to benchmark a shop's trust reputation against competitors, monitor how a review score moves over time, or pull review text for sentiment analysis and voice-of-customer research.

### How to scrape Trusted Shops reviews

1. Add the domains you want to look up to `shopDomains` (e.g. `["otto-office.com", "zalando.de"]`).
2. The actor searches trustedshops.de's own shop directory for each domain and picks the matching profile — you never need to find the internal profile ID yourself.
3. Run the actor. It returns one summary row per shop plus one row per review, up to your `maxReviewsPerShop` and `maxResults` limits.
4. Already have a direct `trustedshops.de/bewertung/info_...` link? Pass it in `profileUrls` instead and skip the search step entirely.

### Input

| Field | Type | Required | Description |
|-------|------|----------|--------------|
| `shopDomains` | Array | No | Shop domains to look up, e.g. `"otto-office.com"`. Resolved to a Trusted Shops profile via the site's own shop search. |
| `profileUrls` | Array | No | Direct `trustedshops.de/bewertung/info_...html` profile URLs, for when you already have the exact link. |
| `maxReviewsPerShop` | Integer | No | Max individual reviews to fetch per shop (default: 40). Large shops can have 100,000+ reviews. |
| `maxResults` | Integer | No | Overall cap on review rows across all shops in the run (default: 200). |
| `proxyConfiguration` | Object | No | Apify proxy settings. Automatic proxy works fine — no anti-bot on trustedshops.de. |

If you leave everything empty, the actor defaults to a well-known certified shop (`otto-office.com`) so a test run always returns data.

### Output

The dataset contains two kinds of rows, distinguished by `recordType`.

#### Shop summary row (`recordType: "shop"`)

| Field | Type | Example |
|-------|------|---------|
| `shopName` | String | `"OTTO Office Deutschland"` |
| `shopDomain` | String | `"otto-office.com"` |
| `tsId` | String | `"X507F9B7DFF6E66ACED13EDB990A7B6BA"` |
| `isMember` | Boolean | `true` |
| `certified` | Boolean | `true` |
| `certifiedSince` | String | `"2015-12-08"` |
| `overallRating` | Number | `4.7` |
| `reviewCount` | Number | `4510` |
| `ratingDistribution` | Object | `{"5": 3702, "4": 543, "3": 106, "2": 44, "1": 115}` |
| `categories` | Array | `["Büro, Schule & Beruf", "Lebensmittel"]` |
| `city` | String | `"Hamburg"` |
| `country` | String | `"DE"` |
| `url` | String | Profile URL on trustedshops.de |

#### Review row (`recordType: "review"`)

| Field | Type | Example |
|-------|------|---------|
| `shopName` | String | `"OTTO Office Deutschland"` |
| `tsId` | String | `"X507F9B7DFF6E66ACED13EDB990A7B6BA"` |
| `reviewId` | String | `"rev-2d8490e8-1ca7-4432-bc9c-c2e90a68358d"` |
| `reviewText` | String | Full review body text |
| `ratingScore` | Number | `4` |
| `reviewerName` | String | `"Jörg L."` or `"Community Member"` when anonymized |
| `entryDate` | String | ISO 8601 review date |
| `language` | String | `"de"` |
| `url` | String | Profile URL with a `#review-...` anchor |
| `scrapedAt` | String | ISO 8601 timestamp of collection |

### Example output

```json
{
    "recordType": "shop",
    "shopName": "OTTO Office Deutschland",
    "shopDomain": "otto-office.com",
    "tsId": "X507F9B7DFF6E66ACED13EDB990A7B6BA",
    "profileUrl": "https://www.trustedshops.de/bewertung/info_X507F9B7DFF6E66ACED13EDB990A7B6BA.html",
    "isMember": true,
    "certified": true,
    "certifiedSince": "2015-12-08",
    "overallRating": 4.7,
    "reviewCount": 4510,
    "ratingDistribution": { "5": 3702, "4": 543, "3": 106, "2": 44, "1": 115 },
    "categories": ["Büro, Schule & Beruf", "Lebensmittel"],
    "city": "Hamburg",
    "country": "DE",
    "url": "https://www.trustedshops.de/bewertung/info_X507F9B7DFF6E66ACED13EDB990A7B6BA.html",
    "scrapedAt": "2026-08-21T09:31:38.930Z"
}
```

```json
{
    "recordType": "review",
    "shopName": "OTTO Office Deutschland",
    "tsId": "X507F9B7DFF6E66ACED13EDB990A7B6BA",
    "reviewId": "rev-2d8490e8-1ca7-4432-bc9c-c2e90a68358d",
    "reviewText": "Ihren Online-shop finde ich als sehr gut strukturiert. Die benötigten Produkte sind schnell zu finden...",
    "ratingScore": 4,
    "reviewerName": "Community Member",
    "entryDate": "2026-08-04T11:20:57.000Z",
    "language": "de",
    "url": "https://www.trustedshops.de/bewertung/info_X507F9B7DFF6E66ACED13EDB990A7B6BA.html#review-rev-2d8490e8-1ca7-4432-bc9c-c2e90a68358d",
    "scrapedAt": "2026-08-21T09:31:38.932Z"
}
```

### How the domain lookup works

Trusted Shops itself doesn't publish domain-to-profile lookups anywhere obvious — the review pages live at an opaque URL like `/bewertung/info_X507F9B7DFF6E66ACED13EDB990A7B6BA.html`. This actor queries trustedshops.de's own shop-search page with your domain, reads the shop list it returns (each entry carries both the shop's real domain and its internal profile ID), and picks the exact domain match. If no exact match exists, it falls back to the closest result and logs a warning so you can see what it picked.

### How much does it cost to scrape Trusted Shops?

- **1 shop, 20 reviews** (default test run): 2 requests, a few seconds of run time
- **1 shop, 200 reviews**: ~11 requests (20 reviews per page)
- **A large shop's recent history**: capped by `maxReviewsPerShop` and `maxResults` so you control cost — a shop with 100,000+ reviews will not be scraped end to end unless you raise the caps

There's no anti-bot cost on this site (no Bright Data or residential proxy needed), so the marginal cost per result is Apify compute plus platform pricing only. Usage cost only settles once a run finishes with status SUCCEEDED — a run you abort or that fails partway through is not charged for the pay-per-event items.

### Tips for best results

- **Use the domain as it appears in the shop's own footer or checkout page** — `shop.de`, `www.shop.de` and `https://shop.de/` all normalize the same way
- **Check `isMember` and `certified`** — non-member profiles are unclaimed listings Trusted Shops indexed from public review activity; they can still have real reviews (e.g. `otto.de` itself has 164), but no buyer-protection guarantee backs them
- **Start with a small `maxReviewsPerShop`** to confirm you've matched the right shop before scaling up

### Limitations

- Reviewer names are usually first name + last initial (e.g. "Jörg L.") or "Community Member" when Trusted Shops anonymizes them — full names are never published
- The `reviewCount` shown in shop-search results can differ from the `aggregateRating.reviewCount` on the shop's own profile page (the two come from different internal counters on Trusted Shops' side) — this actor always reports the profile-page figure, the one shown to visitors
- Zero-review shops (unclaimed profiles Trusted Shops has indexed but that have no reviews yet) produce no rows for that domain
- Data is scraped from the public website and may change without notice
- Respect Trusted Shops' terms of service and use responsibly

### FAQ and support

**Is it legal to scrape Trusted Shops?**
This actor extracts publicly available data from trustedshops.de. Users are responsible for ensuring their use complies with applicable laws and the website's terms of service.

**Why didn't my domain resolve to the shop I expected?**
The shop-search endpoint matches on shop name and domain text, not an exact-only lookup. Check the run log — every resolved domain is logged with the profile it matched, so you can confirm or correct it.

**Can I look up a shop I already have the profile link for?**
Yes — pass it in `profileUrls` and the actor skips the search step entirely.

**The scraper returned 0 results?**
The domain may not have a Trusted Shops profile at all, or the shop's profile may have zero reviews. Try the domain on trustedshops.de directly first to confirm a profile exists.

### Related Scrapers

Looking for review or trust data outside Germany, or a different review vertical?

- Studio AMBA's own DACH review-vertical fleet — [kununu](https://apify.com/store?search=kununu) (employer reviews), [jameda](https://apify.com/store?search=jameda) (doctor reviews)
- [Trustpilot](https://apify.com/store?search=trustpilot) — the closest international equivalent to Trusted Shops

### Need this data on a schedule, or a custom version?

We run this scraper as a managed service for businesses: scheduled runs, deduplication, delta detection, and delivery to your inbox, Google Sheets, or API — maintenance included. We can also build a custom version with your exact fields and filters, or combine multiple sources into one feed.

See [studioamba.dev/services](https://studioamba.dev/services/) or email <hello@studioamba.dev> for a free data sample. We maintain 300+ European web scrapers and answer within one business day.

# Actor input Schema

## `shopDomains` (type: `array`):

Domains of the shops to look up, e.g. 'otto-office.com', 'yves-rocher.de', 'zalando.de'. Each domain is resolved to its Trusted Shops profile via the site's shop search — no need to know the internal profile ID.

## `profileUrls` (type: `array`):

Direct trustedshops.de profile URLs, e.g. 'https://www.trustedshops.de/bewertung/info\_X507F9B7DFF6E66ACED13EDB990A7B6BA.html'. Use when you already have the exact profile link — skips the domain search step. Combine with shopDomains or use alone.

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

Maximum number of individual reviews to fetch per shop. A large shop can have 100,000+ reviews across 5,000+ pages — keep this small for a quick check.

## `maxResults` (type: `integer`):

Overall cap on review rows across ALL shops in this run (the one company-summary row per shop does not count against this cap).

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

Proxy settings. trustedshops.de's shop-search and review pages have no Cloudflare/DataDome/Akamai anti-bot (verified live with a plain HTTP request) — the default automatic Apify proxy works without a residential group.

## Actor input object example

```json
{
  "shopDomains": [
    "otto-office.com"
  ],
  "maxReviewsPerShop": 20,
  "maxResults": 40,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# 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 = {
    "shopDomains": [
        "otto-office.com"
    ],
    "maxReviewsPerShop": 20,
    "maxResults": 40,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("studio-amba/trustedshops-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 = {
    "shopDomains": ["otto-office.com"],
    "maxReviewsPerShop": 20,
    "maxResults": 40,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("studio-amba/trustedshops-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 '{
  "shopDomains": [
    "otto-office.com"
  ],
  "maxReviewsPerShop": 20,
  "maxResults": 40,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call studio-amba/trustedshops-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,studio-amba/trustedshops-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/p0Wi1wWrmV1NY6jxO/builds/93o004nT8DYWifGA2/openapi.json
