# Arbeitsagentur Jobs Scraper - Bundesagentur für Arbeit Jobbörse (`kadi_bence/arbeitsagentur-jobs-scraper`) Actor

Search Germany's Arbeitsagentur Jobbörse (Bundesagentur für Arbeit, 1M+ jobs). Input: keywords, city + radius (e.g. Lagerhelfer within 25 km of München), employer, home office, working time. Returns per job: title, employer, city, salary, posted date, URL. Only-new mode. Default: 20 jobs. $0.75/1K.

- **URL**: https://apify.com/kadi_bence/arbeitsagentur-jobs-scraper.md
- **Developed by:** [Bence Kadi](https://apify.com/kadi_bence) (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.75 / 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

## Germany Jobs Scraper: Arbeitsagentur Jobbörse to JSON, CSV and Excel

### What is Germany Jobs Scraper (Arbeitsagentur Jobbörse)?

Germany Jobs Scraper exports job offers from the **Bundesagentur für Arbeit Jobbörse** ([arbeitsagentur.de/jobsuche](https://www.arbeitsagentur.de/jobsuche/)), Germany's largest job database with 1M+ open positions, many of which never appear on LinkedIn or StepStone. You search by keyword, city plus radius, employer, working time or contract type, and get JSON, CSV or Excel with full descriptions, structured salary, all work locations, coordinates and dates.

It calls the Jobbörse's public JSON interface, the same one arbeitsagentur.de itself uses. There is no browser and no HTML parsing. The input is in plain English, so you don't need to know the German API parameters.

**What makes it different**

- **Works on the current API.** It uses the Jobbörse v6 interface (the old endpoint now answers 403), so there are no soft-blocks or empty runs.
- **All the official filters.** Several keywords at once, city or postal code + radius, employer, occupational field (Berufsfeld), offer type (job, Ausbildung, Praktikum, Selbständigkeit), full-/part-time, shift, minijob, **home office**, permanent or fixed-term, published within N days.
- **Agency flags and filters.** `temporaryAgency` and `privateAgency` on every job, and switches to hide Zeitarbeit and private recruiters.
- **Structured salary.** The employer's own salary range (`gehaltsspanne`) becomes `salaryMin`, `salaryMax`, `salaryCurrency` and `salaryPeriod`. Ranges in the text are parsed as a fallback.
- **Geo-ready.** All work locations, postal code, federal state and latitude/longitude.
- **Only new jobs.** Monitoring mode outputs, and charges for, only offers you haven't seen before.
- **GDPR-friendly.** Street addresses are left out; e-mails and phone numbers are removed from descriptions.

#### Use cases

- **Recruiting and staffing agencies:** find employers hiring for the roles you place, by region, every morning.
- **Sales and lead generation:** spot local companies with open positions (hiring signals for HR tech, training and relocation services).
- **Labour-market research:** analyse demand by occupation, region, salary and contract type.
- **Job portals and apps:** add German job offers to your platform with one clean English schema.
- **Apprenticeship (Ausbildung) search:** collect all apprenticeship offers around a city.
- **AI agents and RAG apps:** give an LLM fresh German job data through the API or the Apify MCP server.

#### Data fields you get

| Field | Description | Example |
|---|---|---|
| `title` | Job title | `Senior Data Platform Engineer` |
| `occupation` | Main occupation (Hauptberuf) | `Data Engineer` |
| `employer` | Employer name | `Smartly.io Solutions GmbH` |
| `refnr` | Jobbörse reference number | `10001-1003717099-S` |
| `url` | Link to the offer on arbeitsagentur.de | `https://www.arbeitsagentur.de/jobsuche/jobdetail/10001-1003717099-S` |
| `externalUrl` | Link to the employer's or partner's page, when the offer has one | `https://www.get-in-it.de/jobsuche/p290571?...` |
| `city` | City of the first work location | `Berlin` |
| `postalCode` | Postal code (PLZ) | `10117` |
| `region` | Federal state | `Berlin` |
| `country` | Country, in German | `Deutschland` |
| `latitude` / `longitude` | Coordinates of the first work location | `52.520904` / `13.388769` |
| `locations` | All work locations (PLZ, city, state) | `["10117, Berlin, Berlin"]` |
| `postedDate` | Current publication date (ISO) | `2026-09-16` |
| `firstPublishedDate` | First publication date | `2026-09-16` |
| `startDate` | Start date (Eintrittsdatum) | `2026-09-16` |
| `modifiedAt` | Last change of the offer | `2026-09-16T14:32:45.163` |
| `offerType` | Offer type as sent by the Jobbörse | `ARBEIT` |
| `workingTime` | Working-time models | `["VOLLZEIT", "HEIM_TELEARBEIT"]` |
| `contractType` | Contract duration | `UNBEFRISTET` |
| `homeOffice` | Working from home allowed | `true` |
| `temporaryAgency` | Offer from a temp agency (Arbeitnehmerüberlassung) | `false` |
| `privateAgency` | Offer from a private placement agency | `false` |
| `salaryMin` / `salaryMax` | Salary range (numbers) | `60000` / `87000` |
| `salaryCurrency` | Currency code | `EUR` |
| `salaryPeriod` | `YEAR`, `MONTH`, `WEEK`, `DAY` or `HOUR` | `YEAR` |
| `salaryText` | Original salary text, when the offer has one | `null` |
| `description` | Job description as text | `We are looking for a Senior Data Platform Engineer…` |
| `descriptionHtml` | Description as HTML, only when the source is HTML | `null` |
| `isNew` | Set in monitoring mode | `true` |
| `scrapedAt` | When the job was scraped (UTC) | `2026-10-04T23:59:53Z` |

### How to use Germany Jobs Scraper

1. Open the Actor and enter one or more **keywords** (e.g. `Elektroniker`, `Data Engineer`) and/or a **location** (`Berlin`, `80331`) with a radius. The prefill (Data Engineer, Berlin, 25 km, 50 results) runs in about 10–15 seconds and costs about $0.04.
2. Optional: set filters (offer type, working time, home office, contract, published within N days, without temp agencies).
3. Set **Max results** and click **Start**.
4. When the run finishes, open the **Output** tab and download CSV, Excel or JSON, or connect Google Sheets, Make, Zapier, n8n or your own code.
5. To get only new jobs every day, turn on **Only new jobs** and create a **Schedule** (see [Integrations and scheduling](#integrations-and-scheduling)).

#### Input guide

**Keywords (`keywords`)**

One search per line, sent to the Jobbörse search like the "Was" box on arbeitsagentur.de. Each keyword is a separate search; a job found by two keywords is saved once.

- Good: `Elektroniker`, `Data Engineer`, `Pflegefachkraft`, `Python`
- Bad: `Data Engineer Berlin` (put the place in **Location**), `IT jobs with home office` (use the **Working time** filter)
- Tip: German job titles usually find more offers than English ones.
- Warning: with no keyword, location, employer or occupational field, the search covers all of Germany (1M+ jobs). Set **Max results** in that case.

**Location (`location`) and radius (`radiusKm`)**

A city or postal code, plus a radius in km (0–200). The radius is only used together with a location. Leave the location empty for all of Germany.

- Good: `Berlin`, `München`, `80331`
- Bad: `Bavaria and Hesse` (one place per run; for several regions use several runs or a schedule per region)

**Employer (`employer`) and occupational field (`occupationalField`)**

`employer` keeps only offers from that employer, written as shown on arbeitsagentur.de (e.g. `Deutsche Bahn AG`). `occupationalField` is the Jobbörse's Berufsfeld, e.g. `Informatik`.

**Filters**

- `offerType`: `job` (default), `apprenticeship` (Ausbildung / dual study), `internship` (Praktikum / trainee) or `self_employment`.
- `workingTime`: any of `full_time`, `part_time`, `shift_night_weekend`, `home_office`, `minijob`. Empty means any. `home_office` keeps only offers that allow working from home.
- `contractType`: `any` (default), `permanent` (unbefristet) or `temporary` (befristet).
- `publishedWithinDays`: only offers published in the last N days (0–100), e.g. `7`.
- `includeTemporaryAgencies` / `includePrivateAgencies` (both on by default): turn off to hide Zeitarbeit or private recruiters.

Most filters are sent to the Jobbörse, so non-matching offers are never downloaded. Offers removed by a filter are not saved and are **not charged**.

**Max results (`maxResults`)**

A limit for the whole run, across all keywords. `0` means no limit. The Console prefill is 50 for a quick test; the default when calling via API, MCP or an AI agent is 20.

Warning: the Jobbörse pages through at most about 10,000 results per search. For bigger exports, split the search by keyword or location (e.g. one run per federal state). The run log warns you when a search hits this limit, and `RUN_SUMMARY` shows the total matches per keyword.

**Only new jobs (`onlyNewJobs`) and Monitor name (`monitorName`)**

See [Monitoring mode](#monitoring-mode-only-new-jobs) below.

**Output options**

- `includeDetails` (default on): one extra request per job for the description, all work locations, contract details and salary. Turn it off for a faster list without descriptions.
- `descriptionFormat`: `text` (default), `html`, `both` or `none`. Most Jobbörse descriptions are plain text with line breaks, so `descriptionHtml` is filled only when the employer's text is HTML.
- `stripContactInfo` (default on): removes e-mails and phone numbers from descriptions.

**Advanced**

- `proxyConfiguration`: off by default and usually not needed. If the log says the API refused every endpoint (HTTP 401/403), enable Apify Proxy with the RESIDENTIAL group and country Germany (DE).

Example input:

```json
{
  "keywords": ["Elektroniker", "Mechatroniker"],
  "location": "Berlin",
  "radiusKm": 25,
  "workingTime": ["full_time"],
  "contractType": "permanent",
  "publishedWithinDays": 7,
  "includeTemporaryAgencies": false,
  "maxResults": 1000
}
```

### Output

Each job is one item in the run's dataset. Here is one real item from the prefill run on 2026-10-05 (description shortened):

```json
{
  "title": "Senior Data Platform Engineer",
  "occupation": "Data Engineer",
  "employer": "Smartly.io Solutions GmbH",
  "refnr": "10001-1003717099-S",
  "url": "https://www.arbeitsagentur.de/jobsuche/jobdetail/10001-1003717099-S",
  "externalUrl": null,
  "city": "Berlin",
  "postalCode": "10117",
  "region": "Berlin",
  "country": "Deutschland",
  "latitude": 52.520904,
  "longitude": 13.388769,
  "locations": ["10117, Berlin, Berlin"],
  "postedDate": "2026-09-16",
  "firstPublishedDate": "2026-09-16",
  "startDate": "2026-09-16",
  "modifiedAt": "2026-09-16T14:32:45.163",
  "offerType": "ARBEIT",
  "workingTime": ["VOLLZEIT"],
  "contractType": "UNBEFRISTET",
  "homeOffice": false,
  "temporaryAgency": null,
  "privateAgency": null,
  "salaryMin": 60000,
  "salaryMax": 87000,
  "salaryCurrency": "EUR",
  "salaryPeriod": "YEAR",
  "salaryText": null,
  "description": "We are looking for a **Senior Data Platform Engineer** to join the **Data Platform** at Smartly!\n\nSmartly is building the standard path for governed data…",
  "descriptionHtml": null,
  "scrapedAt": "2026-10-04T23:59:53Z"
}
```

Notes:

- Jobs with several work locations list all of them in `locations` (one offer in the test run had 7 cities). `city`, `postalCode`, `region` and the coordinates belong to the first location.
- `workingTime` contains `HEIM_TELEARBEIT` and `homeOffice` is `true` when the employer allows working from home.
- Code values such as `offerType`, `workingTime` and `contractType` are kept as the Jobbörse sends them (`ARBEIT`, `VOLLZEIT`, `TEILZEIT`, `UNBEFRISTET`, `KEINE_ANGABE`, …).
- Street addresses are never included. Empty values are `null`, so every item has the same columns in CSV and Excel.

#### Dataset views

The **Output** tab has two views of the same data:

| View | What it shows |
|---|---|
| **Jobs** | A compact table: title, employer, city, PLZ, published date, working time, contract, salary range and link. |
| **Full details** | Title, occupation, employer, all locations, start date, salary text, description, external URL and link. |

Every export (JSON, CSV, Excel, API) contains all fields, whichever view you look at. The run also writes a `RUN_SUMMARY` record to the key-value store: per keyword the total matches and the number of jobs listed, plus any error, the number of requests and the jobs saved.

#### How to export the data

- **In the Console:** Output tab > **Export** > JSON, CSV, Excel, HTML, XML or RSS. You can pick fields and the view.
- **Google Sheets:** add the Google Sheets integration to the Actor or a schedule (Integrations tab), or use `=IMPORTDATA("https://api.apify.com/v2/datasets/<DATASET_ID>/items?format=csv&token=<TOKEN>")`.
- **API:** `https://api.apify.com/v2/datasets/<DATASET_ID>/items?format=json` (also `csv`, `xlsx`, `xml`). Add `&view=overview` for the compact table.

### Pricing

This Actor uses **pay per event**. You pay **$0.75 per 1,000 jobs** ($0.00075 per job saved to the dataset), plus Apify's standard Actor start fee of **$0.00005 per run**. Platform compute is included in the price.

| Example run | Jobs saved | Cost |
|---|---|---|
| Prefill test (Data Engineer, Berlin, 50 jobs) | 50 | about $0.04 |
| One occupation in one city | 1,000 | about $0.75 |
| One federal state, one occupation | 10,000 | about $7.50 |
| Daily monitoring, ~100 new jobs per day for 30 days | 3,000 | about $2.25 per month |

What you don't pay for:

- offers removed by your filters (e.g. published date, home office),
- jobs already seen in monitoring mode,
- the same job found again by a second keyword,
- searches that fail (nothing is saved),
- the `RUN_SUMMARY` record.

To cap spending, set **Max results**, or set **Max charge per run** in the run options; the Actor stops cleanly at that limit and keeps what it saved. Apify's free plan includes monthly platform credit you can use for this Actor.

### Use it via API

Get your API token in the Apify Console under **Settings > API & Integrations**. The examples below run the Actor, wait for it to finish and read the jobs. Fields you don't send get the defaults listed above (e.g. `maxResults` 500).

**JavaScript / Node.js** (`npm install apify-client`)

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });

const run = await client.actor('kadi_bence/arbeitsagentur-jobs-scraper').call({
    keywords: ['Elektroniker', 'Mechatroniker'],
    location: 'München',
    radiusKm: 30,
    contractType: 'permanent',
    maxResults: 200,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(`${items.length} jobs`, items[0]);
```

**Python** (`pip install apify-client`)

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")

run = client.actor("kadi_bence/arbeitsagentur-jobs-scraper").call(run_input={
    "keywords": ["Data Engineer"],
    "location": "Berlin",
    "radiusKm": 25,
    "workingTime": ["home_office"],
    "maxResults": 200,
})

for job in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(job["title"], job["employer"], job["city"], job["salaryMin"], job["url"])
```

**cURL** (runs the Actor and returns the jobs in one request; best for runs under 5 minutes)

```bash
curl -X POST "https://api.apify.com/v2/acts/kadi_bence~arbeitsagentur-jobs-scraper/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"keywords": ["Data Engineer"], "location": "Berlin", "radiusKm": 25, "maxResults": 50}'
```

**Apify CLI**

```bash
apify call kadi_bence/arbeitsagentur-jobs-scraper --input '{"keywords": ["Data Engineer"], "location": "Berlin", "radiusKm": 25, "maxResults": 50}' --output-dataset
```

**MCP server for AI agents** (Claude, Cursor, VS Code and other MCP clients)

Add the Apify MCP server with this Actor as a tool. Your client will ask you to sign in to Apify (OAuth), or you can send your token as an `Authorization: Bearer YOUR_APIFY_TOKEN` header.

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com/?actors=kadi_bence/arbeitsagentur-jobs-scraper"
    }
  }
}
```

Then ask your agent, for example: "Find permanent Elektroniker jobs within 30 km of Munich published in the last 7 days and list the employers with salary ranges."

### Integrations and scheduling

- **Schedules:** in the Console go to **Schedules > Create new**, pick this Actor (or a saved task with your input) and a time, e.g. every day at 07:00. Each run gets its own dataset.
- **Webhooks:** on the Actor's **Integrations** tab, add a webhook for "Run succeeded" to send the run and dataset ID to your server.
- **Zapier, Make and n8n:** use the Apify app or node. Trigger "Actor run finished", then "Get dataset items", then send each job to Slack, e-mail, a CRM or Airtable.
- **Google Sheets:** the Google Sheets integration appends each run's jobs to a sheet, which is the easiest job-alert setup.
- **Slack and e-mail:** Apify's built-in Slack and e-mail integrations can notify you when a run finishes.

#### Monitoring mode (only new jobs)

Turn on **Only new jobs** (`onlyNewJobs: true`) and schedule the Actor:

1. The first run outputs all matching jobs and saves their reference numbers as a baseline.
2. Every later run outputs only jobs that weren't listed before.
3. You pay only for those new jobs.

In monitoring mode every saved item has `isNew: true`, including on the first run.

The "already seen" list is stored in a named key-value store (`arbeitsagentur-jobs-monitor`) in your own Apify account. The key depends on the **Monitor name** and on your whole input except `maxResults`, `onlyNewJobs` and the proxy settings. So if you change a keyword, the location or a filter, a new list starts and the next run outputs all matching jobs again. If you run two schedules with similar input (e.g. one for Berlin, one for Hamburg), give them different **Monitor names** so their lists stay separate. To start over, use a new monitor name.

Only jobs that were actually output (and charged) are added to the list. If a run stops at **Max results** or **Max charge per run**, the jobs it did not reach are returned by the next run, and nothing is charged twice.

### Other job scrapers by the same developer

All of them use the same output fields where possible, so you can merge datasets.

- [Workday Jobs Scraper](https://apify.com/kadi_bence/workday-jobs-scraper): every job from company career sites on Workday (myworkdayjobs.com), by company name, with no 2,000-job cap.
- [Greenhouse, Lever & Ashby Jobs Scraper](https://apify.com/kadi_bence/ats-jobs-scraper): jobs from Greenhouse, Lever, Ashby, Workable, Recruitee and Personio boards, by company name.
- [Oracle, Taleo, BambooHR & Rippling Jobs Scraper](https://apify.com/kadi_bence/ats-plus-jobs-scraper): nine more applicant tracking systems, including Oracle Recruiting Cloud, Taleo, Teamtailor and Jobvite.
- [Sweden Jobs Scraper - Platsbanken](https://apify.com/kadi_bence/sweden-jobs-scraper): all Swedish job ads from Arbetsförmedlingen, with an archive since 2016.
- [EURES Jobs Scraper](https://apify.com/kadi_bence/eures-jobs-scraper): EU job vacancies from 31 countries via the official European Job Mobility Portal.
- [Remote Jobs Scraper](https://apify.com/kadi_bence/remote-jobs-scraper): remote jobs from RemoteOK, Himalayas, Jobicy and Arbeitnow in one de-duplicated feed.

Related company data for B2B leads: [SEC Form D Scraper](https://apify.com/kadi_bence/sec-form-d-funding) (startup funding rounds), [New Business Filings USA](https://apify.com/kadi_bence/us-new-business-filings) (newly registered companies), [Website Tech Stack Detector](https://apify.com/kadi_bence/tech-stack-detector) (technologies a company uses) and [EU Public Tenders Scraper (TED)](https://apify.com/kadi_bence/ted-tenders-scraper) (EU public contracts).

### FAQ

**How does Germany Jobs Scraper work?**
It sends your search to the Jobbörse's public JSON search endpoint, pages through the results (100 per page) and, with full details on, opens each job's detail endpoint. It then turns the German field names into clean English ones. It doesn't use a browser, so it's fast and cheap.

**Is there an official Bundesagentur für Arbeit API?**
The Jobbörse has a public JSON interface that its own website and app use (documented by the community project bundesAPI). This Actor calls it directly, so you get API-style data without writing your own client.

**How many results can I get per search?**
The Jobbörse pages through at most about 10,000 results per query. For bigger exports, split the search by keyword or location (e.g. one run per federal state). The run log warns you when a query hits this limit, and `RUN_SUMMARY` shows the total matches per keyword.

**How fast is it?**
The 50-job prefill takes about 10–15 seconds; several hundred jobs per minute with full details. Turn off `includeDetails` for a faster list without descriptions.

**Why do I get fewer jobs than arbeitsagentur.de shows?**
Usually because of **Max results**, a filter, or the ~10,000-results-per-search limit. `RUN_SUMMARY` shows the total matches and the jobs listed per keyword. In monitoring mode, jobs already returned earlier are skipped.

**Why are some descriptions or salaries empty?**
Some offers are only summaries that link to the employer's own site (see `externalUrl`). Salary is filled only when the employer published a range or the text contains one (about 1 in 5 offers in the test run).

**Do I need a proxy?**
No. The Actor runs without a proxy. If the log says the API refused every endpoint (HTTP 401/403), enable Apify Proxy with the RESIDENTIAL group and country Germany (DE).

**Is it legal to scrape the Jobbörse?**
The Actor reads only publicly accessible job offers through the public interface, with no login. It leaves out street addresses and removes e-mails and phone numbers from descriptions by default. Descriptions are written by employers and can still name a contact person, so treat the data according to GDPR when you store or re-use it. You are responsible for your use of the data, including the site's terms.

**Can I use it from Python, n8n or another app?**
Yes. Use the Apify API, the JavaScript or Python client, the CLI, the n8n/Make/Zapier integrations or the MCP server, as shown in [Use it via API](#use-it-via-api). Only the fields you send are used, plus the documented defaults.

**How do I get only new jobs every day?**
Turn on **Only new jobs** and create a schedule. See [Monitoring mode](#monitoring-mode-only-new-jobs).

**The run failed or a field is missing. What should I do?**
Open an issue on the **Issues** tab with the run link or your input. Fixes usually land within 24–48 hours. See the changelog below for recent changes.

### Related Actors

More low-cost Actors by the same developer, built on official APIs and public data:

- [EURES Jobs Scraper](https://apify.com/kadi_bence/eures-jobs-scraper) — EU job vacancies from 31 countries
- [Platsbanken Jobs Scraper](https://apify.com/kadi_bence/sweden-jobs-scraper) — Swedish job ads, live or archived since 2016
- [Workday Jobs Scraper](https://apify.com/kadi_bence/workday-jobs-scraper) — open jobs of any company by name (NVIDIA, Salesforce), plus Greenhouse/Lever fallback
- [Greenhouse, Lever & Ashby Jobs Scraper](https://apify.com/kadi_bence/ats-jobs-scraper) — all open jobs of a company from 6 applicant systems, plus Workday
- [Oracle, Taleo, BambooHR & Rippling Jobs Scraper](https://apify.com/kadi_bence/ats-plus-jobs-scraper) — jobs from 9 more applicant tracking systems
- [Remote Jobs Scraper](https://apify.com/kadi_bence/remote-jobs-scraper) — remote jobs from We Work Remotely, RemoteOK, Himalayas and more
- [TED Tenders Scraper](https://apify.com/kadi_bence/ted-tenders-scraper) — EU public tenders and contract award winners

All my Actors: [apify.com/kadi_bence](https://apify.com/kadi_bence)

### Changelog

- **2026-10-05:** moved to the new Jobbörse v6 API after the old endpoint started returning 403; structured salary, multiple locations, agency flags, home-office filter.
- **2026-10, 1.0:** first version: keyword/location/employer search with all official filters, details, salary parsing, coordinates, monitoring mode.

# Actor input Schema

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

One search per line (job titles or skills), e.g. 'Elektroniker', 'Data Engineer', 'Pflegefachkraft'. German terms usually find more offers. Leave empty to search all jobs, but then set a location, employer or occupational field, or Max results, because all of Germany is 1M+ jobs.

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

City or postal code, e.g. 'Berlin', 'München' or '80331'. Leave empty for all of Germany. Put only the place here, not job words.

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

Radius around the location in km, e.g. 25. Only used together with a location.

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

Only jobs from this employer, written as shown on arbeitsagentur.de (e.g. 'Deutsche Bahn AG').

## `occupationalField` (type: `string`):

Optional Berufsfeld as used by the Jobbörse, e.g. 'Informatik'.

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

Kind of offer: a regular job, an apprenticeship or dual study (Ausbildung), an internship or trainee position (Praktikum), or self-employment.

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

Leave empty for any. With several values, offers matching any of them are kept. 'Home office / remote' keeps only offers that allow working from home.

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

Permanent or fixed-term.

## `publishedWithinDays` (type: `integer`):

Only offers published in the last N days (0-100), e.g. 7. Leave empty for any date.

## `includeTemporaryAgencies` (type: `boolean`):

Turn off to hide offers from temporary-work agencies (Zeitarbeit / Arbeitnehmerüberlassung).

## `includePrivateAgencies` (type: `boolean`):

Turn off to hide offers posted by private job placement agencies.

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

Stop after this many jobs in total (all keywords together). 0 = no limit. The Console prefill is 50 for a quick test. The default without input (API, MCP and AI-agent calls) is 20. The Jobbörse pages through at most about 10,000 results per search, so split very large searches by keyword or location.

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

Fetch the description, all work locations, contract details and salary for each job (one extra request per job). Turn off for a faster list without descriptions.

## `descriptionFormat` (type: `string`):

Most Jobbörse descriptions are plain text with line breaks. 'HTML' is filled only when the employer's description is HTML.

## `stripContactInfo` (type: `boolean`):

Removes e-mail addresses and phone numbers from descriptions. Recommended (GDPR).

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

Remember returned jobs and output only NEW ones on the next runs with the same input. Ideal for daily schedules; you pay only for new jobs. Only jobs that were actually output (and charged) are remembered, so jobs cut off by Max results or the charge limit come in the next run.

## `monitorName` (type: `string`):

Separate 'already seen' lists for different schedules. Use a new name to start over.

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

Usually not needed. Only if the log says the API refused every endpoint (HTTP 401/403): enable Apify Proxy with the RESIDENTIAL group and country Germany (DE).

## Actor input object example

```json
{
  "keywords": [
    "Data Engineer"
  ],
  "location": "Berlin",
  "radiusKm": 25,
  "offerType": "job",
  "contractType": "any",
  "includeTemporaryAgencies": true,
  "includePrivateAgencies": true,
  "maxResults": 50,
  "includeDetails": true,
  "descriptionFormat": "text",
  "stripContactInfo": true,
  "onlyNewJobs": false,
  "monitorName": "default",
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

All scraped jobs (table view).

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

All scraped jobs with every field.

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

Per-site/company counts, what was found and any problems.

# 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"
    ],
    "location": "Berlin",
    "radiusKm": 25,
    "maxResults": 50,
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("kadi_bence/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": ["Data Engineer"],
    "location": "Berlin",
    "radiusKm": 25,
    "maxResults": 50,
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("kadi_bence/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": [
    "Data Engineer"
  ],
  "location": "Berlin",
  "radiusKm": 25,
  "maxResults": 50,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call kadi_bence/arbeitsagentur-jobs-scraper --silent --output-dataset

```

## MCP server setup

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