# Arbeitsagentur Jobs Scraper (`deriverge/arbeitsagentur-jobs-scraper`) Actor

Job adverts from the Jobsuche of Germany's Federal Employment Agency, with pay, working time, workplace address and the full advert text. Search by keyword, city or postcode and radius; one search can return more than the 10,000 results the website shows.

- **URL**: https://apify.com/deriverge/arbeitsagentur-jobs-scraper.md
- **Developed by:** [deriverge s.r.o.](https://apify.com/deriverge) (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

from $0.15 / 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.
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 Scraper

The Jobsuche of the Bundesagentur für Arbeit is Germany's public job board, with more than 1 million offers in September 2026. This actor returns one row per advert: title, employer, occupation, workplace with coordinates, contract, working time, pay when the employer states it and the full advert text. Type a job title in German, such as `Pflegefachkraft`, add a city and click **Start**. The contact person block of an advert is not collected. It costs $0.30 per 1,000 jobs on the Free plan ($0.15 on Business), and the $5 of monthly credit in Apify's Free plan covers about 16,000 jobs.

### Fields in each advert

| Field | Description |
|---|---|
| `title`, `occupation` | Advert title as the employer wrote it, and the occupation Arbeitsagentur files it under, e.g. `Pflegefachmann/-frau (Gesundheits- und Krankenpflege)`. |
| `offerType` | `Job`, `Apprenticeship or dual study`, `Internship, trainee or working student` or `Self-employment`. |
| `company`, `employerId` | Employer name, empty when the employer stays anonymous, and a hashed ID that is the same on every advert of one employer account. |
| `street`, `postalCode`, `city`, `state` | Workplace address. The city is almost always there; the street on about a third of adverts. |
| `latitude`, `longitude` | Coordinates of the workplace, filled on nearly every advert. |
| `locations` | Every workplace with its address and coordinates, for adverts that name several. |
| `contract`, `fixedTermMonths` | `Permanent` or `Fixed-term`, empty when the advert does not say, and the length of a fixed-term contract in months. |
| `workingTime`, `miniJob` | Working-time models such as `Full-time`, `Part-time mornings` or `Shifts, nights or weekends`, and `true` for a Minijob. |
| `homeOffice`, `homeOfficeType`, `homeOfficePercent` | `true` when working from home is possible, then `By arrangement` or `Share of working time` with the share in percent. |
| `salaryMin`, `salaryMax`, `salaryPeriod` | Pay in euros as numbers per `year`, `month` or `hour`, for example `35640` to `39252` per `year`. Empty when the advert names no pay. |
| `trainingPayPerMonth` | Monthly pay for each year of an apprenticeship, e.g. `[1492, 1533, 1617]`. |
| `requiredEducation` | School certificate an apprenticeship asks for, e.g. `Intermediate school certificate (Mittlere Reife)`. |
| `temporaryAgency`, `privateRecruiter` | `true` when a temporary employment agency (Zeitarbeit) or a private recruitment agency posted the advert. |
| `source`, `externalUrl` | Who supplied the advert: `arbeitsagentur.de`, a partner board such as `jobvector.de`, or the employer's own system. `externalUrl` links to the advert on the partner board. |
| `publishedAt`, `startDate` | Date of first publication and the earliest start date, as `YYYY-MM-DD`. |
| `description` | Full advert text with the formatting marks the Jobsuche uses, such as `#` for headings and `**` for bold. |
| `url` | The advert on arbeitsagentur.de. |

### How to scrape Arbeitsagentur jobs

1. Type job titles, skills or company names into **Keywords**, in German where you can. On 30 September 2026 `Softwareentwickler` matched 3,445 jobs and `software developer` 437. Each keyword runs as its own search.
2. Add cities, postcodes or federal states to **Locations**, for example `Berlin`, `80331` or `Bayern`, and set **Radius (km)**: 25 when left empty, 0 for the place itself. `Österreich` returns the Austrian offers listed on the Jobsuche, 38,161 on 30 September 2026.
3. Pick the **Offer type** and narrow the search with **Working time**, **Contract**, **Home office possible**, **Published** or **Employer**, or with the switches that leave out temporary agencies, private recruiters and adverts taken over from partner boards. A link copied from a search on the Jobsuche website works too: paste it into **Search links from arbeitsagentur.de** and its filters are kept.
4. Keep **Include full details** on to get the advert text, the agency flags, the required school certificate and the source. It costs the same, but every advert needs one more request: 1,000 adverts with details took about 3 minutes.
5. Click **Start**. Rows fill the **Output** tab during the run, and you can export them as CSV, Excel or JSON or read them through the API. When **Maximum jobs** is lower than the number of matches, the searches share it equally.

The same search as API input:

```json
{
  "keywords": ["Pflegefachkraft", "Altenpfleger"],
  "locations": ["Berlin"],
  "radiusKm": 10,
  "workingTime": ["partTime"],
  "excludeTemporaryAgencies": true,
  "postedWithin": "7",
  "maxItems": 500
}
```

### Example output

One advert from a run on 28 September 2026, with the description cut after its first lines.

```json
{
  "key": "ba:18451-k60557.1392-S",
  "jobId": "18451-k60557.1392-S",
  "title": "ambulante Pflegefachkraft (m/w/d)",
  "url": "https://www.arbeitsagentur.de/jobsuche/jobdetail/18451-k60557.1392-S",
  "offerType": "Job",
  "occupation": "Pflegefachmann/-frau (Gesundheits- und Krankenpflege)",
  "otherOccupations": [
    "Pflegefachmann/-frau (Altenpflege)",
    "Pflegefachmann/-frau (Hochschule)"
  ],
  "company": "Diakonie-Pflege Verbund Berlin gGmbH",
  "employerId": "wKwOGaEflK9Xvu7mjuXk9jyZpT3UC0-Sjm9IWk3penE=",
  "street": "Wassertorstraße 21a",
  "postalCode": "10969",
  "city": "Berlin",
  "district": null,
  "state": "Berlin",
  "country": "Germany",
  "latitude": 52.500474000001,
  "longitude": 13.4065935,
  "locations": [
    {
      "street": "Wassertorstraße 21a",
      "postalCode": "10969",
      "city": "Berlin",
      "district": null,
      "state": "Berlin",
      "country": "Germany",
      "latitude": 52.500474000001,
      "longitude": 13.4065935
    }
  ],
  "contract": "Permanent",
  "fixedTermMonths": null,
  "fixedTermUntil": null,
  "workingTime": [
    "Part-time mornings",
    "Part-time afternoons",
    "Part-time evenings"
  ],
  "miniJob": false,
  "homeOffice": false,
  "homeOfficeType": null,
  "homeOfficePercent": null,
  "salaryMin": 35640,
  "salaryMax": 39252,
  "salaryPeriod": "year",
  "salaryCurrency": "EUR",
  "trainingPayPerMonth": [],
  "trainingType": null,
  "studyForm": null,
  "studyProgram": null,
  "requiredEducation": null,
  "startDate": "2026-09-29",
  "publishedAt": "2026-09-28",
  "updatedAt": "2026-09-28T17:39:36.656",
  "careerChangersWelcome": false,
  "temporaryAgency": false,
  "privateRecruiter": false,
  "forSeverelyDisabled": false,
  "source": "Diakonie-Pflege Verbund Berlin gGmbH",
  "sourceWebsite": "https://www.diakonie-pflege.de/",
  "externalUrl": null,
  "description": "Weil wir #pflegeleben!\n\n# ambulante Pflegefachkraft (m/w/d) für unsere Diakonie-Station Kreuzberg\n\nKreuzberg, mitten in Berlin: kurze Touren, viel Kiez, gute Anbindung mit U-Bahn, Bus und Rad.\n\nDas macht die ambulante Pflege hier besonders. ...",
  "detailsIncluded": true,
  "searchQuery": "\"Pflegefachkraft\" in Berlin",
  "scrapedAt": "2026-09-28T18:32:46.110Z"
}
```

### How much does it cost to scrape Arbeitsagentur jobs?

| | Free plan | Starter | Scale | Business |
|---|---|---|---|---|
| 1,000 jobs | $0.30 | $0.24 | $0.195 | $0.15 |

You pay only for the events in the table. There is no start fee, and compute time and proxies are included.

An export of 10,000 adverts with full details costs $3.00 on the Free plan and $1.50 on Business. Adverts removed by **Exclude keywords**, adverts that two of your searches both found and adverts already delivered in the new-only mode cost nothing.

### Limits

- The Jobsuche shows at most 10,000 adverts per search. When **Maximum jobs** asks for more, the actor splits the search by contract type, offer type, the agency and partner board flags, the career changer flag and finally occupational field. Adverts without an occupational field cannot be reached that way; the run log gives their number.
- Pay is optional for employers. In a September 2026 run, 297 of 1,000 adverts for software developers and electricians in Munich and Hamburg stated it.
- `requiredEducation` comes with apprenticeship offers. Ordinary job adverts leave it empty.
- The **Employer** filter needs the name exactly as on the website, legal form included, e.g. `Deutsche Bahn AG`. To catch every advert that mentions a company, put the name into **Keywords**.
- The actor sends at most about 6 requests a second. If the Jobsuche answers with HTTP 429 or 503, it waits a minute and continues at half the pace; after five such pauses it stops and keeps the adverts it already has.

### Apprenticeships and dual study

Set **Offer type** to **Apprenticeships and dual study (Ausbildung, duales Studium)** to read training places, 176,967 of them on 30 September 2026. Their rows carry `trainingType` (`Apprenticeship` or `Dual study`), the pay for each training year in `trainingPayPerMonth`, the school certificate in `requiredEducation` and a `startDate` that for most places is the start of the training year, such as `2027-08-01`. For dual study, `studyForm` and `studyProgram` describe the course. Only some employers publish the training pay: 15 of 100 places for `Kaufmann` in one September 2026 run.

### Daily alerts for new adverts

Turn on **Return only jobs new since the last run**, give the run a **Watch name** such as `pflege-berlin` and schedule it every morning. Runs of a saved task get their own snapshot without a name. The actor remembers each advert for 120 days after it first appeared and sends only adverts it has not delivered under that name before.

### FAQ

#### Is it legal to scrape arbeitsagentur.de?

The Jobsuche is run by a federal agency to publish job offers to everyone, and the actor reads it through the same public interface as the website and the Jobsuche app. That interface leaves out the contact person block, which the website shows only after a CAPTCHA. The advert text itself is published as the employer wrote it, and about a third of adverts in a September 2026 run contained an email address. You are responsible for how you store and use the data.

#### How many offers are on the Jobsuche?

On 30 September 2026 it listed 1,029,255 offers: 834,456 jobs, 176,967 apprenticeship and dual study places, 14,355 internships and trainee places and 3,477 self-employment offers. About a fifth of them, 214,337, came from temporary employment agencies.

#### Does it include adverts from other job boards?

Yes. Arbeitsagentur takes over adverts from partner boards such as jobvector, HeyJobs and the Austrian AMS, 197,365 of them on 30 September 2026. `source` names the partner and `externalUrl` links to the advert there, which is usually where applications go. Turn on **Only jobs posted on Arbeitsagentur** to leave them out.

### Related scrapers

- [Welcome to the Jungle Jobs Scraper](https://apify.com/deriverge/welcome-to-the-jungle-jobs-scraper)
- [Career Site Jobs Search](https://apify.com/deriverge/career-site-jobs-search)

### Support

This actor is built and maintained by deriverge s.r.o., a software company based in the Czech Republic. If a run fails or a field you need is missing, please open an issue in the **Issues** tab or write to us at info@deriverge.com. We respond in English and Czech. Runs can be scheduled in Apify Console or started from the **API** tab, which has examples for Python, JavaScript and cURL and works with Make, Zapier, n8n and the Apify MCP server. If the actor saves you time, a short review helps other people find it.

# Changelog

This Actor's version history is a separate document: https://apify.com/deriverge/arbeitsagentur-jobs-scraper/changelog.md

# Actor input Schema

## `keywords` (type: `array`):

What to search for, as in the Jobsuche search box: a job title, skill or company, best in German, for example "Pflegefachkraft", "Softwareentwickler", "Buchhalter" or "Lagerhelfer". Each keyword is its own search. Leave empty for all jobs.

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

A city, a postcode or a German state, for example Berlin, 80331, Hamburg or Bayern. "Österreich" finds the Austrian jobs listed on Arbeitsagentur. Each location is its own search. Leave empty for all of Germany.

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

How far around each location to search, in kilometres. 0 means only that place. Leave empty for 25 km, as on the website.

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

Which kind of offers to return, as the tabs on the website.

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

Only jobs with any of these working times. Leave empty for all.

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

Only jobs where working from home is possible, as the Homeoffice filter on the website.

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

Only permanent or only fixed-term jobs. Adverts that do not state it are left out by both.

## `postedWithin` (type: `string`):

Only jobs published in this window, as on the website.

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

Only jobs from this employer, written exactly as on the website including the legal form, for example "Deutsche Bahn AG". To find any mention of a company, put it in Keywords instead.

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

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

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

Leave out jobs posted by private recruitment agencies (private Arbeitsvermittlung).

## `excludePartnerJobBoards` (type: `boolean`):

Leave out jobs that Arbeitsagentur takes over from partner job boards such as jobvector, HeyJobs or the Austrian AMS.

## `careerChangersOnly` (type: `boolean`):

Only jobs the employer marked as suitable for career changers (Quereinsteiger).

## `searchUrls` (type: `array`):

Jobsuche search addresses with your filters, for example https://www.arbeitsagentur.de/jobsuche/suche?angebotsart=1\&was=Pflegefachkraft\&wo=Berlin\&umkreis=25. Each link is its own search.

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

Drop jobs whose title or company contains any of these.

## `includeDetails` (type: `boolean`):

Reads each job for the full description, the required school certificate, the temporary agency and private recruiter flags and the source of the advert. The price is the same.

## `newOnly` (type: `boolean`):

Keeps a snapshot per watch name (or per saved task) and returns only jobs that were not there before. Schedule it daily for a job alert.

## `watchName` (type: `string`):

Name of the snapshot used by the new-only mode, for example "pflege-berlin". Runs from a saved task get one automatically.

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

Hard cap on returned jobs. The website shows up to 10,000 jobs per search; larger searches are split automatically. 1,000 jobs with full details take about 3 minutes, without details about 20 seconds.

## Actor input object example

```json
{
  "keywords": [
    "Pflegefachkraft"
  ],
  "locations": [
    "Berlin"
  ],
  "offerType": "job",
  "homeOfficeOnly": false,
  "contractType": "any",
  "postedWithin": "any",
  "excludeTemporaryAgencies": false,
  "excludePrivateRecruiters": false,
  "excludePartnerJobBoards": false,
  "careerChangersOnly": false,
  "includeDetails": true,
  "newOnly": false,
  "maxItems": 20
}
```

# Actor output Schema

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

One row per job with company, address, salary, contract, working time, home office and full description.

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

Jobs matching and returned per search, how large searches were split, details read, dropped rows 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 = {
    "keywords": [
        "Pflegefachkraft"
    ],
    "locations": [
        "Berlin"
    ],
    "maxItems": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("deriverge/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 = {
    "keywords": ["Pflegefachkraft"],
    "locations": ["Berlin"],
    "maxItems": 20,
}

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

```

## MCP server setup

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