# Bundesagentur Job Scraper — German Vacancies (`khadinakbar/bundesagentur-job-scraper`) Actor

Search Germany's Bundesagentur für Arbeit public Jobsuche feed and return normalized vacancies with employer, location, contract, remote-work and date signals. Use for recruitment research and labor-market analysis; not for applicant data.

- **URL**: https://apify.com/khadinakbar/bundesagentur-job-scraper.md
- **Developed by:** [Khadin Akbar](https://apify.com/khadinakbar) (community)
- **Categories:** Jobs, Automation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.25 / 1,000 job scrapeds

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Bundesagentur Job Scraper — German Vacancies

Bundesagentur Job Scraper is an Apify Actor for searching Germany's Bundesagentur fur Arbeit public Jobsuche feed and returning one normalized vacancy record per job. It accepts a free-text job search query, an optional location and radius, or known public BA reference numbers. Each record can include employer, location, postal code, region, offer type, contract duration, work-time flags, remote-work signal, career-change suitability, description, salary text when published, timing fields, external application URL, source URL, and scrape timestamp.

Use it for recruitment research and labor-market analysis when you need current public German vacancy data in a structured dataset. The Actor is usable through Apify and through Apify MCP, and it writes one dataset item per validated job record.

### Best fit and connected workflows

This Actor fits workflows centered on public German vacancy data from the Bundesagentur feed.

It is a strong match when you want to:

- search by role, skill, or occupation in German job-market language,
- focus on a city, district, postal code, or German region with a search radius,
- enrich known BA reference numbers from an earlier collection,
- capture employer, location, contract, work-time, and remote-work signals in one normalized record,
- feed vacancy data into recruitment research, labor-market analysis, alerting, or agent workflows.

For adjacent job-board workflows, these verified related Actors cover other source scopes:

- When your brief matches APEC's job-board scope, geography, or audience, use [APEC Jobs Scraper](https://apify.com/khadinakbar/apec-jobs-scraper).
- When your workflow centers on Ashby-hosted vacancies, use [Ashby Jobs Scraper](https://apify.com/khadinakbar/ashby-jobs-scraper).
- When your research focuses on Bayt's MENA listings and regional coverage, use [Bayt Jobs Data Scraper for MENA Listings](https://apify.com/khadinakbar/bayt-jobs-scraper).

### Practical scenario

Marta is preparing a labor-market snapshot for software roles in Berlin. She starts with:

- `searchQuery: "Softwareentwickler"`
- `location: "Berlin"`
- `radiusKm: 25`
- `maxResults: 20`

The Actor returns records with fields such as:

- `title`
- `companyName`
- `location`
- `workTime`
- `remotePossible`
- `postedAt`
- `externalUrl`
- `sourceUrl`
- `scrapedAt`

Marta uses the employer, work arrangement, and publication date to shortlist current vacancies. She then opens `externalUrl` for the public application page or checks `sourceUrl` for the Bundesagentur detail record before continuing her analysis.

### Input

| Field | Type | Description |
| --- | --- | --- |
| `searchQuery` | string | Free-text role, skill, or occupation query for Bundesagentur Jobsuche. Defaults to `Softwareentwickler`. |
| `location` | string | City, district, postal code, or German region to search around. Defaults to `Berlin`. |
| `radiusKm` | integer | Search radius in km around `location`. Choose `0, 10, 15, 25, 50, 100, or 200`. Defaults to `25`. |
| `jobReferenceNumbers` | array of string | Known public BA reference numbers to enrich directly. These take precedence over search filters. |
| `maxResults` | integer | Maximum number of validated jobs written and billed by the run. Range: `1` through `500`. Defaults to `20`. |
| `includeJobDetails` | boolean | Fetches the public BA detail record for each listing to include description, contract, work-time, and remote-work fields. Defaults to `true`. |
| `responseFormat` | string | Controls returned job-description length for agent workflows. Choose `concise` or `detailed`. Defaults to `concise`. |

#### Input example

```json
{
  "searchQuery": "Data Engineer",
  "location": "Muenchen",
  "radiusKm": 25,
  "jobReferenceNumbers": [],
  "maxResults": 10,
  "includeJobDetails": true,
  "responseFormat": "concise"
}
```

### Output

Each dataset item is one normalized public vacancy record.

| Field | Type | Description |
| --- | --- | --- |
| `jobId` | string | Stable Bundesagentur offer reference number. |
| `title` | string | Published vacancy title. |
| `companyName` | string or null | Employer name published with the listing. |
| `location` | string or null | Published work location text. |
| `postalCode` | string or null | Published work-location postal code. |
| `region` | string or null | Published work-location region. |
| `employmentOfferType` | string or null | Bundesagentur employment offer category. |
| `contractDuration` | string or null | Published contract-duration category. |
| `workTime` | array of string | Published work-time flags. |
| `remotePossible` | boolean or null | Whether the public detail record marks remote work as possible. |
| `careerChangeSuitable` | boolean or null | Whether the public detail record marks the role as suitable for career changers. |
| `description` | string or null | Plain-text public job description, truncated according to `responseFormat`. |
| `salaryText` | string or null | Public salary statement when supplied. |
| `postedAt` | string or null | Public publication date or timestamp. |
| `updatedAt` | string or null | Public listing modification timestamp. |
| `availableFrom` | string or null | Published requested start date. |
| `externalUrl` | string or null | Public external job or application URL, when supplied. |
| `sourceUrl` | string | Public Bundesagentur detail API route used for this record. |
| `scrapedAt` | string | ISO 8601 time when this record was collected. |
| `source` | string | Source identifier. |

#### Output example

```json
{
  "jobId": "10000-1000000000-S",
  "title": "Softwareentwickler/in",
  "companyName": "Example GmbH",
  "location": "Berlin, Deutschland",
  "postalCode": "10115",
  "region": "Berlin",
  "employmentOfferType": "ARBEIT",
  "contractDuration": "UNBEFRISTET",
  "workTime": ["full-time"],
  "remotePossible": false,
  "careerChangeSuitable": true,
  "description": "Develop software systems...",
  "salaryText": "4,000 EUR monthly",
  "postedAt": "2026-07-17",
  "updatedAt": "2026-07-17T07:03:33.973",
  "availableFrom": "2026-08-01",
  "externalUrl": "https://careers.example.com/jobs/123",
  "sourceUrl": "https://rest.arbeitsagentur.de/jobboerse/jobsuche-service/pc/v4/jobdetails/...",
  "scrapedAt": "2026-07-19T14:00:00.000Z",
  "source": "bundesagentur-fuer-arbeit"
}
```

### How it works

This Actor searches the public Bundesagentur fur Arbeit Jobsuche feed and writes normalized vacancy records to the default dataset. It supports two collection paths:

- a free-text search query with optional location and radius, or
- explicit public BA reference numbers for direct enrichment.

When `includeJobDetails` is enabled, the Actor fetches the public detail record for each listing so the output can include description, contract, work-time, and remote-work fields. The Actor also writes compact run outcome records in the default key-value store:

- `OUTPUT`
- `RUN_SUMMARY`

The dataset view presents a table of normalized public vacancies with title, employer, location, type, contract, work time, remote signal, posted date, and external listing link.

### Pricing

This Actor uses Pay per event plus Apify platform usage. The charged events are:

- Actor start
- Job scraped

Each persisted job is charged as a `Job scraped` event, and the run can also incur Apify platform compute and storage usage. The `maxResults` input sets a cap on how many validated jobs can be written and billed in one run.

For example, a run that collects twenty jobs creates up to twenty job events, plus one actor-start event, plus platform usage. Review the live Pricing tab for the current event prices and platform-usage details before running.

### Use with AI agents (MCP)

This Actor is available as an Apify Actor usable through Apify MCP. It exposes a precise tool for collecting public Bundesagentur vacancies with structured, provenance-rich output.

**Actor identity:** `khadinakbar/bundesagentur-job-scraper`

A practical agent prompt:

> Search public Bundesagentur vacancies for Data Engineer roles in Berlin within 25 km. Return concise job records, keep the result set bounded, and cite `sourceUrl` and `scrapedAt` for each record. Then summarize the collection outcome and include the dataset link for downstream review.

What to expect from the output:

- `dataset` points to the default dataset items endpoint.
- `output` contains the compact run outcome.
- `runSummary` contains public-API, pagination, validation, and billing diagnostics.

Provenance guidance:

- use `sourceUrl` as the primary public API reference for each record,
- use `scrapedAt` to understand when the record was collected,
- use `externalUrl` as the public application link when it is supplied.

Scope guidance:

- the Actor returns public vacancy data from the Bundesagentur feed,
- it centers on normalized job records, not applicant or recruiter contact data.

Pagination and cost guidance:

- `maxResults` sets the collection and billing cap for validated jobs,
- use smaller result sets for narrow research tasks,
- use `jobReferenceNumbers` when refreshing known BA offers instead of repeating a broad search.

### Apify API example

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

const client = new ApifyClient({
    token: process.env.APIFY_TOKEN,
});

const input = {
    searchQuery: 'Data Engineer',
    location: 'Berlin',
    radiusKm: 25,
    maxResults: 10,
    includeJobDetails: true,
    responseFormat: 'concise',
};

const run = await client.actor('khadinakbar/bundesagentur-job-scraper').call(input);

const dataset = await client.dataset(run.defaultDatasetId).listItems();

console.log('Run finished:', run.id);
console.log('Jobs returned:', dataset.items.length);
console.log(dataset.items);
```

Set `APIFY_TOKEN` in your environment before running the script.

### Best results and outcome guidance

Use a role name that matches German vacancy wording, then pair it with a specific location for a focused search. `radiusKm` fits the workflow when it matches the research area you need, and `jobReferenceNumbers` is useful for direct enrichment of known listings.

For agent workflows, `concise` keeps descriptions shorter while preserving the same normalized fields. Use `detailed` when downstream processing benefits from longer public descriptions. When you need a stable sample size, set `maxResults` before running so the dataset and billing scope stay aligned.

### Design note

I found that the live dataset contract requires `jobId`, `title`, `workTime`, `sourceUrl`, `scrapedAt`, and `source` on every record, so the README should always frame those as the stable minimum output.

### FAQ

#### When should I use `searchQuery` versus `jobReferenceNumbers`?

Use `searchQuery` for discovery and `jobReferenceNumbers` when you already have public BA reference numbers from a prior collection and want to enrich them directly.

#### When is `location` useful?

Use `location` when you want vacancies centered on a city, district, postal code, or German region. Combine it with `radiusKm` for area-based searches.

#### What changes when `includeJobDetails` is turned off?

The Actor can return a listing-focused feed with less detail. Fields that depend on the public detail record, such as description, contract, work-time, and remote-work signals, are centered on the listing data that is available.

#### Which fields are most useful for routing into downstream workflows?

For routing, start with `title`, `companyName`, `location`, `workTime`, `remotePossible`, `postedAt`, and `externalUrl`. Use `sourceUrl` and `scrapedAt` for provenance.

#### How should I choose related Actors?

Choose the related Actors when your workflow needs another job board or region-specific source. Keep the market and source scope aligned with the research brief.

### Related Actors

- [APEC Jobs Scraper](https://apify.com/khadinakbar/apec-jobs-scraper) - use when the brief matches APEC's job-board scope, geography, or audience.
- [Ashby Jobs Scraper](https://apify.com/khadinakbar/ashby-jobs-scraper) - use when the brief calls for Ashby-hosted vacancies and that source scope.
- [Bayt Jobs Data Scraper for MENA Listings](https://apify.com/khadinakbar/bayt-jobs-scraper) - use when the brief focuses on Bayt's MENA listings and regional coverage.

### Responsible use

This Actor collects public vacancy data from the Bundesagentur fur Arbeit Jobsuche API and includes provenance fields so you can trace each record back to the source. Use the output in ways that respect applicable law, source terms, and privacy expectations, and keep your workflows focused on public job listings.

# Actor input Schema

## `searchQuery` (type: `string`):

Free-text role, skill, or occupation query for Bundesagentur Jobsuche, for example 'Softwareentwickler'. It accepts normal German search text and defaults to 'Softwareentwickler'. Use it with Location for local searches or leave the default for the quality-test search. This is not a listing URL or an applicant query.

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

City, district, postal code, or German region around which to search, for example 'Berlin'. It is optional and defaults to 'Berlin' for a dependable initial search. Radius only applies when this field is supplied. This is not a free-form employer-address filter.

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

Distance in kilometres around Location for the public BA search. Choose 0, 10, 15, 25, 50, 100, or 200; the default is 25. Use 0 for the exact location only. This is not a geographic-coordinate field.

## `jobReferenceNumbers` (type: `array`):

Known public Bundesagentur reference numbers to enrich directly, for example '10000-1000000000-S'. When supplied, they take precedence over the search filters. Enter only reference numbers returned by the BA listing API. This is not for URLs, customer identifiers, or applicant IDs.

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

Maximum number of validated jobs written and billed by this run. Choose an integer from 1 through 500; default is 20. Each persisted job costs $0.00225 plus Apify platform usage, so this is also the event-cost cap. This is not a per-page limit.

## `includeJobDetails` (type: `boolean`):

Fetch the public BA detail record for each listing to include description, contract, work-time and remote-work fields. It defaults to true; set false for a faster listing-only feed. A temporary detail failure preserves the valid listing and is reported as a partial outcome. This does not request authenticated or private data.

## `responseFormat` (type: `string`):

Controls the maximum returned job-description length for agent workflows. Choose concise for 800 characters or detailed for 5000; concise is the default. All other normalized fields are identical in both modes. This is not a CSV, JSON, or export-format setting.

## Actor input object example

```json
{
  "searchQuery": "Data Engineer",
  "location": "München",
  "radiusKm": 25,
  "jobReferenceNumbers": [
    "10000-1000000000-S"
  ],
  "maxResults": 20,
  "includeJobDetails": true,
  "responseFormat": "concise"
}
```

# Actor output Schema

## `dataset` (type: `string`):

Default dataset containing one normalized public Bundesagentur vacancy per item.

## `output` (type: `string`):

Compact machine-readable collection outcome with record and billing counts.

## `runSummary` (type: `string`):

Detailed public-API, pagination, validation, and billing diagnostics.

# 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 = {
    "searchQuery": "Softwareentwickler",
    "location": "Berlin",
    "radiusKm": 25,
    "jobReferenceNumbers": [],
    "maxResults": 20,
    "responseFormat": "concise"
};

// Run the Actor and wait for it to finish
const run = await client.actor("khadinakbar/bundesagentur-job-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 = {
    "searchQuery": "Softwareentwickler",
    "location": "Berlin",
    "radiusKm": 25,
    "jobReferenceNumbers": [],
    "maxResults": 20,
    "responseFormat": "concise",
}

# Run the Actor and wait for it to finish
run = client.actor("khadinakbar/bundesagentur-job-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "searchQuery": "Softwareentwickler",
  "location": "Berlin",
  "radiusKm": 25,
  "jobReferenceNumbers": [],
  "maxResults": 20,
  "responseFormat": "concise"
}' |
apify call khadinakbar/bundesagentur-job-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=khadinakbar/bundesagentur-job-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/fyWjDsG4Z576pzki6/builds/lZYsdLFxfyCmHVIrI/openapi.json
