# Arbeitsagentur Scraper · German Federal Job Board Listings (`reapx/arbeitsagentur-scraper`) Actor

Arbeitsagentur jobs scraper for Germany's federal employment agency (arbeitsagentur.de / Bundesagentur für Arbeit). Scrape German job listings with employer, salary, location, and contact details.

- **URL**: https://apify.com/reapx/arbeitsagentur-scraper.md
- **Developed by:** [Tarek Etman](https://apify.com/reapx) (community)
- **Categories:** Jobs, Business, Lead generation
- **Stats:** 2 total users, 1 monthly users, 66.7% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.10 / 1,000 job returneds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

![reapX — public sources in, addressable records out](https://reapx.dev/reapx.gif)

## Arbeitsagentur Scraper · German Federal Job Board Listings

**Arbeitsagentur jobs scraper** for Germany's federal job board (arbeitsagentur.de / Bundesagentur für Arbeit). Search and scrape German job listings by keyword, location, radius, employer, contract type, or publication date.

> Maintained by **reapX**. Every row cites the Apify run that produced it — nothing is
> inferred, modelled or filled in, and a field absent from the source is absent from the row.
> The extracted archive for this source is browsable at
> [reapx.dev/data/arbeitsagentur-scraper/](https://reapx.dev/data/arbeitsagentur-scraper/) and mirrored as an open dataset on
> [Hugging Face](https://huggingface.co/datasets/reapxdev/arbeitsagentur-scraper) and
> [Kaggle](https://www.kaggle.com/datasets/reapxdev/arbeitsagentur-scraper). Questions: reapxdev@proton.me

Just under a million postings are live on the board at any time. This Arbeitsagentur scraper reads the agency's own public search service, returning structured job listings from arbeitsagentur.de without a browser.

### Search German jobs by keyword and location

Set **Job title or keyword** in German - `Pflegefachkraft`, `Softwareentwickler`, `LKW-Fahrer` - and optionally a **city or postal code** with a **radius**. A radius search also fills in the distance from your search point on every row, which is what you want for catchment analysis.

Leave every field empty and you get the most recent listings nationwide.

### Filter by working time and contract type

**Working time** covers Vollzeit, Teilzeit, shift work, Heimarbeit and Minijob. **Contract type** separates permanent (unbefristet) from fixed-term (befristet). **Exclude temp agencies** drops Zeitarbeit staffing firms and leaves only direct employers, which is usually what a hiring-market analysis wants.

### Monitor new German job postings

Set **Published within the last N days** to 1 and schedule the Actor daily. Deduplicate on `referenceNumber`, which is permanent per posting. `modifiedAt` moves when an employer edits a live posting, so you can catch changes as well as new listings.

### Track a single employer's hiring

Set **Employer name** to a company - `SAP`, `Siemens`, `Charité` - and you get that employer's open roles across Germany. Every row also carries `employerHash`, a stable pseudonymous key that groups postings from one employer even when the displayed name varies between them.

### What data you get

Every row contains the reference number, job title, standardised occupation, employer, city, postal code, region, country, street where published, latitude and longitude, distance from your search point, publication date, start date, last-modified timestamp, the stable employer key, and a direct posting URL.

Three views are provided: Jobs, Locations and Employers. Export as JSON, CSV, Excel or XML.

### Input configuration

Every field is optional. The prefilled values below are what runs if you press Start without changing anything.

#### What and where

Both are optional. Leave them empty for the newest listings nationwide.

| Field | Type | Accepts | What it does |
| --- | --- | --- | --- |
| `what` | string | free text | What to search for, in German. For example Pflege, Softwareentwickler, Verkäufer, LKW-Fahrer. Leave empty to search every occupation. Prefilled with `"Softwareentwickler"`. |
| `where` | string | free text | Where to search, for example Berlin, München, or 10115. Combine with a radius to cover the surrounding area. Prefilled with `"Berlin"`. |
| `radiusKm` | integer | 0 to 200 | How far around the city or postal code to search. Only applies when a location is set. Prefilled with `25`. |

#### Filters

Narrow the result set. Every filter is optional.

| Field | Type | Accepts | What it does |
| --- | --- | --- | --- |
| `workingTime` | string | one of 6: ``, `vollzeit`, `teilzeit`, `schicht`, ... | Restrict to one working-time model. Prefilled with `""`. |
| `contractType` | string | ``, `permanent`, `fixed-term` | Permanent (unbefristet) or fixed-term (befristet). Prefilled with `""`. |
| `employer` | string | free text | Restrict to one employer, for example SAP, Siemens, or Charité. |
| `publishedWithinDays` | integer | 0 to 100 | Only postings published this recently. Use 1 for a daily monitor, 7 for a weekly one. |
| `excludeTempAgencies` | true/false | checkbox | Drop postings from Zeitarbeit staffing agencies and keep only direct employers. |

#### Output

How many rows you get and how politely they are fetched.

| Field | Type | Accepts | What it does |
| --- | --- | --- | --- |
| `maxJobs` | integer | 1 to 10000 | Hard ceiling on the rows this run produces, and therefore on what it costs. You are charged per job returned. Prefilled with `100`. |
| `requestsPerSecond` | integer | 1 to 8 | Politeness against the federal API. Lower this if you see the source refusing requests. Prefilled with `4`. |

### Pricing

Pay per event. The primary event is **Job returned** (`job-returned`), charged at **$0.002 per event** on the free plan, falling to $0.001 on the highest tier.

One job posting delivered as a complete row. Blocked sources and empty result sets are never charged.

Minimum charge cap per run: $0.02.

Tiered discounts apply automatically on every paid Apify plan. Platform usage is absorbed by the Actor, so the per-event price is the whole price.

### Usage examples

#### The prefilled run, which is what Start does with nothing changed

```json
{
  "what": "Softwareentwickler",
  "where": "Berlin",
  "radiusKm": 25,
  "maxJobs": 100,
  "requestsPerSecond": 4
}
```

#### Filter by job title or keyword

```json
{
  "what": "Pflegefachkraft",
  "where": "Berlin",
  "radiusKm": 25,
  "maxJobs": 100,
  "requestsPerSecond": 4
}
```

#### Filter by city or postal code

```json
{
  "what": "Softwareentwickler",
  "where": "Hamburg",
  "radiusKm": 25,
  "maxJobs": 100,
  "requestsPerSecond": 4
}
```

#### Filter by working time

```json
{
  "what": "Softwareentwickler",
  "where": "Berlin",
  "radiusKm": 25,
  "maxJobs": 100,
  "requestsPerSecond": 4,
  "workingTime": "vollzeit"
}
```

#### Filter by contract type

```json
{
  "what": "Softwareentwickler",
  "where": "Berlin",
  "radiusKm": 25,
  "maxJobs": 100,
  "requestsPerSecond": 4,
  "contractType": "permanent"
}
```

### Output example

One row, exactly as the actor wrote it to the dataset:

```json
{
  "referenceNumber": "12322-YCXCE37Z5GDLME7F-S",
  "jobTitle": "Softwareentwickler (m/w/d)",
  "occupation": "Softwareentwickler/in",
  "employer": "Walter-Fach-Kraft GmbH & Co. KG",
  "city": "Frankfurt am Main",
  "postalCode": "60386",
  "region": "Hessen",
  "country": "Deutschland",
  "street": null,
  "latitude": 50.127193732,
  "longitude": 8.75386232,
  "distanceKm": "9",
  "publishedAt": "2026-07-10",
  "startsAt": "2026-07-10",
  "modifiedAt": "2026-07-10T15:28:34.9",
  "employerHash": "tGz4mt1QwIt4WuSPD3XLAf5n-JOVpy-PwfmLTcfuMp0=",
  "jobUrl": "https://www.arbeitsagentur.de/jobsuche/jobdetail/12322-YCXCE37Z5GDLME7F-S",
  "retrievedAt": "2026-08-03T00:37:23Z"
}
```

#### Fields on every row

| Field | Type | What it is |
| --- | --- | --- |
| `referenceNumber` | string | The job board's own permanent identifier for this posting. Deduplicate on this across runs. |
| `jobTitle` | string | Posting title exactly as the employer wrote it. |
| `occupation` | string | Standardised occupation the federal agency classified the posting under. |
| `employer` | string | Hiring organisation. Null on the small number of postings that withhold it. |
| `city` | string | Place of work. |
| `postalCode` | string | German postal code of the workplace. |
| `region` | string | Federal state or region. |
| `country` | string | Country of the workplace. Mostly Deutschland, occasionally a neighbouring country. |
| `street` | string | Street address where the employer publishes one. About a third of postings do. |
| `latitude` | number | Workplace latitude, for mapping and distance work. |
| `longitude` | number | Workplace longitude. |
| `distanceKm` | string | Kilometres from the searched location. Present only on runs that set a search radius. |
| `publishedAt` | string | Date the posting was published, as YYYY-MM-DD. |
| `startsAt` | string | Earliest start date the employer will accept, as YYYY-MM-DD. |
| `modifiedAt` | string | Timestamp the posting was last changed. Use this to detect edits between runs. |
| `employerHash` | string | Stable pseudonymous employer key. Groups postings from one employer even when the displayed name varies. |
| `jobUrl` | string | Direct link to the posting on arbeitsagentur.de. |
| `retrievedAt` | string | UTC timestamp this row was collected. |

3 named dataset views ship with it: **Jobs**, **Locations**, **Employers**. They drive the Output tab in Console and the Output block on the Actor's `.md` page.

### FAQ

#### Do I need an API key or an account?

No. The Bundesagentur für Arbeit publishes this search service for public use and it needs no user credential.

#### Does the search work in English?

The job board's content is German, so German search terms return far more. `nurse` returns a handful; `Pflegefachkraft` returns tens of thousands.

#### How many jobs can one run return?

As many as you ask for. The service pages 100 at a time and this Actor follows the pages, so the practical limit is your **Maximum jobs to return** and your budget.

#### Why is the street address empty on some rows?

Because the employer did not publish one. About a third of postings include a street; all of them include a city and coordinates.

#### Can I get the full job description?

Not currently. The agency's posting-detail service rejects the public search key, so this Actor returns the search record only - which still carries title, occupation, employer, location, dates and the posting URL.

#### How do I detect new postings between runs?

Deduplicate on `referenceNumber`. It is permanent per posting and never reused.

***

Unofficial - not affiliated with Bundesagentur für Arbeit. Collects public data only. reapx.
Contact reapxdev@proton.me.

### The full published archive

- **[arbeitsagentur scraper archive](https://reapx.dev/data/arbeitsagentur-scraper/)** — every entity this Actor has observed
- **[All reapx datasets](https://reapx.dev/data/)** — 20 sources, tens of thousands of pages
- **[llms.txt](https://reapx.dev/llms.txt)** · **[feed.json](https://reapx.dev/feed.json)** ·
  **[feed.xml](https://reapx.dev/feed.xml)** — the machine-readable index, for agents

Each archive page carries Dataset JSON-LD, a canonical URL and the identifiers used, so an agent
can resolve an entity without running anything. Nothing on those pages is estimated or modelled.

### 🧪 Example input

A real, runnable configuration — this is an actual input this Actor has run with.

```json
{
  "what": "Softwareentwickler",
  "where": "Frankfurt am Main",
  "radiusKm": 25,
  "maxJobs": 500,
  "requestsPerSecond": 4
}
```

### 📄 Sample output

One real row from a real run of this Actor, unedited.

```json
{
  "referenceNumber": "12322-YCXCE37Z5GDLME7F-S",
  "jobTitle": "Softwareentwickler (m/w/d)",
  "occupation": "Softwareentwickler/in",
  "employer": "Walter-Fach-Kraft GmbH & Co. KG",
  "city": "Frankfurt am Main",
  "postalCode": "60386",
  "region": "Hessen",
  "country": "Deutschland",
  "street": null,
  "latitude": 50.127193732,
  "longitude": 8.75386232,
  "distanceKm": "9",
  "publishedAt": "2026-07-10",
  "startsAt": "2026-07-10",
  "modifiedAt": "2026-07-10T15:28:34.9",
  "employerHash": "tGz4mt1QwIt4WuSPD3XLAf5n-JOVpy-PwfmLTcfuMp0=",
  "jobUrl": "https://www.arbeitsagentur.de/jobsuche/jobdetail/12322-YCXCE37Z5GDLME7F-S",
  "retrievedAt": "2026-08-03T00:37:23Z"
}
```

### How it works

1. You set the filters below, or none at all - every field is optional.
2. The Actor calls the public **rest.arbeitsagentur.de** API directly over HTTP. There is no key to obtain, no login and no headless browser, so a run is fast and cannot break on a UI change.
3. It pages through the results until your maximum is reached or the source runs out of matches.
4. Every row is pushed to the dataset **as it is built** - never buffered to the end. A run that hits its time limit still returns everything it collected.
5. You are charged `job-returned` at **$0.002 per row**, and nothing for Apify platform usage. The maximum-results field is therefore your cost cap, and Apify Store discounts apply on top.

### 💬 Your feedback

Found a bug, or need a field this does not return yet? Open an issue on the Actor's **Issues**
tab, or write to **reapxdev@proton.me**. Bugs get fixed and reasonable field requests get
added.

### ⚠️ Run outcomes and error handling

This Actor reports what happened in the run's **status message**, and it always keeps whatever it collected. These are the outcomes you can get and what each one means.

| Outcome | What it means |
|---|---|
| **Success** | Rows were returned and you were charged `job-returned` at $0.002 per row. |
| **No matches** | The source returned nothing for your filters. **Nothing is charged.** Widen the date window or drop a filter. |
| **Partial - source refused** | The source rate-limited or refused some requests. The affected items are skipped and named in the log, and **everything already collected is still pushed**. A block never discards a run's work. |

#### What is guaranteed either way

- **Every row is pushed as it is built**, not buffered to the end of the run. Anything that buffers output loses everything to a timeout, a block or a migration; this does not.
- **A field absent from the source is absent from the row.** Nothing is inferred, modelled or filled in to make a row look complete.

### 🧭 Ready-made configurations

These are saved, published configurations of this exact Actor. Open one and run it as it is, or copy its input as a starting point - each link is a live page with the full input and its output schema.

| Configuration | Input |
|---|---|
| [Nursing Jobs in Berlin - Arbeitsagentur](https://apify.com/reapx/arbeitsagentur-scraper/examples/ba-pflegefachkraft-berlin) | `what`: Pflegefachkraft; `where`: Berlin; `radiusKm`: 25 |
| [Nursing Jobs in München - Arbeitsagentur](https://apify.com/reapx/arbeitsagentur-scraper/examples/ba-pflegefachkraft-munchen) | `what`: Pflegefachkraft; `where`: München; `radiusKm`: 25 |
| [Software Developer Jobs in Berlin - Arbeitsagentur](https://apify.com/reapx/arbeitsagentur-scraper/examples/ba-softwareentwickler-berlin) | `what`: Softwareentwickler; `where`: Berlin; `radiusKm`: 25 |
| [Software Developer Jobs in München - Arbeitsagentur](https://apify.com/reapx/arbeitsagentur-scraper/examples/ba-softwareentwickler-munchen) | `what`: Softwareentwickler; `where`: München; `radiusKm`: 25 |
| [Software Developer Jobs in Hamburg - Arbeitsagentur](https://apify.com/reapx/arbeitsagentur-scraper/examples/ba-softwareentwickler-hamburg) | `what`: Softwareentwickler; `where`: Hamburg; `radiusKm`: 25 |
| [Childcare Educator Jobs in Berlin - Arbeitsagentur](https://apify.com/reapx/arbeitsagentur-scraper/examples/ba-erzieher-berlin) | `what`: Erzieher; `where`: Berlin; `radiusKm`: 25 |
| [Retail Sales Jobs in Hamburg - Arbeitsagentur](https://apify.com/reapx/arbeitsagentur-scraper/examples/ba-verkaufer-hamburg) | `what`: Verkäufer; `where`: Hamburg; `radiusKm`: 25 |
| [Electronics Technician Jobs in Stuttgart - Arbeitsagentur](https://apify.com/reapx/arbeitsagentur-scraper/examples/ba-elektroniker-stuttgart) | `what`: Elektroniker; `where`: Stuttgart; `radiusKm`: 25 |
| [Chef Jobs in München - Arbeitsagentur](https://apify.com/reapx/arbeitsagentur-scraper/examples/ba-koch-munchen) | `what`: Koch; `where`: München; `radiusKm`: 25 |
| [Accountant Jobs in Frankfurt am Main - Arbeitsagentur](https://apify.com/reapx/arbeitsagentur-scraper/examples/ba-buchhalter-frankfurt-am-main) | `what`: Buchhalter; `where`: Frankfurt am Main; `radiusKm`: 25 |
| [Nurse Jobs in Köln - Arbeitsagentur](https://apify.com/reapx/arbeitsagentur-scraper/examples/ba-krankenpfleger-koln) | - |
| [Mechatronics Technician Jobs in Stuttgart - Arbeitsagentur](https://apify.com/reapx/arbeitsagentur-scraper/examples/ba-mechatroniker-stuttgart) | - |
| [Field Service Technician Jobs in Hannover - Arbeitsagentur](https://apify.com/reapx/arbeitsagentur-scraper/examples/ba-servicetechniker-hannover) | - |
| [Sales Representative Jobs in Düsseldorf - Arbeitsagentur](https://apify.com/reapx/arbeitsagentur-scraper/examples/ba-vertriebsmitarbeiter-dusseldorf) | - |

There are **50** of these in total, all listed on the Actor's [**Examples** tab](https://apify.com/reapx/arbeitsagentur-scraper).

# Actor input Schema

## `what` (type: `string`):

What to search for, in German. For example Pflege, Softwareentwickler, Verkäufer, LKW-Fahrer. Leave empty to search every occupation.

## `where` (type: `string`):

Where to search, for example Berlin, München, or 10115. Combine with a radius to cover the surrounding area.<br><br>Leave this field empty to skip this filter.

## `radiusKm` (type: `integer`):

How far around the city or postal code to search. Only applies when a location is set.

## `workingTime` (type: `string`):

Restrict to one working-time model.<br><br>Options: <code></code>, <code>vollzeit</code>, <code>teilzeit</code>, <code>schicht</code>, <code>homeoffice</code>, <code>minijob</code>.

## `contractType` (type: `string`):

Permanent (unbefristet) or fixed-term (befristet).<br><br>Options: <code></code>, <code>permanent</code>, <code>fixed-term</code>.

## `employer` (type: `string`):

Restrict to one employer, for example SAP, Siemens, or Charité.<br><br>Leave this field empty to skip this filter.

## `publishedWithinDays` (type: `integer`):

Only postings published this recently. Use 1 for a daily monitor, 7 for a weekly one.<br><br>The higher the number, the longer the run takes and the more you are charged, because you pay per row returned.

## `excludeTempAgencies` (type: `boolean`):

Drop postings from Zeitarbeit staffing agencies and keep only direct employers.

## `maxJobs` (type: `integer`):

Hard ceiling on the rows this run produces, and therefore on what it costs. You are charged per job returned.<br><br>The higher the number, the longer the run takes and the more you are charged, because you pay per row returned.

## `requestsPerSecond` (type: `integer`):

Politeness against the federal API. Lower this if you see the source refusing requests.

## Actor input object example

```json
{
  "what": "Pflegefachkraft",
  "where": "Hamburg",
  "radiusKm": 25,
  "workingTime": "vollzeit",
  "contractType": "permanent",
  "employer": "SAP",
  "publishedWithinDays": 7,
  "excludeTempAgencies": true,
  "maxJobs": 100,
  "requestsPerSecond": 4
}
```

# Actor output Schema

## `overview` (type: `string`):

One row per posting, with employer, location and a direct link.

## `locations` (type: `string`):

Workplace geography for mapping and catchment analysis.

## `employers` (type: `string`):

Hiring volume per employer, keyed on the stable employer key.

## `results` (type: `string`):

Every record this run produced, with all fields and no view applied. Field-level titles, types, descriptions and examples are declared in the dataset schema.

# 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 = {
    "what": "Softwareentwickler",
    "where": "Berlin",
    "radiusKm": 25,
    "workingTime": "",
    "contractType": "",
    "maxJobs": 100,
    "requestsPerSecond": 4
};

// Run the Actor and wait for it to finish
const run = await client.actor("reapx/arbeitsagentur-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 = {
    "what": "Softwareentwickler",
    "where": "Berlin",
    "radiusKm": 25,
    "workingTime": "",
    "contractType": "",
    "maxJobs": 100,
    "requestsPerSecond": 4,
}

# Run the Actor and wait for it to finish
run = client.actor("reapx/arbeitsagentur-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "what": "Softwareentwickler",
  "where": "Berlin",
  "radiusKm": 25,
  "workingTime": "",
  "contractType": "",
  "maxJobs": 100,
  "requestsPerSecond": 4
}' |
apify call reapx/arbeitsagentur-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=reapx/arbeitsagentur-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/O13aSeOnY1G8S2HP8/builds/GeVZOfI6XKfVNBbcP/openapi.json
