# Arbeitsagentur Jobs Scraper - German Jobbörse (Public API) (`rjmacarthy/arbeitsagentur-jobs-scraper`) Actor

Scrape Germany's official job board (Bundesagentur für Arbeit Jobbörse) via its public API: every filter incl. radius, Ausbildung, part-time, employer, home office; parsed geo and salary; optional full descriptions; only-new-jobs feed. No login.

- **URL**: https://apify.com/rjmacarthy/arbeitsagentur-jobs-scraper.md
- **Developed by:** [rj](https://apify.com/rjmacarthy) (community)
- **Categories:** Jobs, Automation
- **Features:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 job listings

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

## Arbeitsagentur Jobs Scraper - Germany's Official Job Board (Jobbörse)

Scrape job listings from the **Bundesagentur für Arbeit Jobbörse** (arbeitsagentur.de), Germany's largest job board with around a million vacancies, apprenticeships (Ausbildung) and internships. Search with the same filters as the website: keywords, city or postcode, **radius**, **offer type** (job, Ausbildung / duales Studium, Praktikum / trainee, self-employment), **working time** (full-time, part-time, shift, mini-job), **permanent or temporary contract**, **published in the last N days**, **employer** and **home office**. You get clean JSON with English field names, **parsed geo coordinates**, numeric **salary** and **apprenticeship pay per year**. Add **full job descriptions** as a cheap optional extra, and use **Only new jobs** to turn a daily schedule into a feed of fresh vacancies.

Why this one: every Jobbörse filter in one place, full descriptions only when you want them (and only charged when they're fetched), an only-new-jobs feed without a monitor fee, no start fee, and $0.001 per job. Contact persons, emails and phone numbers are never output.

This is an unofficial tool. It uses the public Jobbörse API (the open-data key documented on bund.dev), not a login.

### What data can you get?

| Field | Example |
|---|---|
| `id` (Referenznummer), `url` | 10001-1003891446-S, https://www.arbeitsagentur.de/jobsuche/jobdetail/10001-1003891446-S |
| `title`, `employer` | Softwareentwicklerin (w/m/d), GASAG AG |
| `profession`, `professions` | Softwareentwickler/in |
| `offerType` | `job`, `apprenticeship`, `internship`, `selfEmployment` |
| `location` {street, zip, city, region, country, lat, lon}, `otherLocations` | EUREF-Campus 23-24, 10829, Berlin, BERLIN, 52.48, 13.36 |
| `distanceKm` | Distance from the searched location |
| `workingTime` | \["fullTime", "partTimeMorning", "shiftNightWeekend", "miniJob", ...] |
| `homeOfficePossible`, `homeOfficePercent` | true, 50 |
| `contractType`, `contractMonths` | `temporary`, 24 |
| `salaryMin`, `salaryMax`, `salaryPeriod`, `salaryCurrency` | 72600, 72600, `year`, EUR |
| `apprenticeshipPayMonthly` | \[1050, 1239, 1418, 1470] (EUR per training year) |
| `suitableForCareerChangers` | Quereinstieg possible |
| `publishedAt`, `firstPublishedAt`, `modifiedAt`, `entryDate` | 2026-10-21 |
| `externalUrl` | Original ad on the employer's or a partner's site |
| `description`\* | Full job description (Markdown) |
| `isTempAgency`\*, `isPrivatePlacement`\* | Zeitarbeit / private recruiter flags |
| `requiredEducation`\*, `sourcePartner`\* | HAUPTSCHULABSCHLUSS, Studyflix GmbH |
| `detailsStatus`, `searchQuery`, `scrapedAt` | Provenance and status |

\* Needs **Fetch full job details**.

### Use cases

- **Job boards and aggregators:** repost Jobbörse vacancies with a daily **Only new jobs** feed.
- **Recruiting and staffing agencies:** find which employers are hiring which professions, where, and with which contract.
- **Ausbildung and dual-study portals:** list apprenticeships with training pay per year and required school certificate.
- **Salary and labour-market research:** pay ranges, part-time and home-office share, temporary vs permanent mix by city and profession.
- **Lead generation (company level):** employers hiring in your niche, with company address and coordinates.

### How to use

1. Enter one or more **Search queries** (each is a separate search; German job titles work best) and a **Location** (city or postcode).
2. Optionally set **Radius**, **Offer type**, **Working time**, **Contract**, **Published in the last N days**, **Employer** or **Home office only**.
3. Set **Max jobs per search** and, if you want descriptions, turn on **Fetch full job details**.
4. Run, then download the results as JSON, CSV, Excel or via the API.

Software developer jobs in Berlin:

```json
{ "queries": ["Softwareentwickler"], "location": "Berlin", "maxItems": 15 }
```

Apprenticeships (Ausbildung) as Mechatroniker near Munich:

```json
{ "queries": ["Mechatroniker"], "location": "München", "radiusKm": 50, "offerType": "apprenticeship", "maxItems": 50 }
```

Part-time permanent nursing jobs in Hamburg from the last 7 days, with descriptions:

```json
{ "queries": ["Pflegefachkraft"], "location": "Hamburg", "employmentTypes": ["partTime"], "contractType": "permanent",
  "publishedSinceDays": 7, "fetchDetails": true, "maxItems": 100 }
```

Daily feed of new jobs at one employer:

```json
{ "employer": "Deutsche Bahn AG", "maxItems": 0, "onlyNew": true, "stateKey": "deutsche-bahn" }
```

### Output example

```json
{
  "id": "10001-1003891446-S",
  "title": "Softwareentwicklerin (w/m/d)",
  "employer": "GASAG AG",
  "profession": "Softwareentwickler/in",
  "professions": [
    "Softwareentwickler/in"
  ],
  "offerType": "job",
  "location": {
    "street": "EUREF-Campus 23-24",
    "zip": "10829",
    "city": "Berlin",
    "region": "BERLIN",
    "country": "DEUTSCHLAND",
    "lat": 52.480611,
    "lon": 13.356027
  },
  "otherLocations": [],
  "distanceKm": 6,
  "workingTime": [
    "fullTime"
  ],
  "homeOfficePossible": true,
  "homeOfficePercent": 50,
  "contractType": "temporary",
  "contractMonths": 24,
  "salaryMin": 72600,
  "salaryMax": 72600,
  "salaryPeriod": "year",
  "salaryCurrency": "EUR",
  "apprenticeshipPayMonthly": null,
  "suitableForCareerChangers": null,
  "publishedAt": "2026-10-21",
  "firstPublishedAt": "2026-10-21",
  "modifiedAt": "2026-10-22T12:54:32.215",
  "entryDate": "2026-10-22",
  "externalUrl": null,
  "url": "https://www.arbeitsagentur.de/jobsuche/jobdetail/10001-1003891446-S",
  "description": "Wir suchen dich an unserem Standort in Berlin-Schöneberg **zum nächstmöglichen Zeitpunkt,befristet für 2 Jahre und in Vollzeit (38,5h)** als\n\n## **Softwareentwi...",
  "isTempAgency": null,
  "isPrivatePlacement": null,
  "requiredEducation": null,
  "sourcePartner": null,
  "detailsStatus": "ok",
  "searchQuery": "Softwareentwickler",
  "scrapedAt": "2026-11-06T12:25:36.021Z"
}
```

### Pricing

Pay per event, no start fee, no monthly fee:

| Event | Price | When |
|---|---|---|
| `job` | $0.001 | Each job listing output |
| `job-details` | $0.0005 | Each job whose full details were fetched (**Fetch full job details** on) |

- **1,000 jobs ≈ $1.00**
- **1,000 jobs with full descriptions ≈ $1.50**
- **Only new jobs** has no surcharge: you pay only for the new jobs that are output.
- Set **Maximum cost per run** in the run options; the Actor stops cleanly when it is reached.
- A job whose details couldn't be fetched (expired, refused) is not charged `job-details`.

### Tips and limits

- Results come in the Jobbörse's own order (relevance/distance), 100 per API page.
- **Home office only** is applied after fetching, because the Jobbörse API has no working home-office filter. The run reads up to 30 pages per search (3,000 listings) to find matches, and only home-office jobs are output and charged. Many employers don't state home office at all (`homeOfficePossible: null`); those are excluded.
- **Employer** must match the name as shown on the Jobbörse (e.g. "Deutsche Bahn AG").
- Salary is only present when the employer gives it; `salaryPeriod` is `year`, `month` or `hour`. Apprenticeship pay is in `apprenticeshipPayMonthly`.
- `modifiedAt` is German local time without a time zone, exactly as the API returns it. Dates are YYYY-MM-DD.
- `detailsStatus` tells you per job whether details were fetched (`ok`), the job had expired (`not-found`) or the request failed/was refused. `RUN_SUMMARY` in the key-value store counts these.
- For **Only new jobs**, use a different **State key** per feed. Seen jobs are forgotten after 90 days. Feed runs read at most 30 pages (3,000 listings) per search, so keep each search narrower than that.
- Not available from the public API: number of open positions, company size and industry.

### FAQ

**Is it legal?**
The Actor reads only public job listings through the Jobbörse's public API, without logging in. It does not collect personal data: contact-person fields are never output (only an allow-list of job fields is copied), and email addresses, phone numbers (including WhatsApp links) and contact names in descriptions are replaced with `[email removed]`, `[phone removed]` and `[name removed]`. Name removal is pattern-based (salutations such as "Frau ...", labels such as "Ansprechpartner: ..."), so an unusual phrasing can slip through; report it and we'll add the pattern. Employer company name and address are kept. You are responsible for using the data in line with GDPR, the Bundesagentur's terms and other laws that apply to you.

**Is this an official Bundesagentur für Arbeit product?**
No. It's an independent tool that uses the public Jobbörse API (key `jobboerse-jobsuche`, documented at bund.dev).

**Do I need a proxy?**
Normally not. If you see HTTP 403/429, enable Apify Proxy (datacenter). Residential proxies are not supported: if you pick the RESIDENTIAL group, the Actor logs a warning and uses Apify datacenter proxy instead.

**Can I search several job titles at once?**
Yes. Each query is a separate search with its own **Max jobs per search** limit; a job found by several searches is output once per run.

**Why are `description` and some flags null?**
They come from the job-details request, so they're null unless **Fetch full job details** is on.

**Can I search in English?**
The Jobbörse is German: "Softwareentwickler" finds far more than "software developer". Output field names are English.

### Integrations

- **API:** run the Actor and fetch the dataset with the Apify API or the `apify-client` libraries for JavaScript and Python.
- **Make, Zapier, n8n:** run it on a schedule and send new jobs to Google Sheets, Airtable, Slack or email.
- **MCP:** AI agents can call this Actor through the Apify MCP server (`mcp.apify.com`).
- **Webhooks:** get notified when a run finishes and pull the new items.

### Changelog

- **0.1** (November 2026): first release. All Jobbörse search filters, parsed geo and salary, optional full details, Only new jobs mode.

### Ready-to-run examples

- [Scrape Pflegefachkraft (nurse) jobs in Hamburg](https://apify.com/rjmacarthy/arbeitsagentur-jobs-scraper/examples/pflegefachkraft-jobs-hamburg-arbeitsagentur)
- [Find Mechatroniker apprenticeships (Ausbildung) in Munich](https://apify.com/rjmacarthy/arbeitsagentur-jobs-scraper/examples/mechatroniker-ausbildung-muenchen-arbeitsagentur)

### More scrapers by the same developer

- [Apna Jobs Scraper - India Jobs by Keyword, City & Category](https://apify.com/rjmacarthy/apna-jobs-scraper)
- [ATS Jobs Scraper: Greenhouse, Lever, Ashby & Workday](https://apify.com/rjmacarthy/ats-jobs-scraper)
- [Cutshort Jobs Scraper - India Startup & Tech Jobs](https://apify.com/rjmacarthy/cutshort-jobs-scraper)
- [Dice Jobs Scraper](https://apify.com/rjmacarthy/dice-jobs-scraper)
- [Instahyre Jobs Scraper: India Tech Jobs, Salary & Skills](https://apify.com/rjmacarthy/instahyre-jobs-scraper)
- [Reed.co.uk Jobs Scraper - UK Job Listings with Salary](https://apify.com/rjmacarthy/reed-jobs-scraper)

Browse all my Actors on [my Apify Store profile](https://apify.com/rjmacarthy).

### Support

Found a search that doesn't work, or need an extra field? Open an issue on the **Issues** tab with your input. Fixes are usually quick.

# Actor input Schema

## `queries` (type: `array`):

Job titles or keywords, one search per line, e.g. "Softwareentwickler", "Pflegefachkraft", "Mechatroniker". German terms work best. Leave empty to list all jobs for the location/employer.

## `location` (type: `string`):

City or postcode, e.g. "Berlin", "München" or "10115". Leave empty for all of Germany.

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

Search radius around the location (umkreis). 0 = the Jobbörse default. Only used with a location.

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

Regular jobs, apprenticeships (Ausbildung / duales Studium), internships/trainee programmes or self-employment offers.

## `employmentTypes` (type: `array`):

Only jobs offering one of these working-time models (arbeitszeit). Leave empty for all.

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

Permanent (unbefristet) or temporary (befristet) contracts only.

## `publishedSinceDays` (type: `integer`):

Only jobs published in the last N days (0-100; 0 = today). Leave empty for any date.

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

Exact employer name as shown on the Jobbörse, e.g. "Deutsche Bahn AG".

## `remoteOnly` (type: `boolean`):

Only jobs that state home office is possible. The Jobbörse API has no working home-office filter, so this is applied after fetching: the run reads more result pages (up to 30 per search) and only home-office jobs are output and charged.

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

Maximum jobs to output for each search query. 0 = no limit.

## `fetchDetails` (type: `boolean`):

Make one extra request per job for the full description, temp-agency / private-placement flags, required education and source partner. Charged as an extra "job-details" event per job. Emails, phone numbers and contact-person names are removed from descriptions.

## `onlyNew` (type: `boolean`):

Skip jobs this Actor already output in earlier runs with the same state key (remembered in a named key-value store). Schedule it daily for a new-jobs feed. The first run outputs everything and becomes the baseline.

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

Name of the job-alert memory used by "Only new jobs". Use a different key for each separate alert/schedule.

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

Not needed normally: the Jobbörse API answers Apify's servers directly. Enable Apify Proxy (datacenter) only if you see HTTP 403/429. Residential proxies are not supported and fall back to datacenter proxy.

## Actor input object example

```json
{
  "queries": [
    "Softwareentwickler"
  ],
  "location": "Berlin",
  "radiusKm": 0,
  "offerType": "any",
  "employmentTypes": [],
  "contractType": "any",
  "remoteOnly": false,
  "maxItems": 15,
  "fetchDetails": false,
  "onlyNew": false,
  "stateKey": "default",
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `jobs` (type: `string`):

One item per job: title, employer, location, working time, home office, salary, dates and URL.

## `jobsFull` (type: `string`):

Every field per job, incl. geo coordinates, contract details and (with fetchDetails) the full description.

## `summary` (type: `string`):

Per-search status, counts, request statistics and warnings.

# 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 = {
    "queries": [
        "Softwareentwickler"
    ],
    "location": "Berlin",
    "maxItems": 15
};

// Run the Actor and wait for it to finish
const run = await client.actor("rjmacarthy/arbeitsagentur-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 = {
    "queries": ["Softwareentwickler"],
    "location": "Berlin",
    "maxItems": 15,
}

# Run the Actor and wait for it to finish
run = client.actor("rjmacarthy/arbeitsagentur-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 '{
  "queries": [
    "Softwareentwickler"
  ],
  "location": "Berlin",
  "maxItems": 15
}' |
apify call rjmacarthy/arbeitsagentur-jobs-scraper --silent --output-dataset

```

## MCP server setup

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