# Arbeitsagentur Jobs API | 1M+ German Jobs — Official API (`runix/arbeitsagentur-jobs-api`) Actor

Search Germany's Bundesagentur für Arbeit job board (1M+ listings) by keyword, city and radius. Full descriptions, salary, employer, address and GPS, contract filters, and only-new monitoring. Official public API—no browser. $1.50 per 1,000 jobs.

- **URL**: https://apify.com/runix/arbeitsagentur-jobs-api.md
- **Developed by:** [Runix Services](https://apify.com/runix) (community)
- **Categories:** Jobs, Lead generation, Automation
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

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

## Arbeitsagentur Jobs API: 1M+ German Jobs from the Official API

Search **Germany's largest job board**, the Jobsuche of the **Bundesagentur für Arbeit** (Federal Employment Agency, arbeitsagentur.de), with **over 1 million open jobs**, and get clean, structured rows: title, company, full address with GPS, salary range, working time, contract type, start date, the **full job description** and the employer's website.

It reads the job board's **official REST API**, the same one the Arbeitsagentur's own apps use. No browser, no captcha, no proxies, no login. Runs are fast: 100 jobs with descriptions in about 30 seconds, 500 in under a minute.

**$1.50 per 1,000 jobs.** You pay only for the jobs you get.

### What you can do with it

- **Recruiting and staffing**: find every open nurse, electrician, driver or engineer role in a city and radius, with the hiring company and its website.
- **B2B lead generation**: companies that are hiring are companies that are growing. Pull employers by occupation and region, with address and website.
- **Job boards and aggregators**: fill a German job board with fresh, deduplicated jobs every day using only-new mode.
- **Labour-market research**: salaries, working time, contract types and demand by occupation and region.

### Input

| Field | What it does |
|---|---|
| **Job titles or keywords** (`keywords`) | What to search, in German or English: `Data Engineer`, `Pflegefachkraft`, `Elektriker`. Each is its own search. Empty = every job. |
| **Locations** (`locations`) | German cities, postcodes or states: `Berlin`, `80331`, `Bayern`. Empty = all of Germany. |
| **Include jobs abroad** (`includeAbroad`) | With no location, also return the jobs abroad the board lists from partner services (mostly Austria). Off by default. |
| **Radius** (`radiusKm`) | Kilometres around each location, e.g. 10, 25, 50, 100. |
| **Max jobs** (`maxJobs`) | Stop after this many jobs in total. |
| **Offer type** (`offerType`) | Jobs (default), apprenticeships (Ausbildung, duales Studium), internships and trainee posts, self-employment, or any. |
| **Posted within (days)** (`postedWithinDays`) | 0 = today, 1, 7, 14, 28 ... up to 100. |
| **Working time** (`workingTime`) | Full-time, part-time, shift/night/weekend, mini-job. |
| **Contract** (`contract`) | Permanent (unbefristet) or fixed-term (befristet). |
| **Employer** (`employer`) | Only one employer's jobs, e.g. `Deutsche Bahn AG`. |
| **Only jobs with a salary** | Keep only jobs that state pay. |
| **Exclude temporary-work agencies / private recruiters / partner-board copies** | Cleaner lists of direct employers. |
| **Include full description** (`includeDescription`) | On by default. Adds the description, employer website and agency flags. |
| **Only new jobs** (`onlyNewJobs`) | Return only jobs not returned by earlier runs of the same search. Schedule it daily. |

Every keyword is searched in every location, and jobs found by more than one search are returned once.

#### Example: data engineers in Berlin (the prefill)

```json
{
  "keywords": ["Data Engineer"],
  "locations": ["Berlin"],
  "radiusKm": 25,
  "maxJobs": 100
}
```

#### Example: daily monitor of new nursing and electrician jobs, direct employers only

```json
{
  "keywords": ["Pflegefachkraft", "Elektriker"],
  "locations": ["Hamburg", "München"],
  "radiusKm": 25,
  "postedWithinDays": 7,
  "contract": "permanent",
  "excludeTemporaryAgencies": true,
  "onlyNewJobs": true
}
```

### Output

One row per job. Example (description shortened):

```json
{
  "title": "Senior Applied AI Engineer",
  "company": "DKB Service GmbH",
  "city": "Berlin",
  "postalCode": "10557",
  "region": "Berlin",
  "country": "Germany",
  "street": null,
  "latitude": 52.5239066,
  "longitude": 13.3578666,
  "distanceKm": 5,
  "offerType": "job",
  "occupation": "KI-Engineer",
  "workingTime": ["full-time"],
  "contract": "permanent",
  "homeOffice": true,
  "homeOfficeType": "by arrangement",
  "salaryMin": 82000,
  "salaryMax": 100000,
  "salaryCurrency": "EUR",
  "salaryPeriod": "year",
  "salaryText": "€82,000–100,000 per year",
  "startDate": "2026-11-01",
  "publishedAt": "2026-10-08",
  "employerWebsite": "https://www.dkb.de",
  "sourceName": "DKB Service GmbH",
  "sourceWebsite": "https://www.dkb.de",
  "temporaryAgency": false,
  "privateAgency": false,
  "description": "Wir finanzieren, was Menschen im Alltag brauchen - zum Beispiel erneuerbare Energien, bezahlbaren ...",
  "url": "https://www.arbeitsagentur.de/jobsuche/jobdetail/14412-44489256-107-S",
  "applyUrl": "https://www.arbeitsagentur.de/jobsuche/jobdetail/14412-44489256-107-S",
  "referenceNumber": "14412-44489256-107-S",
  "searchKeyword": "Data Engineer",
  "searchLocation": "Berlin",
  "fetchedAt": "2026-11-05T07:38:56.523Z"
}
```

Also in each row: all locations of multi-site jobs (`locations`), all matching occupations, first publication and last change dates, whether the job suits career changers (`suitableForCareerChangers`) and a stable `employerId`. `sourceName` and `sourceWebsite` say who delivered the posting to the job board (the employer itself, a recruiter or a partner job board); `employerWebsite` is filled when that source is the employer. For jobs imported from partner job boards, `applyUrl` is the original posting.

A `SUMMARY` record in the run's key-value store lists every search with how many jobs were available, read and returned.

### Pricing

Pay per event: **$1.50 per 1,000 jobs** ($0.0015 per job). Nothing else is charged. The Actor stops at your Max jobs or your run's spending limit, whichever comes first, so a run never costs more than you allow.

### Limits and tips

- The API serves the **first 10,000 jobs of each search**. For bigger pulls, split by location (for example the 16 states, or a list of cities) or add filters; the Actor deduplicates across searches.
- Salary is given on roughly 15–30% of postings, depending on the occupation. Use *Only jobs with a salary* to keep those.
- Turn off *Include full description* for the fastest runs (one API call per 100 jobs instead of one per job).
- Keywords match the job board's own search, which understands German occupations and their synonyms.

### Is this allowed?

The data is public: the Bundesagentur für Arbeit publishes these job offers so that anyone can find them, and the Actor reads them through the job board's documented public API at a polite pace. It collects job postings, not personal data about applicants. Contact persons hidden behind the job board's captcha are not collected. If you republish jobs, follow the Arbeitsagentur's terms for its data.

### FAQ

**Do I need an API key or an account at the Arbeitsagentur?** No.

**Can I search in English?** Yes, but most German postings use German titles, so German keywords (`Softwareentwickler`, `Krankenpfleger`, `Vertrieb`) usually find more.

**How fresh is it?** Live: every run reads the job board at that moment.

**Does it work for apprenticeships (Ausbildungsplätze)?** Yes, set Offer type to Apprenticeships.

Questions or a field you need? Open an issue on the Actor's Issues tab.

# Actor input Schema

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

What to search for, one per line, in German or English: e.g. 'Data Engineer', 'Pflegefachkraft', 'Elektriker', 'Buchhaltung'. Each keyword is its own search. Leave empty for every job.

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

German cities, postcodes or states, one per line: e.g. 'Berlin', '80331', 'Bayern'. Each location is searched with every keyword. Leave empty for all of Germany.

## `includeAbroad` (type: `boolean`):

With no location, also return the jobs abroad that the job board lists from partner services (mostly Austria, from AMS). Off: Germany only.

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

How far around each location to search, e.g. 10, 25, 50, 100, 200. Leave empty for the job board's default.

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

Stop after this many jobs in total. Leave empty for every match (up to 10,000 per keyword and location, the API's limit).

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

Jobs, apprenticeships (Ausbildung, duales Studium), internships and trainee posts, or self-employment offers.

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

Only jobs published in the last N days: 0 = today, 1, 7, 14, 28 ... up to 100. Leave empty for all.

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

Keep jobs offering any of these. Leave empty for all.

## `contract` (type: `string`):

Permanent (unbefristet) or fixed-term (befristet).

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

Only jobs from this employer, by its name on the job board, e.g. 'Deutsche Bahn AG'.

## `onlyWithSalary` (type: `boolean`):

Keep only jobs that state a salary or salary range.

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

Drop jobs offered through temporary-work agencies (Arbeitnehmerüberlassung).

## `excludePrivateAgencies` (type: `boolean`):

Drop jobs posted by private recruiters (private Arbeitsvermittlung).

## `excludePartnerBoardJobs` (type: `boolean`):

Keep only jobs posted on the Arbeitsagentur itself, not ones imported from partner job boards.

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

Fetch each job's full description, employer website and agency flags (one extra API call per job). Turn off for the fastest runs.

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

Return only jobs this monitor has not returned before. Schedule the Actor daily to get each new job once.

## `monitorId` (type: `string`):

Name for the only-new memory, to run several monitors. Leave empty to derive it from the search.

## Actor input object example

```json
{
  "keywords": [
    "Data Engineer"
  ],
  "locations": [
    "Berlin"
  ],
  "includeAbroad": false,
  "radiusKm": 25,
  "maxJobs": 100,
  "offerType": "job",
  "contract": "any",
  "onlyWithSalary": false,
  "excludeTemporaryAgencies": false,
  "excludePrivateAgencies": false,
  "excludePartnerBoardJobs": false,
  "includeDescription": true,
  "onlyNewJobs": false
}
```

# Actor output Schema

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

JSON dataset items from the run (one object per job).

# 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": [
        "Data Engineer"
    ],
    "locations": [
        "Berlin"
    ],
    "radiusKm": 25,
    "maxJobs": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("runix/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 = {
    "keywords": ["Data Engineer"],
    "locations": ["Berlin"],
    "radiusKm": 25,
    "maxJobs": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("runix/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 '{
  "keywords": [
    "Data Engineer"
  ],
  "locations": [
    "Berlin"
  ],
  "radiusKm": 25,
  "maxJobs": 100
}' |
apify call runix/arbeitsagentur-jobs-api --silent --output-dataset

```

## MCP server setup

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