# Arbeitsagentur Scraper - German Jobs, Salaries & Employers (`scrapewise/arbeitsagentur-scraper`) Actor

Scrape jobs, apprenticeships and internships from the German Federal Employment Agency (Bundesagentur für Arbeit) by keyword, city, radius, working time, home office and contract: employer, location with coordinates, salary, start date and full description. Error rows are free.

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

## Pricing

from $1.53 / 1,000 job delivereds

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 Scraper: German jobs, apprenticeships and internships with salary, employer and location

Arbeitsagentur Scraper collects **job offers from the Jobbörse of the German Federal Employment Agency
(Bundesagentur für Arbeit)**, the largest job board in Germany, without an account, cookies or a browser. Each job
comes back as one clean row: title, occupation, employer, city, postal code, state and coordinates, working time,
home office, contract type, salary when the employer publishes it, start date, publication dates, the partner job
board it came from and, by default, the full job description.

It is used to build job market datasets for Germany, to track hiring by region, occupation or employer, to find
apprenticeship (Ausbildung) and internship offers, to feed job aggregators and alert bots, and to give recruiting
and HR teams a daily list of new openings.

### At a glance

| What | Price |
|---|---|
| Job delivered | **US$ 1.80 per 1,000 jobs** (US$ 0.0018 each) |
| Run start | US$ 0.005 per run |

- 500 jobs with full descriptions = **US$ 0.905**. The description, the source partner and the employer profile
  cost nothing extra.
- Error rows, duplicates and jobs skipped by `onlyNew` are never charged. `maxItems` is a hard cap, and a spending
  limit set on the run stops it cleanly with everything delivered so far.
- Runs are fast: about 100 jobs per second without descriptions and 4 to 5 jobs per second with them.

### Quick start

```json
{
  "queries": ["Softwareentwickler"],
  "location": "Berlin",
  "radiusKm": 25,
  "maxItems": 100
}
```

Apprenticeships in Bavaria published in the last 7 days, newest first:

```json
{
  "queries": ["Mechatroniker", "Elektroniker"],
  "offerType": "apprenticeship",
  "location": "Bayern",
  "postedWithinDays": 7,
  "sortBy": "newest",
  "maxItems": 0
}
```

Remote-friendly permanent full-time jobs, at least 50% home office:

```json
{
  "queries": ["Data Engineer"],
  "minHomeOfficePercent": 50,
  "contractType": "permanent",
  "workingTime": ["full-time"],
  "maxItems": 200
}
```

You can also paste a search link from the site, with every filter you picked there:

```json
{
  "startUrls": [
    "https://www.arbeitsagentur.de/jobsuche/suche?angebotsart=1&was=Pflegefachkraft&wo=Hamburg&umkreis=25&arbeitszeit=tz"
  ]
}
```

### Input

| Field | What it does |
|---|---|
| `queries` | Job titles or keywords, one per line (`Softwareentwickler`, `Pflegefachkraft`, `Data Engineer`). Empty = search by location or employer only. |
| `startUrls` | Search links from arbeitsagentur.de/jobsuche (filters in the link are kept), job pages (`/jobsuche/jobdetail/...`) or bare reference numbers like `10001-1234567890-S`. |
| `location` | City, postal code, German state or country (`München`, `80331`, `Bayern`, `Österreich`). Empty = all of Germany. |
| `radiusKm` | Distance around the location (site default 25 km; 0 = only the place). |
| `offerType` | `job`, `apprenticeship` (Ausbildung and dual study), `internship` (Praktikum and trainee) or `self-employment`. |
| `workingTime` | `full-time`, `part-time`, `shift` (night and weekend) and `mini job`; any of them matches. |
| `remoteOnly` | Only jobs where home office is possible. |
| `minHomeOfficePercent` | Only jobs with at least this share of home office (for example 50). |
| `contractType` | `permanent` (unbefristet) or `temporary` (befristet). |
| `postedWithinDays` | 0 (today), 1, 7, 14 or 28; other values are rounded up to the next option. |
| `employer` | Exact employer name as shown on the site (`Deutsche Bahn AG`). |
| `excludeTemporaryAgencies` | Leave out Zeitarbeit / Arbeitnehmerüberlassung offers. |
| `excludePrivateRecruiters` | Leave out offers from private recruitment agencies. |
| `sortBy` | `relevance` (default), `newest`, `modified`, `start date` or `distance`. |
| `includeDescription` | Full text, source partner, required education and contract length (default on). |
| `includeCompanyProfile` | Employer self-description and website, when the employer has a profile (default off, slower). |
| `onlyNew` | For schedules: delivers only jobs not delivered in earlier runs of the same search. |
| `maxItems` | Cap for the whole run (default 50; 0 = no cap). |
| `proxyConfiguration` | Apify datacenter proxy by default. |

`searchQuery`, `keyword`, `was`, `wo`, `city`, `radius`, `umkreis`, `angebotsart`, `arbeitszeit`, `maxResults` and
`urls` are accepted too, so inputs written for other Arbeitsagentur tools keep working.

### Output

Every job is one row with `type: job`:

| Field | What it is |
|---|---|
| `referenceNumber`, `url` | The job's reference number (Referenznummer) and its page on arbeitsagentur.de |
| `title`, `occupation`, `allOccupations` | Job title as written by the employer, and the occupations the agency assigned |
| `offerType` | `ARBEIT`, `AUSBILDUNG`, `PRAKTIKUM_TRAINEE` or `SELBSTAENDIGKEIT` |
| `companyName`, `employerId` | Employer name and the site's anonymous employer id (same id = same employer) |
| `city`, `postalCode`, `region`, `country`, `latitude`, `longitude` | First work location; `locations` lists all of them |
| `distanceKm` | Distance from the searched location |
| `workingTime`, `isFullTime` | `fullTime`, `partTimeMorning`, `partTimeAfternoon`, `partTimeEvening`, `partTimeFlexible`, `shiftNightWeekend`, `miniJob` |
| `remotePossible`, `remotePercent`, `remoteArrangement` | Home office flag, share and arrangement (`NACH_VEREINBARUNG` = by agreement) |
| `contractDuration`, `contractMonths` | `UNBEFRISTET`, `BEFRISTET` or `KEINE_ANGABE`, and the length of fixed-term contracts |
| `startDate`, `publishedAt`, `firstPublishedAt`, `modifiedAt` | Start date and publication dates |
| `salaryMin`, `salaryMax`, `salaryCurrency`, `salaryPeriod` | Salary when published (`hour`, `year`...), in EUR |
| `salaryInfo`, `salaryKind` | The raw salary type (`JAHRESGEHALT`, `STUNDENLOHN`, `AUSBILDUNGSVERGUETUNG_NACH_JAHREN`...) and fixed or range |
| `isTemporaryAgency`, `isPrivateRecruiter` | Zeitarbeit and private recruiter flags |
| `suitableForCareerChangers`, `disabilityRequired` | Quereinstieg flag and the severe-disability offer flag |
| `requiredEducation`, `trainingType` | School leaving certificate asked for, and `AUSBILDUNG` or `DUALES_STUDIUM` |
| `sourcePartner`, `sourcePartnerUrl`, `externalUrl`, `boxNumber` | Partner job board the offer came from, its link, and the box number (Chiffre) of anonymous offers |
| `description` | Full job description (with `includeDescription`) |
| `companyDescription`, `companyWebsite` | Employer profile (with `includeCompanyProfile`) |
| `sourceQuery`, `scrapedAt` | The keyword or link that found the job, and when |

One real row (description shortened):

```json
{
  "type": "job",
  "referenceNumber": "10001-1003713573-S",
  "title": "Data Engineer Waffensystemdaten (m/w/d)",
  "occupation": "Data Engineer",
  "allOccupations": ["Data Engineer", "Informatiker/in"],
  "offerType": "ARBEIT",
  "companyName": "IABG Industrieanlagen Betriebs-GmbH",
  "city": "Ottobrunn",
  "postalCode": "85521",
  "region": "BAYERN",
  "country": "DEUTSCHLAND",
  "latitude": 48.054645,
  "longitude": 11.6603415,
  "distanceKm": 12,
  "workingTime": ["fullTime"],
  "contractDuration": "UNBEFRISTET",
  "startDate": "2026-10-05",
  "publishedAt": "2026-09-16",
  "salaryMin": 65000.0,
  "salaryMax": 85000.0,
  "salaryCurrency": "EUR",
  "salaryPeriod": "year",
  "sourcePartner": "arbeitsagentur.de",
  "url": "https://www.arbeitsagentur.de/jobsuche/jobdetail/10001-1003713573-S",
  "description": "### **Beschreibung der Stelle**\n\nSie begeistern sich für Data Engineering und möchten Daten komplexer technischer Systeme nutzbar machen?...",
  "companyWebsite": "http://www.iabg.de",
  "sourceQuery": "Data Engineer"
}
```

### Errors you may see

Every error is a row with `errorCode` and is never charged:

| errorCode | Meaning |
|---|---|
| `INVALID_INPUT` | A field has a wrong value (the message lists the accepted ones), or the site rejected the search |
| `INVALID_URL` | Not an arbeitsagentur.de search link, job link or reference number |
| `NOT_FOUND` | The job link points to an offer that expired or was removed |
| `NO_RESULTS` | The search and filters match no job; try a broader keyword or fewer filters |
| `BLOCKED` | The site refused every attempt for this search; run it again in a few minutes |

### Integrations, scheduling and AI agents

- **Schedule** a daily run with `onlyNew` on in [Apify schedules](https://docs.apify.com/platform/schedules) to get
  only the jobs published since the last run, ready for alerts.
- **Export** as JSON, CSV, Excel or XML, or read the dataset from the [Apify API](https://docs.apify.com/api/v2).
- **Connect** it to Make, n8n, Zapier, Slack or Google Sheets through
  [Apify integrations](https://docs.apify.com/platform/integrations).
- **AI agents:** call it as a tool through the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp)
  in Claude, ChatGPT, Cursor or any MCP client, for example "list the permanent nursing jobs in Hamburg published
  this week with their salary".

### FAQ

**Do I need an account or an API key?** No. The Actor uses the public job search the website and the official app
use, with the public key they publish. Nothing to sign up for.

**Does it cover Austria and other countries?** The Jobbörse also lists offers abroad (mostly Austria, from the
Austrian public employment service). Set `location` to `Österreich` or a city there.

**How many jobs can one search return?** The site serves at most 10,000 jobs per search. For a bigger slice, split
it by location, occupation or offer type; duplicates across searches in the same run are delivered only once.

**Why do some jobs have no salary?** Most employers in Germany do not publish one. When they do, it comes as a
fixed amount or a range per hour, month or year.

**Are contact persons included?** No. The Actor returns company data only. Emails, phone numbers and the names of
contact persons in the description are replaced by `[contact removed]`.

**Is it legal?** The Actor reads public job offers only. You are responsible for how you use the data under the
laws that apply to you, including the GDPR.

**Something broke or a field is missing?** Open an issue on the Actor page; issues are answered within a day.

### Limitations

- At most 10,000 jobs per search (a limit of the site).
- `postedWithinDays` follows the site options (today, 1, 7, 14 and 28 days).
- `employer` needs the exact employer name; a partial name returns nothing.
- Descriptions are in the language the employer wrote them, almost always German.
- Contact removal works on patterns; an unusual way of writing a name may slip through. Report it and it is fixed.

### Changelog

- **16 Oct 2026:** first version. Keyword, location, radius, offer type, working time, home office, contract, date,
  employer, agency filters and sorting; search and job links; full description and employer profile; `onlyNew` for
  schedules.

# Actor input Schema

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

Job titles or keywords (German or English work), one per line, for example 'Softwareentwickler', 'Pflegefachkraft', 'Data Engineer'. Leave empty to search only by location or employer.

## `startUrls` (type: `array`):

Search links copied from https://www.arbeitsagentur.de/jobsuche (all filters in the link are kept), job pages (/jobsuche/jobdetail/...) or bare reference numbers like 10001-1234567890-S.

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

City, postal code, German state or country, for example 'Berlin', '80331', 'Bayern' or 'Österreich'. Empty = all of Germany.

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

Distance around the location in km (the site offers 0, 10, 15, 25, 50, 100, 200). Empty = the site default of 25 km; 0 = only the place itself.

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

Empty = jobs of every type.

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

One or more; jobs matching any of them are returned.

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

Only jobs where the employer offers home office.

## `minHomeOfficePercent` (type: `integer`):

Only jobs with at least this share of home office, for example 50. Overrides 'Home office possible'.

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

Empty = both.

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

Only jobs published in the last N days. The site offers 0 (today), 1, 7, 14 and 28; other values are rounded up to the next option. Empty = any date.

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

Exact employer name as shown on the site, for example 'Deutsche Bahn AG'.

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

Leave out Zeitarbeit / Arbeitnehmerüberlassung offers.

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

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

## `sortBy` (type: `string`):

Order of the results. 'distance' needs a location.

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

Opens each job for the full text, source partner, required education and contract length (one extra request per job, same price).

## `includeCompanyProfile` (type: `boolean`):

Adds the employer's self-description and website when the employer has a profile on the site (one page per employer, slower).

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

On: remembers the jobs delivered in earlier runs of the same search (in your account) and delivers only jobs not seen before. Skipped jobs are free.

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

Hard cap for the whole run, across all searches. 0 = no cap. The site serves at most 10,000 jobs per search.

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

Apify datacenter proxy by default, which the public job API accepts. Change it only if you know you need to.

## Actor input object example

```json
{
  "queries": [
    "Softwareentwickler"
  ],
  "location": "Berlin",
  "remoteOnly": false,
  "excludeTemporaryAgencies": false,
  "excludePrivateRecruiters": false,
  "sortBy": "relevance",
  "includeDescription": true,
  "includeCompanyProfile": false,
  "onlyNew": false,
  "maxItems": 50,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

No description

## `resultsCsv` (type: `string`):

No description

# 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": 50,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

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

# Run the Actor and wait for it to finish
run = client.actor("scrapewise/arbeitsagentur-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": 50,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call scrapewise/arbeitsagentur-scraper --silent --output-dataset

```

## MCP server setup

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