# Kununu Scraper - DACH Employer Reviews & Ratings (`studio-amba/kununu-scraper`) Actor

Scrape company reviews, ratings, recommendation rates and salary data from kununu.com, the leading employer review platform for Germany, Austria and Switzerland. No login required.

- **URL**: https://apify.com/studio-amba/kununu-scraper.md
- **Developed by:** [Studio Amba](https://apify.com/studio-amba) (community)
- **Categories:** Business
- **Features:** Limited permissions
- **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/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

### What does Kununu Scraper do?

**Kununu Scraper** extracts company ratings, employee reviews, recommendation rates and salary data from [kununu.com](https://www.kununu.com) — the leading employer-review platform for Germany, Austria and Switzerland (the "Glassdoor of DACH"). It collects **overall ratings, 13 rating dimensions, recommendation rates, individual review text, and per-job-title salary averages** for any company profile. No login or cookies required.

Use the Apify platform to run this scraper on a schedule, access results via API, or integrate with tools like Google Sheets, Slack, Zapier, and Make.

### Why use Kununu Scraper?

- **Employer branding research** — See exactly how your company (or a competitor) is rated on the platform DACH job seekers check before applying
- **HR benchmarking** — Compare recommendation rates, salary bands and the 13 rating dimensions (work-life balance, leadership, salary/benefits, etc.) across employers in your industry
- **Recruitment intelligence** — Read real employee reviews before accepting an offer or evaluating an acquisition target
- **Talent market research** — Track salary ranges by job title across German, Austrian and Swiss employers
- **Reputation monitoring** — Set up scheduled runs to catch new reviews and rating shifts for your own company

### How to scrape kununu data

1. Go to the [Kununu Scraper](https://apify.com/studio-amba/kununu-scraper) page on Apify
2. Click **Try for free** to open the actor in Apify Console
3. Enter one or more company slugs (e.g. `lidl-deutschland`, found in the profile URL `kununu.com/de/lidl-deutschland`), full profile URLs, or a free-text `searchQuery` like `"siemens"`
4. Choose the country site (`de`, `at`, or `ch`) for slug-based lookups
5. Set `maxReviews` (per company) and `maxResults` (total review-row cap across all companies)
6. Add your Bright Data API key (see "Bright Data requirement" below)
7. Click **Start** and wait for the scraper to finish
8. Download your data in JSON, CSV, Excel, or HTML format

### Input

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `companySlugs` | Array | No | kununu profile slugs, e.g. `["lidl-deutschland"]` |
| `companyUrls` | Array | No | Full kununu.com profile URLs (any country) |
| `searchQuery` | String | No | Company name to search for, e.g. `"siemens"` — resolves the top 3 matches |
| `country` | String | No | `de` (default), `at`, or `ch` — applies to `companySlugs` |
| `maxReviews` | Integer | No | Max reviews to fetch per company (default: 20) |
| `maxResults` | Integer | No | Total review-row cap across all companies (default: 200) |
| `brightDataApiKey` | String | Yes\* | Bright Data Web Unlocker API key. \*Can also be set via the `BRIGHT_DATA_API_KEY` environment variable if you run your own deployment |
| `proxyConfiguration` | Object | No | Not used by this actor — all traffic routes through Bright Data Web Unlocker |

If you provide none of `companySlugs`, `companyUrls` or `searchQuery`, the actor defaults to `lidl-deutschland` (Germany) as a demonstration run.

### Output

This actor writes two kinds of rows into the same dataset, distinguished by `recordType`.

#### Company-summary row (`recordType: "company"`)

| Field | Type | Example |
|-------|------|---------|
| `companyName` | String | `"Lidl in Deutschland"` |
| `companySlug` | String | `"lidl-deutschland"` |
| `companyWebsite` | String | `"https://jobs.lidl.de/..."` |
| `overallRating` | Number | `3.8` |
| `totalReviewCount` | Number | `13916` |
| `recommendationRate` | Number | `70` |
| `ratingDimensions` | Object | `{"Gehalt/Benefits": 4, "Work-Life-Balance": 3.2, ...}` (13 dimensions) |
| `scoreDistribution` | Array | `[{"label": "Sehr gut", "min": 4, "max": 5, "percentage": 53, "totalReviews": 6345}, ...]` |
| `salarySnippets` | Array | `[{"jobTitle": "Verkäufer:in", "average": 33700, "min": 21900, "max": 50600, "entries": 1795}, ...]` |
| `url` | String | Profile URL |
| `scrapedAt` | String | ISO 8601 timestamp |

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

| Field | Type | Example |
|-------|------|---------|
| `companyName` | String | `"Lidl in Deutschland"` |
| `companySlug` | String | `"lidl-deutschland"` |
| `reviewTitle` | String | `"Lidl als Arbeitgeber"` |
| `reviewRating` | Number | `4.4` |
| `recommended` | Boolean | `true` |
| `pros` | String | Free text on what the reviewer liked |
| `cons` | String | Free text on what the reviewer disliked |
| `position` | String | `"employee / sales (former, since 2021)"` |
| `reviewDate` | String | ISO 8601 date the review was published |
| `multipleReview` | Boolean | Whether this reviewer submitted more than one review |
| `url` | String | Direct review permalink |
| `scrapedAt` | String | ISO 8601 timestamp |

### Example output

Company-summary row:

```json
{
    "recordType": "company",
    "companyName": "Lidl in Deutschland",
    "companySlug": "lidl-deutschland",
    "companyWebsite": "https://jobs.lidl.de/?utm_campaign=20-regelkomm&utm_source=kununu",
    "overallRating": 3.8,
    "totalReviewCount": 13916,
    "recommendationRate": 70,
    "ratingDimensions": {
        "Gehalt/Benefits": 4,
        "Gleichberechtigung": 3.9,
        "Kollegenzusammenhalt": 3.8,
        "Umwelt-/Sozialbewusstsein": 3.8,
        "Umgang mit älteren Kollegen": 3.8,
        "Image": 3.7,
        "Karriere/Weiterbildung": 3.6,
        "Arbeitsatmosphäre": 3.6,
        "Interessante Aufgaben": 3.6,
        "Arbeitsbedingungen": 3.6,
        "Kommunikation": 3.4,
        "Vorgesetztenverhalten": 3.4,
        "Work-Life-Balance": 3.2
    },
    "scoreDistribution": [
        { "label": "Sehr gut", "min": 4, "max": 5, "percentage": 53, "totalReviews": 6345 },
        { "label": "Gut", "min": 3, "max": 4, "percentage": 21, "totalReviews": 2575 },
        { "label": "Befriedigend", "min": 2, "max": 3, "percentage": 16, "totalReviews": 1953 },
        { "label": "Genügend", "min": 1, "max": 2, "percentage": 9, "totalReviews": 1118 }
    ],
    "salarySnippets": [
        { "jobTitle": "Verkäufer:in", "average": 33700, "min": 21900, "max": 50600, "entries": 1795 },
        { "jobTitle": "Filialleiter:in", "average": 62200, "min": 28700, "max": 84500, "entries": 759 }
    ],
    "url": "https://www.kununu.com/de/lidl-deutschland",
    "scrapedAt": "2026-07-12T22:37:04.638Z"
}
```

Review row:

```json
{
    "recordType": "review",
    "companyName": "Lidl in Deutschland",
    "companySlug": "lidl-deutschland",
    "reviewTitle": "Lidl als Arbeitgeber",
    "reviewRating": 4.4,
    "recommended": true,
    "pros": "Möglichkeit weiter aufzusteigen",
    "cons": "",
    "position": "intern / procurement",
    "reviewDate": "2026-07-10T00:00:00+00:00",
    "multipleReview": false,
    "url": "https://www.kununu.com/de/statements/cfd30ce0-32b5-4169-b18e-a15ba3e62b2d/review/732964c8-f7cc-4a11-ad13-f737e2938419",
    "scrapedAt": "2026-07-12T22:37:04.642Z"
}
```

### Bright Data requirement

kununu.com runs AWS WAF Bot Control on CloudFront. Plain HTTP requests get a `202 challenge` response after 2-3 requests, and headless browsers hit an interactive image CAPTCHA. This actor routes every request through [Bright Data](https://brightdata.com) Web Unlocker, which reliably gets through (100% success rate across profile, review, salary and search pages during testing).

You need a Bright Data account and a Web Unlocker zone API key. Add it in the actor's input, or set it as the `BRIGHT_DATA_API_KEY` environment variable if you're running your own deployment. Bright Data cost is small: at roughly $0.0015 per request and 10 reviews returned per request, that's about **$0.0001 in Bright Data cost per review** — a run over 20 companies at 40 reviews each costs roughly $0.20 in Bright Data usage on top of the Apify run cost.

### How much does it cost to scrape kununu?

- **1 company + 20 reviews** (default test run): ~5 Bright Data requests, about a minute of run time
- **1 large company + everything visible** (up to ~50 reviews): ~8 Bright Data requests, one to three minutes of run time
- **50 companies + 20 reviews each**: ~250 Bright Data requests

Use `maxReviews` and `maxResults` to control exactly how much you scrape and spend.

### Tips for best results

- **Use company slugs when you know them** — faster and more precise than search
- **Use searchQuery to discover profiles** — resolves the top 3 matches across all three countries, so `"siemens"` can return the German parent, the Austrian entity, and Siemens Healthineers in one run
- **Scrape many companies rather than one company deeply** — for a large employer kununu shows about 50 reviews to a logged-out visitor, so a `maxReviews` above 50 does not return more
- **Company URLs override the country field** — if you pass a full `companyUrls` entry for an Austrian or Swiss profile, that company's own country is used automatically

### Limitations

- **About 50 reviews per large company.** Since September 2026 kununu only shows logged-out visitors the first page of reviews for any company with more than 20 reviews. Asking for page 2 returns page 1 again. This actor collects the first page plus the newest, best, worst and oldest reviews, which are separate lists on kununu, and stops there. For Lidl Deutschland that is 42 distinct reviews out of about 14,000. The company row (overall rating, all 13 rating dimensions, score distribution, total review count, salaries) always covers the whole company. Companies with 20 reviews or fewer are not fenced and are scraped in full.
- **Numbered review pages are robots-disallowed** on kununu.com. Bright Data Web Unlocker serves them today, but if Bright Data tightens robots.txt enforcement they could stop working. The company row, first-page reviews and salary data are robots-allowed and unaffected.
- **Salary snippets are best-effort.** If the `/gehalt` page fetch fails for a company, the company row is still pushed — just without `salarySnippets`.
- **Pros/cons text coverage varies by review.** Roughly 60% of reviews include kununu's dedicated "what's good / what's bad" free-text fields directly; for the rest, this actor falls back to joining the reviewer's per-factor comments (labeled by dimension) so the fields stay populated for the large majority of reviews.
- Data is scraped from the public website and may change without notice.
- Respect kununu's terms of service and use responsibly.

### FAQ and support

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

**Why do I need a Bright Data key?**
kununu's anti-bot system (AWS WAF Bot Control) blocks plain HTTP requests and headless browsers alike. Bright Data Web Unlocker is the only fetch method that reliably works.

**Can I scrape US or other non-DACH kununu profiles?**
This actor targets the `de`/`at`/`ch` country sites, which cover the vast majority of kununu's catalogue. Legacy `us` profiles exist but are not covered by this actor's country enum.

**The scraper returned 0 results?**
Double-check your Bright Data API key is valid and has Web Unlocker zone access, and that the company slug or URL is correct (try opening it in a browser first).

### Related Scrapers

Looking for employer or job-market data outside DACH? Check out:

- [Glassdoor](https://apify.com/store?search=glassdoor) — the closest US/global equivalent to kununu
- [Indeed](https://apify.com/store?search=indeed) — job listings and company reviews
- Studio AMBA's own European job-board fleet — [stepstone](https://apify.com/store?search=stepstone), [pracuj](https://apify.com/store?search=pracuj), [xing-jobs](https://apify.com/store?search=xing), and 20+ other national job boards across Europe

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

## `companySlugs` (type: `array`):

kununu profile slugs to scrape, e.g. 'lidl-deutschland' from https://www.kununu.com/de/lidl-deutschland. Combine with searchQuery / companyUrls or use alone.

## `companyUrls` (type: `array`):

Full kununu.com profile URLs, e.g. 'https://www.kununu.com/de/lidl-deutschland'. Use when you already have the exact profile link (any country).

## `searchQuery` (type: `string`):

Company name to search for, e.g. 'siemens'. Resolves to the top matching profiles via kununu's search and scrapes each of them.

## `country` (type: `string`):

Which kununu country site to use for companySlugs (companyUrls and search results carry their own country). 'de' = Germany, 'at' = Austria, 'ch' = Switzerland.

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

Maximum number of reviews to fetch per company. For a company with more than 20 reviews, kununu shows a logged-out visitor about 50 (the first page plus the newest, best, worst and oldest reviews), so values above 50 return no more for those companies. Smaller companies are scraped in full.

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

Overall cap on review rows across ALL companies in this run (company-summary rows do not count against this cap).

## `brightDataApiKey` (type: `string`):

Your Bright Data API key for the Web Unlocker zone. Required to bypass kununu's AWS WAF Bot Control (CloudFront). Get one at https://brightdata.com. Can also be supplied via the BRIGHT_DATA_API_KEY environment variable.

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

Not used — this actor routes all traffic through Bright Data Web Unlocker, not Apify proxies.

## Actor input object example

```json
{
  "companySlugs": [
    "lidl-deutschland"
  ],
  "country": "de",
  "maxReviews": 20,
  "maxResults": 50,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# 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 = {
    "companySlugs": [
        "lidl-deutschland"
    ],
    "country": "de",
    "maxReviews": 20,
    "maxResults": 50,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("studio-amba/kununu-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 = {
    "companySlugs": ["lidl-deutschland"],
    "country": "de",
    "maxReviews": 20,
    "maxResults": 50,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("studio-amba/kununu-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 '{
  "companySlugs": [
    "lidl-deutschland"
  ],
  "country": "de",
  "maxReviews": 20,
  "maxResults": 50,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call studio-amba/kununu-scraper --silent --output-dataset

```

## MCP server setup

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