# Kununu Scraper · DACH Employer Reviews, Salaries & Jobs (`memo23/kununu-scraper`) Actor

Scrape kununu.com across Germany, Austria & Switzerland — employer scores, employee reviews, interview reviews with questions & outcomes, salary medians and Kulturkompass. Plus kununu JOB postings with each employer's rating attached. Incremental monitoring + alerts. $1 per 1,000 rows.

- **URL**: https://apify.com/memo23/kununu-scraper.md
- **Developed by:** [Muhamed Didovic](https://apify.com/memo23) (community)
- **Categories:** Jobs, Lead generation, AI
- **Stats:** 17 total users, 17 monthly users, 93.5% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 results

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

## Kununu Scraper · DACH Employer Reviews, Salaries & Jobs

Scrape **kununu.com** — the employer-review site for Germany, Austria and Switzerland — and get employer scores, employee reviews, interview reviews, salary medians, culture data **and kununu's job postings** as clean JSON or CSV.

Pure HTTP. No browser, no login, no API key. **$1 per 1,000 rows.**

![How the Kununu Scraper works](https://raw.githubusercontent.com/muhamed-didovic/muhamed-didovic.github.io/main/assets/how-it-works-kununu.png)

***

### Why use this scraper

- **Jobs included.** Every other kununu scraper on the Store stops at reviews. This one also pulls each employer's open positions — title, location, contract type, posting date, salary range — with the employer's kununu score attached **to every posting**. That combination does not exist anywhere else.
- **Interview intelligence.** Applicant reviews come with the outcome (offer / rejection), the year applied, and the actual interview questions candidates remembered being asked.
- **All three countries.** Germany, Austria and Switzerland from one actor. Mix them freely in one run.
- **You don't need URLs.** Hand it a list of plain company names — it resolves each to the right kununu profile itself.
- **Monitoring built in.** Incremental mode emits only what changed since the last run, so a daily schedule costs a fraction of a full re-scrape. Alerts go to Telegram, Slack, Discord or your own webhook.
- **Honest billing.** You are charged per row. Optional extras (salary tables, culture, full job descriptions, email discovery) bill only when the data is actually found.

***

### What it scrapes

Three row types, distinguished by a `type` field, from one run:

| Row type | Source | What you get |
|---|---|---|
| `company` | Employer profile | kununu score, review counts, recommendation rate, 13 category scores, awards, industry, location, size band, socials |
| `review` | Reviews & interview tabs | Rating, title, pros, cons, suggestions, per-category comments, department, current-vs-former, interview outcome & questions |
| `job` | Employer's open positions | Title, employer, location, contract type, posting date, salary range — plus the employer's kununu score |

***

### Supported inputs

Any of these, alone or combined:

| Input | Example |
|---|---|
| Company names | `["Bosch", "SAP", "Red Bull"]` |
| Company profile URL | `https://www.kununu.com/de/bosch-gruppe` |

Country comes from each pasted URL, so DE, AT and CH URLs can be mixed in one run.

***

### Use cases

- **Employer branding & benchmarking** — track your kununu score, recommendation rate and 13 category scores against competitors in your industry, and watch them move over time.
- **Recruitment market research** — pull an employer's entire open-roles list with their kununu reputation attached, so you can see who is hiring and how they are rated.
- **Compensation analysis** — salary medians and ranges per job title, with the sample size behind each figure.
- **Interview preparation and hiring-process research** — real interview questions, outcomes, and how candidates rated the process.
- **Lead generation** — employer profiles with website, location, size band and optional contact-email discovery.
- **HR sentiment monitoring** — schedule an incremental run and get alerted the moment a new review lands for the employers you watch.
- **AI and LLM pipelines** — compact mode returns token-efficient rows ready for retrieval or agent workflows.

***

### How it works

1. You give it company names or kununu company URLs.
2. It resolves each input to the right kununu pages and paginates through them.
3. Employer profiles, reviews, salaries, culture and jobs are read from the same JSON endpoints kununu's own website calls — so the data arrives typed and complete, not scraped out of markup that changes every deploy.
4. Optional extras are included only when you switch them on.
5. Rows stream into the dataset as they are found — you see results immediately, not at the end.

kununu challenges datacenter traffic, so the actor retries with a fresh residential IP and backs off when throttled. Residential proxies are strongly recommended.

If an input genuinely cannot be served, the run reports that reason and fails rather than finishing "successfully" with an empty dataset.

***

### Input configuration

| Field | Type | Default | What it does |
|---|---|---|---|
| `companyNames` | array | — | Plain company names to resolve |
| `startUrls` | array | — | Any kununu URLs |
| `countryCode` | select | `de` | `de`, `at` or `ch` for searches |
| `maxItems` | integer | `100` | Hard cap on rows — your main cost control |
| `includeReviews` | boolean | `false` | Also scrape employee reviews |
| `maxReviewsPerCompany` | integer | `50` | Reviews per employer |
| `includeApplicantReviews` | boolean | `false` | Also scrape interview reviews |
| `maxApplicantReviewsPerCompany` | integer | `50` | Interview reviews per employer |
| `includeSalaries` | boolean | `false` | Add the salary table |
| `includeCulture` | boolean | `false` | Add the Kulturkompass verdict |
| `includeJobs` | boolean | `false` | Also scrape the employer's open job postings |
| `maxJobsPerCompany` | integer | `50` | Job postings per employer |
| `enrichEmails` | boolean | `false` | Discover employer contact emails |
| `includeContactData` | boolean | `true` | Keep emails and phones found in page text |
| `compact` | boolean | `false` | Core fields only, for AI pipelines |
| `incrementalMode` | boolean | `false` | Emit only what changed since last run |
| `stateKey` | string | — | Names the saved baseline for monitoring |

Notifications (`telegramToken`, `slackWebhookUrl`, `discordWebhookUrl`, `webhookUrl`) send a run summary to your own channels.

***

### Output samples

#### Job row

```json
{
  "type": "job",
  "jobId": "d90a5475-b051-47b3-b5ed-77badbfbee39",
  "url": "https://www.kununu.com/job-postings/de/d90a5475-b051-47b3-b5ed-77badbfbee39",
  "title": "Praktikum / Flexikum im Customer Support und Klärfallmanagement",
  "companyName": "Deutsche Telekom AG",
  "companyProfileUrl": "https://www.kununu.com/de/deutsche-telekom",
  "companyWebsite": "https://www.telekom.com",
  "location": "Göttingen, Niedersachsen",
  "city": "Göttingen",
  "region": "Niedersachsen",
  "employmentType": [
    "JOB_EMPLOYMENT_PARTTIME",
    "JOB_EMPLOYMENT_INTERN"
  ],
  "datePosted": "2026-08-11",
  "employerScore": 3.9,
  "salaryMin": null,
  "salaryMax": null,
  "salaryCurrency": null
}
```

#### Company row

```json
{
  "type": "company",
  "slug": "deutsche-telekom",
  "url": "https://www.kununu.com/de/deutsche-telekom",
  "companyId": "ea360420-065c-4ca1-867b-4b177ce8224c",
  "name": "Deutsche Telekom AG",
  "city": "Bonn",
  "state": "Nordrhein-Westfalen",
  "country": "de",
  "website": "https://www.telekom.com",
  "kununuScore": 3.9,
  "reviewCount": 8057,
  "recommendationRate": 78,
  "employeeReviewCount": 7815,
  "applicantReviewCount": 242,
  "salaryCount": 4991,
  "employerSegment": "giant",
  "scoreTrend": "STABLE",
  "scoreTrendDelta": 0.1,
  "isTopCompany": true,
  "isTopCompanyPaid": false,
  "totalLocations": 186,
  "employeeCountText": "ca. 200.000 Mitarbeitenden (31.12.2025)",
  "revenueText": "119,1 Milliarden Euro Umsatz im Jahr 2025",
  "awards": [
    "kununu Top Company",
    "Top Company 2026"
  ],
  "socialLinks": [
    "https://www.facebook.com/TelekomGroupCareers",
    "https://www.youtube.com/user/DeutscheTelekomAG09"
  ],
  "categoryScores": [
    {
      "category": "Karriere",
      "score": 3.8
    },
    {
      "category": "Gehalt/Benefits",
      "score": 3.9
    },
    {
      "category": "Image",
      "score": 3.9
    }
  ]
}
```

#### Review row

```json
{
  "type": "review",
  "reviewKind": "employee",
  "companySlug": "bosch-gruppe",
  "companyName": "Bosch Gruppe",
  "title": "Bosch",
  "rating": 3.2,
  "datePublished": "2026-08-03T00:00:00+00:00",
  "department": "Produktion",
  "location": "Bühl",
  "isCurrentEmployee": false,
  "pros": "Gehalt und bis vor einem jahr war es auch noch ein sicherer Arbeitsplatz",
  "cons": "Stellenabbau und das man nur eine Zahl ist",
  "suggestions": "Mehr auf die Bedürfnisse der Arbeiter eingehen",
  "sections": [
    { "category": "Arbeitsatmosphäre", "text": "Aufgrund des Stellenabbaus sind es überall gemischte Gefühle" }
  ]
}
```

An interview review adds `interviewOutcome` (`"Zusage"` / `"Absage"`), `applicationYear`, and `interviewQuestions`.

***

### Key output fields

`scoreTrend` reads RISING / FALLING / STABLE from the 24-month score delta, and treats a move under 0.2 as STABLE — kununu scores carry one decimal, so ±0.1 is rounding noise that would otherwise flip the trend from one day to the next. `scoreTrendDelta` keeps the raw number.

**Company** — `slug`, `companyId`, `name`, `city`, `state`, `country`, `website`, `logoUrl`, `kununuScore`, `reviewCount`, `recommendationRate`, `employeeReviewCount`, `applicantReviewCount`, `salaryCount`, `categoryScores`, `awards`, `isTopCompany`, `isTopCompanyPaid`, `employerSegment`, `scoreTrend`, `scoreTrendDelta`, `totalLocations`, `employeeCountText`, `revenueText`, `socialLinks`, `benefits`, `reviewSnippets`, `salarySatisfaction`, `topFactors`, `salaries`, `culture`

**Review** — `reviewKind`, `companySlug`, `title`, `rating`, `datePublished`, `department`, `location`, `isCurrentEmployee`, `pros`, `cons`, `suggestions`, `sections`, `interviewOutcome`, `applicationYear`, `interviewQuestions`

**Job** — `jobId`, `url`, `title`, `companyName`, `companyProfileUrl`, `companyWebsite`, `location`, `city`, `region`, `employmentType`, `datePosted`, `employerScore`, `salaryMin`, `salaryMax`, `salaryCurrency`, `salaryPeriod`

***

### FAQ

**Do I need a kununu account or API key?**
No. Only public pages are read.

**Which countries are covered?**
Germany, Austria and Switzerland — kununu's whole footprint. Mix them in one run.

**Do I need a proxy?**
Strongly recommended. kununu challenges datacenter IPs. Residential proxies work reliably; the actor already retries and rotates on a block.

**Is the content in German?**
Yes — reviews, categories and interview questions are in the language people wrote them in, mostly German. Field *names* are English.

**Can I search all kununu jobs by keyword and city?**
No. kununu serves its keyword job search only as a bot-walled web page with no data endpoint behind it, so that input fails with a clear message instead of returning an empty result. Scrape jobs per employer instead: give the actor company names (or company URLs) and turn on `includeJobs`. Every posting still carries the employer's kununu score.

**Why is `salaryMin` empty on some job rows?**
Not every employer publishes a pay range on a posting. When they do, `salaryMin` / `salaryMax` / `salaryCurrency` are filled; otherwise they stay empty rather than being guessed from an estimate.

**How many reviews can I get per employer?**
As many as you set. Reviews come 10 per page, so large employers with thousands of reviews need a higher cap and more time.

**How does incremental mode decide something changed?**
A company changes when its score or review counts move, a job changes when its listing fields move, and reviews are new-or-not. Unchanged rows are dropped before they cost anything.

**Are job descriptions clean text?**
They are returned as the employer submitted them, HTML included. Sanitise before rendering them in a browser, an email or an LLM prompt.

**Why did a few rows come back without a detail?**
When kununu throttles a specific request the actor keeps the base row rather than dropping it, so you get the listing data with the detail fields empty.

***

### Support

Found a bug or need a field that isn't here? Open an issue on the actor's Issues tab. Include the input you ran and the URL involved.

***

### Explore more scrapers

Other employer-review and jobs actors from the same publisher:

- Glassdoor Scraper — reviews, jobs, interviews, salaries
- Trustpilot Scraper — all reviews, no cap, incremental
- AmbitionBox Reviews Scraper — India employer reviews
- TeamBlind Scraper — anonymous workplace reviews
- Xing Scraper — jobs, companies and profiles across DACH
- StepStone, Arbeitsagentur and Pracuj scrapers — European job boards

***

### 🤖 For AI agents & LLM apps

Turn on `compact` to get token-efficient rows with just the core fields — ideal for retrieval pipelines, agent tools and MCP servers. Every row carries a `type` field (`company`, `review`, `job`) so a downstream agent can route without inspecting the shape.

Useful patterns:

- **Employer due diligence** — company row plus 20 reviews gives an agent enough to summarise what working somewhere is actually like.
- **Job matching with reputation** — job rows already carry the employer's score, so an agent can rank openings by employer quality without a second lookup.
- **Interview prep** — applicant reviews supply real questions and outcomes for a specific employer.

Set `includeContactData` to `false` when your pipeline should not ingest personal data.

***

### ⚠️ Disclaimer

This actor collects only publicly available information from kununu.com — pages any visitor can view without logging in. It does not bypass authentication, and it does not collect private or restricted data.

Reviews are personal opinions published by individuals. They are provided as-is, and neither the actor nor its publisher endorses or verifies any statement in them. Job descriptions and employer content are reproduced as published.

You are responsible for how you use the data, including compliance with GDPR and any other applicable law, kununu's terms of use, and any restrictions on personal data. If you are processing personal data, make sure you have a lawful basis for it. The `includeContactData` toggle turns off email and phone extraction where a stricter policy applies.

This actor is not affiliated with, endorsed by, or connected to kununu, New Work SE, or any employer listed on the site. All trademarks belong to their respective owners.

***

### SEO Keywords

kununu scraper, kununu api, scrape kununu, kununu reviews scraper, employer reviews germany, arbeitgeberbewertungen scraper, kununu jobs scraper, german employer reviews api, DACH employer data, kununu company data, employee reviews germany, austria employer reviews, switzerland employer reviews, german salary data scraper, gehalt scraper, employer branding data, kununu score api, interview questions scraper, bewerbungsgespräch daten, german job board scraper, employer reputation monitoring, HR analytics germany, recruitment data DACH, kununu alternative api, employer rating data, glassdoor germany equivalent, company culture data, kulturkompass data, german jobs api, employer benchmark data

# Actor input Schema

## `companyNames` (type: `array`):

Plain company names to look up (e.g. \['Bosch', 'SAP']). Each is resolved straight to its kununu profile, so you do not need to know the URL slug. This is the main way to feed the actor.

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

Paste kununu company profile URLs (https://www.kununu.com/de/bosch-gruppe). Country is read from each URL, so DE/AT/CH can be mixed in one run. Search and job-search URLs are accepted but currently blocked by kununu.

## `countryCode` (type: `string`):

Which kununu country site to search. Applies to searches and company-name lookups; pasted URLs keep their own country.

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

Hard cap on rows written to the dataset — companies, reviews and jobs all count. This is your main cost control, since billing is per row.

## `includeReviews` (type: `boolean`):

Also scrape each employer's individual employee reviews. Every review becomes its own row with title, rating, department, pros, cons, suggestions and the per-category comments.

## `maxReviewsPerCompany` (type: `integer`):

How many employee reviews to pull per employer (10 per page fetched). Large employers have thousands, so keep this bounded.

## `includeApplicantReviews` (type: `boolean`):

Also scrape interview reviews: the outcome (offer / rejection), the year applied, and the interview questions candidates recalled being asked. Each becomes its own row.

## `maxApplicantReviewsPerCompany` (type: `integer`):

How many applicant reviews to pull per employer (10 per page fetched).

## `includeSalaries` (type: `boolean`):

Add the employer's salary table — median pay and range per job title, with the sample size behind each figure. Billed as additional data.

## `includeCulture` (type: `boolean`):

Add kununu's Kulturkompass — modern vs traditional for the employer and its industry, the 0-200 compass scores, and how many submissions it is based on. Billed as additional data.

## `includeJobs` (type: `boolean`):

Also scrape each employer's open jobs. Every job becomes its own row with title, location, contract type, posting date and salary range — plus the employer's kununu score. This is the reliable way to get kununu jobs; the keyword job search below is currently blocked by kununu.

## `maxJobsPerCompany` (type: `integer`):

How many job postings to pull per employer (20 per page fetched). Large employers can have well over a thousand open roles.

## `enrichEmails` (type: `boolean`):

Discover the employer's own website and harvest a contact email from it. Billed as additional data, and only when an email is actually found.

## `includeContactData` (type: `boolean`):

Keep emails and phone numbers found in page text. Turn off to comply with stricter PII policies — those fields are then returned empty.

## `compact` (type: `boolean`):

Return only the core fields per row. Smaller payloads for AI agents and dashboards.

## `flatten` (type: `boolean`):

Flatten nested objects into top-level keys so CSV exports stay readable.

## `incrementalMode` (type: `boolean`):

Track state across runs and emit only what changed — new jobs, new reviews, employers whose score or review count moved. Unchanged rows are dropped before they cost anything.

## `stateKey` (type: `string`):

Names the saved baseline for incremental mode (e.g. 'dach-employers-v1'). Use a different key per monitoring job.

## `telegramToken` (type: `string`):

Your own Telegram bot token from @BotFather, to receive a summary when a run finishes.

## `telegramChatId` (type: `string`):

Chat or channel id the summary is sent to (e.g. -100123456789). Required when a Telegram token is set.

## `slackWebhookUrl` (type: `string`):

Slack incoming webhook to post the run summary to.

## `discordWebhookUrl` (type: `string`):

Discord incoming webhook to post the run summary to.

## `webhookUrl` (type: `string`):

Receives a JSON POST with the run metadata and rows — for n8n, Make, Zapier or your own backend.

## `webhookHeaders` (type: `object`):

Optional headers for the generic webhook, e.g. {"Authorization": "Bearer ..."}.

## `notificationLimit` (type: `integer`):

How many rows to list inside each notification message.

## `notifyOnlyChanges` (type: `boolean`):

With incremental mode on, stay silent when a run finds nothing new.

## `maxConcurrency` (type: `integer`):

How many pages to fetch in parallel. Lower this if you hit rate limits.

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

Proxy used to reach kununu. Residential proxies are strongly recommended — kununu challenges datacenter IPs.

## Actor input object example

```json
{
  "companyNames": [
    "Bosch"
  ],
  "countryCode": "de",
  "maxItems": 100,
  "includeReviews": false,
  "maxReviewsPerCompany": 50,
  "includeApplicantReviews": false,
  "maxApplicantReviewsPerCompany": 50,
  "includeSalaries": false,
  "includeCulture": false,
  "includeJobs": false,
  "maxJobsPerCompany": 50,
  "enrichEmails": false,
  "includeContactData": true,
  "compact": false,
  "flatten": true,
  "incrementalMode": false,
  "notificationLimit": 10,
  "notifyOnlyChanges": true,
  "maxConcurrency": 8,
  "proxy": {
    "useApifyProxy": true
  }
}
```

# 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 = {
    "companyNames": [
        "Bosch"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("memo23/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 = { "companyNames": ["Bosch"] }

# Run the Actor and wait for it to finish
run = client.actor("memo23/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 '{
  "companyNames": [
    "Bosch"
  ]
}' |
apify call memo23/kununu-scraper --silent --output-dataset

```

## MCP server setup

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