# StepStone Jobs Scraper (`mina_safwat/stepstone-jobs-scraper`) Actor

Scrapes job listings from any StepStone search link (stepstone.de, .at, .be, .nl) with every filter kept: title, company, location, salary, posted date, contract and work type, home-office flag and the full description.

- **URL**: https://apify.com/mina_safwat/stepstone-jobs-scraper.md
- **Developed by:** [Mina](https://apify.com/mina_safwat) (community)
- **Categories:** Jobs, Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$1.00 / 1,000 jobs

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 StepStone Jobs Scraper do?

**StepStone Jobs Scraper** collects **job listings from StepStone**, one of Europe's biggest job boards, on **[stepstone.de](https://www.stepstone.de)** (Germany), **[stepstone.at](https://www.stepstone.at)** (Austria), **[stepstone.be](https://www.stepstone.be)** (Belgium, in English, French or Dutch) and **[stepstone.nl](https://www.stepstone.nl)** (Netherlands). Search on StepStone as you normally would, paste the link, and get every job as a clean row: **title, company, location, home-office option, salary range, posted and expiry dates, contract and work type, benefits, workplace address and the full job description**.

**Every filter in your link is kept**: keywords, place and radius, date posted, full or part time, contract type, home office, salary, experience, industry, sort order and anything else StepStone puts in the address. The Actor hands your link to StepStone's own result list, so you get the jobs the website shows, in the same order. By default you get only the **exact matches**, not the loosely related "similar" jobs StepStone pads its list with.

Try it with the prefilled search: open the Actor, click **Start**, and 25 data scientist jobs in Berlin, with full descriptions, are ready in under 30 seconds. Running on the Apify platform also gives you API access, scheduled runs, integrations (Google Sheets, Make, Zapier, Slack, webhooks) and run monitoring.

### Why scrape StepStone?

- **Labour market research.** Track demand by role, region, contract type and home-office share across Germany, Austria, Belgium and the Netherlands.
- **Salary benchmarking.** StepStone shows a salary range for many German jobs; you get it as numbers you can sort, chart and average.
- **Recruitment and sales leads.** See which companies are hiring, for what and where, with their StepStone company page.
- **Job aggregation.** Feed a niche job board, newsletter or internal tool with fresh, structured listings and descriptions.
- **Monitoring.** Schedule a daily run on a "last 24 hours" search and keep only the job IDs you have not seen.

### How to scrape StepStone jobs

1. Open [stepstone.de](https://www.stepstone.de) (or the Austrian, Belgian or Dutch site) and search: type a job title and a place, then pick any filters.
2. Copy the address from your browser's address bar, for example `https://www.stepstone.de/jobs/data-scientist/in-berlin?radius=30&ag=age_7`.
3. Paste it into **StepStone search links**. Add as many links as you like, one per line; links from different StepStone sites can be mixed.
4. Set **Max jobs per search link** and choose whether to include full descriptions.
5. Click **Start**, then download the results as JSON, CSV, Excel or HTML.

### Input

Everything is set on the Input tab. In JSON, the input looks like this:

```json
{
    "search_urls": [
        "https://www.stepstone.de/jobs/data-scientist/in-berlin?radius=30&ag=age_7",
        "stepstone.at/jobs/data-scientist/in-wien",
        { "url": "https://www.stepstone.be/emplois/data-scientist" }
    ],
    "max_results_per_search": 100,
    "include_description": true,
    "exact_matches_only": true
}
```

| Field | What it does |
|---|---|
| `search_urls` | StepStone search links, one per line, from stepstone.de, stepstone.at, stepstone.be or stepstone.nl. A company's job list on stepstone.de (`stepstone.de/cmp/de/<company>/jobs`) works too. `https://` is optional, and API callers can send `{"url": "…"}` objects. |
| `max_results_per_search` | Stops after this many jobs from each link. Default: 100. |
| `include_description` | Opens each job's own page for the full description (plain text and HTML), contract type, work type, industry and workplace address. Default: on. Turn it off for a faster run with the job cards only. |
| `exact_matches_only` | StepStone lists the jobs that match your search first, then pads the list with similar jobs and jobs from the surrounding area, which often ignore your keywords or filters. Default: on, so you only collect (and pay for) exact matches. Turn it off to also collect the similar and nearby jobs; they are saved and billed like any other job. |
| `proxy_configuration` | Leave empty. The Actor reaches StepStone directly where it can and switches to Apify's proxies on its own when StepStone turns a request away. Choose a proxy only to send every request through it. |

#### Which filters are kept?

All of them, because the link is passed to StepStone as it is. Some examples from stepstone.de:

| On StepStone | In the link | Example |
|---|---|---|
| Job title or keywords | path or `q=` | `/jobs/python`, `/jobs?q=data%20science` |
| Place and radius | path and `radius=` | `/jobs/python/in-hamburg?radius=30` |
| Date posted | `ag=` | `ag=age_1` (last 24 hours), `ag=age_7` (last 7 days) |
| Full or part time | path | `/jobs/vollzeit/data-scientist/in-berlin` |
| Contract type | `ct=` | `ct=222` (permanent) |
| Home office | `wfh=` | `wfh=1` (home office only), `wfh=2` (partly) |
| Salary | `us=` | `us=60000` |
| Experience, industry, field, city | `ex=`, `se=`, `fu=`, `fci=` | `ex=90002` |
| Sort order | `orderByField=` | `orderByField=date` |

The page number in a link is ignored: every search starts from its first page. Click-tracking parameters (`action=`, `searchOrigin=`, `utm_…`) are dropped.

### Output

Each job becomes one row. Here is a real one from the prefilled search, with long texts shortened:

```json
{
    "job_id": 14519393,
    "title": "Data Scientist Supply Chain Consulting (d/w/m)",
    "company_name": "4flow",
    "location": "Berlin",
    "work_from_home": "partial",
    "salary_min": 55000,
    "salary_max": 79000,
    "salary_currency": "EUR",
    "salary_period": "year",
    "salary_is_estimate": true,
    "posted_at": "2026-10-03T07:03:22Z",
    "expires_at": "2026-11-17T07:30:49Z",
    "contract_type": "Feste Anstellung",
    "work_type": "Homeoffice möglich, Vollzeit",
    "employment_types": ["FULL_TIME"],
    "industry": "Wissenschaften, Wissenschaften-Data Science",
    "street_address": "Hallerstraße 1",
    "postal_code": "10587",
    "city": "Berlin",
    "country": "DE",
    "latitude": 52.522575,
    "longitude": 13.324423,
    "description": "Über uns:\n\n4flow – das sind 1500+ Teammitglieder an 20+ Standorten weltweit...",
    "description_html": "<h4>Über uns:</h4>\n<p>4flow – das sind 1500+ Teammitglieder an 20+ Standorten weltweit...",
    "labels": [],
    "benefits": [
        "Spannende internationale Projekte sowie aktive Gestaltung deines Jobprofils und -werdegangs",
        "Persönliche und professionelle Entwicklungsplanung u.a. mit unserem internen Schulungs- und Buddyprogramm"
    ],
    "snippet": "Als Data Scientist bei 4flow vereinst du deine Expertise in Data Science und Consulting mit Logistikwissen...",
    "company_id": 2033,
    "company_url": "https://www.stepstone.de/cmp/de/4flow-2033/jobs",
    "company_logo": "https://www.stepstone.de/upload_DE/logo/7/logo4flow-2033DE-2605281000.gif",
    "url": "https://www.stepstone.de/stellenangebote--Data-Scientist-Supply-Chain-Consulting-d-w-m-Berlin-4flow--14519393-inline.html",
    "match_type": "exact",
    "search_position": 1,
    "search_url": "https://www.stepstone.de/jobs/data-scientist/in-berlin",
    "scraped_at": "2026-10-10T14:28:55Z"
}
```

You can download the dataset in various formats such as JSON, HTML, CSV, or Excel. The Output tab has two views: **Jobs** (the main columns) and **Full details**.

### Data fields

| Field | Description |
|---|---|
| `job_id` | StepStone's job number. |
| `title` | Job title. |
| `company_name` | The hiring company as StepStone shows it. |
| `location` | The place or places as StepStone shows them, for example "Berlin" or "Berlin, Hamburg, München". |
| `work_from_home` | `full` (home office only), `partial` (home office possible), or empty when the listing offers none. |
| `salary_min`, `salary_max` | The salary range StepStone shows on the job card. Empty when it shows none. |
| `salary_currency`, `salary_period` | Currency code (`EUR`) and `year`, `month` or `hour`. |
| `salary_is_estimate` | `true` when the range is StepStone's own estimate for the role and place rather than a figure from the employer. In our tests every range was an estimate, and only stepstone.de showed ranges; pay that an employer states is usually in the description text. |
| `posted_at` | When the job was published, in UTC. |
| `expires_at` | When the listing is due to go offline, in UTC. |
| `contract_type` | The contract as the job page names it, in the site's language, for example "Feste Anstellung" or "Contrat fixe à durée indéterminée". Some listings leave it blank. \* |
| `work_type` | Full or part time and home office as the job page names them, for example "Homeoffice möglich, Vollzeit". \* |
| `employment_types` | The schema.org employment types on the job page, such as `FULL_TIME` or `PART_TIME`. \* |
| `industry` | StepStone's field and sub-field for the job. \* |
| `street_address`, `postal_code`, `city`, `country` | The workplace address on the job page, when the employer gave one; `country` is a two-letter code. \* |
| `latitude`, `longitude` | The workplace's coordinates, when the job page has them. \* |
| `description`, `description_html` | The full job description as plain text and as HTML. \* |
| `labels` | StepStone's badges on the card, such as "Schnelle Bewerbung" (quick apply) or "Anschreiben nicht erforderlich" (no cover letter needed). |
| `benefits` | The benefits listed on the job card, one per item. |
| `snippet` | The short summary StepStone shows in search results. |
| `company_id`, `company_url` | The company's StepStone number and its list of jobs on StepStone. |
| `company_logo` | The company logo, when the listing has one. |
| `url` | Link to the job listing. |
| `match_type` | `exact` for jobs that match your search. With **Exact matches only** turned off, also `similar` for the similar jobs StepStone adds after them and `nearby` for jobs from the surrounding area. |
| `search_position` | The job's position in StepStone's result list. |
| `search_url` | The link you pasted that found this job. |
| `scraped_at` | When the job was collected, in UTC. |

\* Only when **Include full job descriptions** is on; with it off, these fields are left out of the rows.

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

The Actor uses **pay-per-event** pricing: you pay a small fixed price for each job saved, and the exact price is on the **Pricing** tab. **Full descriptions are included at no extra charge.**

You are never charged for links that return nothing: a search with no jobs (or no exact matches, while **Exact matches only** is on), a job ad link or a link that is not from StepStone is listed in the run's `FAILED_INPUTS` record instead. If you set a maximum cost for a run, the Actor stops as soon as it is reached.

### Tips for scraping StepStone

- **Let StepStone filter for you.** Narrow the search on StepStone before copying the link. The filters are applied by StepStone itself, and with **Exact matches only** on (the default) you only collect (and pay for) jobs that match them.
- **Want more than the exact matches?** StepStone pads short result lists with similar jobs and jobs from nearby places, which often ignore your keywords or filters. Turn off **Exact matches only** to collect them too; they are billed like any other job, and `match_type` tells them apart. When a search has no exact matches, its `FAILED_INPUTS` entry says how many similar or nearby jobs were left out.
- **Monitor new jobs.** Choose "Neuer als 24h" (`ag=age_1`) or sort by date, schedule the Actor to run daily, and drop job IDs you already have.
- **Faster runs.** With descriptions on, the Actor opens every job's own page; 300 jobs take about one to two minutes. With descriptions off, 300 jobs take about 25 seconds.
- **Each job is saved once per run**, even when several of your links find it.

### FAQ, disclaimers and support

**Which links work?** Search results pages from stepstone.de, stepstone.at, stepstone.be (English `/jobs/`, French `/emplois/` and Dutch `/vacatures/` pages) and stepstone.nl, plus company job lists on stepstone.de. The StepStone home page, single job ads and older address formats that StepStone itself no longer shows results for are listed in `FAILED_INPUTS` with the reason. Other StepStone-branded addresses (stepstone.fr, stepstone.pl, stepstone.dk and others) redirect elsewhere or run a different site, and are not supported.

**Why do I get fewer jobs than StepStone's total?** StepStone's total counts the "similar" and "nearby" jobs it shows after the exact matches. **Exact matches only** (on by default) leaves them out; turn it off to collect them too, billed like any other job and marked in `match_type`. When nothing matches a search at all, StepStone shows "recommended" jobs that ignore your filters; those are never saved.

**What happens to links that return nothing?** They are not saved as rows, so you are not charged for them. Each is listed with its reason in the `FAILED_INPUTS` record of the run's key-value store, and the run's status message gives the counts. A run fails only when StepStone could not be reached for any of your links.

**A job came without a description?** Very rarely a job page cannot be loaded, or the listing is taken down between the search and the visit. The job is still saved with its card fields, and the run's status message says how many jobs have no description.

**Is it legal to scrape StepStone?** This Actor collects job listings that employers publish publicly so that people can find and apply for them. It does not log in and does not collect candidate data. Listings can still contain a recruiter's name or contact details written by the employer, and their text belongs to the employer; StepStone's robots.txt also asks automated clients to stay away from its search API and filtered result pages. You are responsible for making sure your use complies with StepStone's terms and with the laws that apply to you, such as the GDPR and copyright rules for republishing listings. If in doubt, ask a lawyer.

**Found a problem or need something custom?** Open an issue on the **Issues** tab and we will look into it. Custom scrapers and job data feeds are available on request.

# Actor input Schema

## `search_urls` (type: `array`):

One link per line. Search on stepstone.de, stepstone.at, stepstone.be or stepstone.nl with any filters you like, then copy the address bar: keywords, place and radius, date posted, contract type, full or part time, home office, salary, experience, industry, sort order and the rest are all kept. A company's job list (stepstone.de/cmp/...) works too. Links without https:// are fine.

## `max_results_per_search` (type: `integer`):

Stops after this many jobs from each search link.

## `include_description` (type: `boolean`):

Opens each job's own page for its full description (plain text and HTML), contract type, work type, industry and workplace address. Turn it off for a faster run with the job cards only: title, company, place, home office, salary, dates, benefits and a short snippet.

## `exact_matches_only` (type: `boolean`):

StepStone lists the jobs that match your search first, then pads the list with similar jobs and jobs from the surrounding area, which often ignore your keywords or filters. On by default, so you only collect (and pay for) the exact matches. Turn it off to also collect the similar and nearby jobs the website shows; they are saved and billed like any other job, and each job's match_type field says which kind it is.

## `proxy_configuration` (type: `object`):

Leave this empty. The Actor reaches StepStone directly where it can and switches to Apify's proxies on its own when StepStone turns a request away. Choose a proxy here only to send every request through it.

## Actor input object example

```json
{
  "search_urls": [
    "https://www.stepstone.de/jobs/data-scientist/in-berlin"
  ],
  "max_results_per_search": 25,
  "include_description": true,
  "exact_matches_only": true,
  "proxy_configuration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `dataset` (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 = {
    "search_urls": [
        "https://www.stepstone.de/jobs/data-scientist/in-berlin"
    ],
    "max_results_per_search": 25
};

// Run the Actor and wait for it to finish
const run = await client.actor("mina_safwat/stepstone-jobs-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 = {
    "search_urls": ["https://www.stepstone.de/jobs/data-scientist/in-berlin"],
    "max_results_per_search": 25,
}

# Run the Actor and wait for it to finish
run = client.actor("mina_safwat/stepstone-jobs-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 '{
  "search_urls": [
    "https://www.stepstone.de/jobs/data-scientist/in-berlin"
  ],
  "max_results_per_search": 25
}' |
apify call mina_safwat/stepstone-jobs-scraper --silent --output-dataset

```

## MCP server setup

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