# Arbeitsagentur Jobs API – German Jobbörse jobs (`benelux-signals/arbeitsagentur-jobs-api`) Actor

Job postings from the Bundesagentur für Arbeit Jobbörse (Germany's largest job board, 1M+ jobs) as clean JSON: salary, contract, home office, location, full description. Search by term, city, radius, employer. Only-new mode. From $0.0007/job.

- **URL**: https://apify.com/benelux-signals/arbeitsagentur-jobs-api.md
- **Developed by:** [Benelux Signals](https://apify.com/benelux-signals) (community)
- **Categories:** Jobs, Automation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.70 / 1,000 job postings

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

## Arbeitsagentur Jobs API: Scrape the German Jobbörse (Bundesagentur für Arbeit)

**Get job postings from the Jobbörse of the Bundesagentur für Arbeit, Germany's largest job board with more than 1 million open positions, from $0.0007 per job.** Enter a job title and a city, and the Actor returns one clean, structured record per job: title, employer, occupation, address with postcode, Bundesland and coordinates, full-time/part-time/shift/mini-job, permanent or fixed-term, home-office option, **salary range when the employer gives one**, start date, publication dates, temporary-agency flag and the full job description as plain text.

It reads the same public job-search service that powers [arbeitsagentur.de/jobsuche](https://www.arbeitsagentur.de/jobsuche/). It needs no login, no proxy and no browser, so it is fast (about 100 jobs in 5–20 seconds) and cheap. Searches that fail show up as a free error row and are **never charged**.

### Who is this Jobbörse scraper for?

- **Recruiters, staffing and Personaldienstleister** who want every open *Pflegefachkraft*, *Elektroniker* or *Softwareentwickler* job within 25 km of a city, every morning.
- **Sales and business-development teams** using hiring as a buying signal: an employer posting 20 warehouse jobs in Duisburg needs staff, software and services.
- **Job boards, niche job sites and newsletters** that need a daily feed of new German jobs (use **Only new jobs**).
- **Labour-market researchers, journalists and HR-tech teams** who analyse vacancies per occupation, region, contract type or salary.
- **AI agents and MCP clients**: every field has a safe default; `{"searchTerms": ["Data Engineer"], "locations": ["Berlin"]}` is enough.

### What does it do?

1. Runs one search per **search term × location** (for example 2 terms × 3 cities = 6 searches) with your radius in km.
2. Applies the Jobbörse's own filters: offer type (job, apprenticeship/Ausbildung, internship/trainee, self-employment), working time, contract type, posting age, employer name, and excluding temporary agencies (Zeitarbeit) or private recruiters.
3. Opens each job for the full description, salary, contract, home-office and start-date details (switch **Include description** off for a faster and leaner list-only run).
4. Normalises everything: ISO dates, Bundesland names, `full-time` / `part-time` / `shift-night-weekend` / `mini-job`, `permanent` / `fixed-term`, salaries as numbers with a period (`year`, `month`, `hour`).
5. Removes duplicates across searches and, in **Only new jobs** mode, skips jobs you already received in earlier runs. Skipped jobs are free.

**Privacy:** the Actor collects job and employer information only. E-mail addresses and phone numbers in descriptions are replaced by `[email removed]` and `[phone removed]`, and the employer name is cleaned of attention lines such as "z. Hd. Frau …". There are no separate contact-person fields.

### Input example

```json
{
    "searchTerms": ["Pflegefachkraft", "Elektroniker"],
    "locations": ["Köln", "München"],
    "radiusKm": 15,
    "offerType": "job",
    "workingTime": ["full-time"],
    "contractType": "permanent",
    "postedWithinDays": 14,
    "excludeTemporaryAgencies": true,
    "includeDescription": true,
    "maxResults": 400,
    "maxResultsPerSearch": 100
}
```

| Field | What it does | Default |
|---|---|---|
| `searchTerms` | Job titles or keywords (German titles give the most results). Empty = all jobs | `Data Engineer` |
| `locations` | City, postcode or region. Empty = all of Germany | empty |
| `radiusKm` | Radius around each location (0–200) | `25` |
| `employer` | Only jobs from this employer name | empty |
| `offerType` | `any`, `job`, `apprenticeship`, `internship-trainee`, `self-employment` | `any` |
| `workingTime` | `full-time`, `part-time`, `shift-night-weekend`, `mini-job` | all |
| `contractType` | `any`, `permanent`, `fixed-term` | `any` |
| `postedWithinDays` | Only jobs published in the last N days (0 = any, max 100) | `0` |
| `excludeTemporaryAgencies` / `excludePrivateRecruiters` | Drop Zeitarbeit / private recruitment agencies | `false` |
| `homeOfficeOnly` / `withSalaryOnly` | Only jobs with home office / with a salary | `false` |
| `excludeKeywords` | Drop jobs whose title contains any of these words | empty |
| `includeDescription` | Fetch the full description and details | `true` |
| `onlyNewJobs` / `stateKey` | Incremental mode for schedules | `false` / `default` |
| `maxResults` / `maxResultsPerSearch` | Cost caps | `200` / `0` |

**Tip:** with several searches and a small `maxResults`, the first search can fill the whole quota. Set `maxResultsPerSearch` to spread results evenly. The Jobbörse returns at most 10,000 jobs per search; split very broad searches by city or term.

### Output example

```json
{
    "status": "ok",
    "charged": true,
    "jobId": "ba:10001-1002345678-S",
    "referenceNumber": "10001-1002345678-S",
    "title": "Pflegefachkraft (m/w/d) Intensivstation",
    "company": "Universitätsklinikum Köln AöR",
    "occupation": "Gesundheits- und Krankenpfleger/in",
    "offerType": "job",
    "city": "Köln",
    "postalCode": "50937",
    "state": "Nordrhein-Westfalen",
    "countryCode": "DE",
    "latitude": 50.92,
    "longitude": 6.92,
    "distanceKm": 3,
    "fullTime": true,
    "partTime": true,
    "workingTimes": ["full-time", "part-time-flexible", "shift-night-weekend"],
    "contractType": "permanent",
    "homeOfficePossible": false,
    "salaryMin": 3900,
    "salaryMax": 4600,
    "salaryPeriod": "month",
    "salaryCurrency": "EUR",
    "salaryText": "3.900–4.600 EUR / month",
    "temporaryAgency": false,
    "startDate": "2026-12-01",
    "publishedAt": "2026-10-27",
    "jobUrl": "https://www.arbeitsagentur.de/jobsuche/jobdetail/10001-1002345678-S",
    "externalUrl": null,
    "description": "Wir suchen ab sofort ... Bewerbung an [email removed]",
    "searchTerm": "Pflegefachkraft",
    "searchLocation": "Köln",
    "scrapedAt": "2026-10-28T09:15:00.000Z"
}
```

Status values: `ok` (a job, charged), `error` (a search failed, free), `no_results` (nothing matched or no new jobs, free). Every run also stores a `RUN_SUMMARY` record with per-search counts (jobs on the Jobbörse, listed, saved, duplicates, filtered out).

### How much does it cost?

Pay per event, with platform usage included:

| Event | Free plan | Bronze | Silver | Gold and up |
|---|---|---|---|---|
| Job posting | $0.001 | $0.0009 | $0.0008 | $0.0007 |
| Actor start (per run) | $0.005 | | | |

1,000 jobs cost about $1 on the Free plan, 10,000 jobs about $7 on Gold. Error rows, no-results rows, duplicates, filtered-out jobs and jobs skipped by only-new mode are free. Use **Max results** and Apify's maximum cost per run to stay within budget.

### FAQ

**Is it legal to scrape the Jobbörse?** The Actor only reads public job postings that anyone can see on arbeitsagentur.de without an account, through the public job-search service, at a polite request rate. It removes e-mail addresses and phone numbers and does not output contact persons. You are responsible for how you use the data (for example GDPR and the employers' rights when republishing).

**Why do I get fewer jobs than on the website?** The website counts every location of a multi-location job; the Actor lists each job once and removes duplicates. Check `RUN_SUMMARY` for the number found per search.

**Why are there jobs from other cities in my location search?** The Jobbörse adds nationwide postings ("bundesweit", field-sales and promoter jobs) to every location search, with `distanceKm` 0 and the employer's head office as the city. Add `excludeKeywords` such as `bundesweit` to drop them.

**Does it work in English?** Yes, the input and output are in English, but the job content is German. Search with German job titles (`Erzieher`, `Lagerhelfer`) for the best results.

**Can I schedule a daily feed?** Yes. Create a task, turn on **Only new jobs**, and schedule it. Only jobs you have not received before are saved and charged.

**Is this an official API of the Bundesagentur für Arbeit?** No. This Actor is independent and not affiliated with or endorsed by the Bundesagentur für Arbeit.

### Related actors by benelux-signals

Cover the rest of the European job market:

- [Career Site Jobs API](https://apify.com/benelux-signals/eu-career-site-jobs-api) – jobs straight from Greenhouse, Lever, Recruitee, Personio, Ashby and other company career sites.
- [Workday Jobs API](https://apify.com/benelux-signals/workday-jobs-api-europe) – jobs from any myworkdayjobs.com career site, with a European employer seed list.
- [Remote Jobs Aggregator](https://apify.com/benelux-signals/remote-jobs-aggregator) – Europe-friendly remote jobs from RemoteOK, We Work Remotely, Jobicy and more, deduplicated.

More tools from the same maintainer:

- [EU Tender Radar](https://apify.com/benelux-signals/eu-tender-radar) – TED + TenderNed public tenders with keyword/CPV filters and only-new alerts.
- [Benelux Trade Fair Exhibitors](https://apify.com/benelux-signals/benelux-trade-fair-exhibitors) – exhibitor lists from Dutch and Belgian trade fairs (Horecava, METSTRADE, Batibouw…) for B2B lead lists.
- [Bulk PageSpeed & SEO Audit](https://apify.com/benelux-signals/bulk-pagespeed-seo-audit) – Core Web Vitals, Lighthouse scores and on-page SEO checks for many URLs or a sitemap.
- [EU & Dutch News Monitor](https://apify.com/benelux-signals/eu-news-rss-monitor) – keyword alerts across 80+ built-in Dutch, Belgian and EU news and official RSS feeds.
- [PDF & Image to Text OCR](https://apify.com/benelux-signals/pdf-image-to-text-ocr) – text and Markdown from PDFs and scans, ready for RAG and AI agents.
- [Technical SEO Site Crawler](https://apify.com/benelux-signals/technical-seo-site-crawler) – crawl a site for broken links, redirects, missing titles/meta, canonicals and noindex issues.

Questions or a source we should add? Open an issue on the Actor page.

# Actor input Schema

## `searchTerms` (type: `array`):

What to search for on the Jobbörse of the Bundesagentur für Arbeit, e.g. "Data Engineer", "Pflegefachkraft", "Elektroniker". German or English terms both work. Each term is a separate search. Leave empty to list all jobs (combine with locations, employer or filters).

## `locations` (type: `array`):

Where to search, e.g. "Berlin", "München", "50667", "Bayern". Every search term is combined with every location. Leave empty for all of Germany.

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

Distance around each location, 0–200 km. Only used when locations are set.

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

Only jobs from this employer as it appears on the Jobbörse, e.g. "Deutsche Bahn AG". Optional.

## `offerType` (type: `string`):

Type of offer (Angebotsart).

## `workingTime` (type: `array`):

Keep jobs that offer any of these working-time models. Empty = all.

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

Contract duration.

## `postedWithinDays` (type: `integer`):

Only jobs whose current publication started within the last N days (for example 1 = since yesterday, 7 = last week). 0 = any date. Max 100.

## `excludeTemporaryAgencies` (type: `boolean`):

Leave out jobs from temporary employment agencies (Arbeitnehmerüberlassung).

## `excludePrivateRecruiters` (type: `boolean`):

Leave out jobs posted by private placement agencies.

## `homeOfficeOnly` (type: `boolean`):

Keep only jobs where the employer marks home office / remote work as possible.

## `withSalaryOnly` (type: `boolean`):

Keep only jobs that publish a salary (fixed amount or range).

## `excludeKeywords` (type: `array`):

Skip jobs whose title, company or occupation contains any of these words (case-insensitive), e.g. "Praktikum", "Minijob".

## `includeDescription` (type: `boolean`):

Fetch the full description for every job (one extra request per job). E-mail addresses and phone numbers are removed from the text. Turn off for faster, list-only runs.

## `onlyNewJobs` (type: `boolean`):

Skip (and don't charge) jobs this Actor already delivered in an earlier run with the same stateKey. Ideal for scheduled daily runs. Delivered IDs are remembered for 180 days.

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

Name of the memory used by only-new mode. Use a different key per schedule/search to keep them separate.

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

Stop after this many jobs (you are only charged for saved jobs). The Jobbörse returns at most 10,000 jobs per search – split big searches by location or term.

## `maxResultsPerSearch` (type: `integer`):

Optional cap per search (term × location), so one big search doesn't use the whole maxResults. 0 = no cap.

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

How many job descriptions to fetch in parallel (1–16).

## Actor input object example

```json
{
  "searchTerms": [
    "Data Engineer"
  ],
  "locations": [
    "Berlin"
  ],
  "radiusKm": 25,
  "offerType": "any",
  "contractType": "any",
  "postedWithinDays": 0,
  "excludeTemporaryAgencies": false,
  "excludePrivateRecruiters": false,
  "homeOfficeOnly": false,
  "withSalaryOnly": false,
  "includeDescription": true,
  "onlyNewJobs": false,
  "stateKey": "default",
  "maxResults": 50,
  "maxResultsPerSearch": 0,
  "maxConcurrency": 8
}
```

# Actor output Schema

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

All job postings in the 'overview' table view.

## `runSummary` (type: `string`):

JSON summary (jobs saved, charged count, per-search stats, filtered-out, already-seen and duplicate counts) stored under RUN_SUMMARY.

# 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 = {
    "searchTerms": [
        "Data Engineer"
    ],
    "locations": [
        "Berlin"
    ],
    "maxResults": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("benelux-signals/arbeitsagentur-jobs-api").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 = {
    "searchTerms": ["Data Engineer"],
    "locations": ["Berlin"],
    "maxResults": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("benelux-signals/arbeitsagentur-jobs-api").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 '{
  "searchTerms": [
    "Data Engineer"
  ],
  "locations": [
    "Berlin"
  ],
  "maxResults": 50
}' |
apify call benelux-signals/arbeitsagentur-jobs-api --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,benelux-signals/arbeitsagentur-jobs-api"
        }
    }
}
```

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/2GBrf7fb6i5l4QcSt/builds/w1Q5F2YPFQ2dlG0MD/openapi.json
