# Ausbildung.de Vocational Training Scraper (`crawlerbros/ausbildung-de-scraper`) Actor

Scrape German apprenticeship (Ausbildung) job listings from ausbildung.de by city and category, or by specific profession nationwide. Get titles, companies, locations, start dates, requirements, and application details.

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

## Pricing

from $3.00 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## Ausbildung.de Vocational Training Scraper

Scrape German apprenticeship (Ausbildung) job listings from [ausbildung.de](https://www.ausbildung.de) — one of Germany's largest vocational-training job boards. Search open apprenticeship positions by city and industry category, look up nationwide listings for a specific profession, or run a free-text keyword search across all professions and employers nationwide. Get titles, employer names, locations, start dates, school-diploma requirements, apprenticeship type, and application details. No auth, no proxy, no cookies required.

### What this actor does

- **Three modes:** `byCity` (city + broad category browse), `byProfession` (nationwide lookup for one specific occupation), and `byQuery` (free-text keyword search nationwide, matching partial profession/employer names)
- **Any German city:** works with any city ausbildung.de indexes (Berlin, München, Hamburg, Köln, and thousands of smaller towns)
- **~700 professions:** from `fachinformatiker` to `altenpfleger` to `bankkaufmann`
- **Filters:** required school diploma, apprenticeship type, training start-date range, minimum open positions, keyword, direct-application-only, top-rated-employer-only
- **Optional deep enrichment:** fetch each listing's detail page for the full job description, employer contact/website, and address
- **Empty fields are omitted**

### Output per listing

- `vacancyId`, `jobPostingId` — ausbildung.de internal IDs
- `title`, `professionTitle` — the specific posting title and the standardized occupation name
- `corporationName`, `subsidiaryName` — hiring company
- `location`, `city`, `postalCode` — parsed from the raw location string
- `vacancyCount` — number of open positions in this posting
- `relatedBranchesCount` — number of other company locations also offering this posting
- `startsNoEarlierThan`, `validUntil` — training start date and posting expiry
- `expectedGraduation` — required school-leaving diploma
- `apprenticeshipType` — dual apprenticeship / school-based / dual-study / etc.
- `duration` — training length
- `applicationOptions`, `directApplicationOn` — how to apply
- `corporationLogo`, `subsidiaryLogo` — employer logo image URLs
- `inSpotlight`, `topRatedEmployer` — ausbildung.de curation flags
- `corporationRecentReviewCount`, `corporationRecentStarCountAvg` — employer rating (when reviews exist)
- `listingUrl` / `sourceUrl` — canonical ausbildung.de detail page
- With `includeJobDescription: true`, also: `description` (full plain-text job ad), `employmentType`, `datePosted`, `employerWebsite`, `streetAddress`, `addressLocality`, `addressRegion`, `addressCountry`, `industry`, `educationRequirements`, `jobImage`
- `recordType: "apprenticeshipListing"`, `scrapedAt`

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `mode` | string | `byCity` | `byCity`, `byProfession`, or `byQuery` |
| `citySlug` | string | `berlin` | City name (mode=byCity). Umlauts auto-normalized. |
| `category` | select | `kaufmaennisch` | Broad industry/topic filter (mode=byCity) |
| `professionSlug` | string | `fachinformatiker` | Exact profession slug (mode=byProfession), nationwide |
| `searchQuery` | string | `Fachinformatiker` | Free-text keyword (mode=byQuery), nationwide — matches partial profession/employer names |
| `expectedGraduation` | select | – | Required school diploma |
| `apprenticeshipType` | select | – | Dual / school-based / dual-study / etc. |
| `startDateFrom` / `startDateTo` | string | – | Only keep listings whose training start date (`YYYY-MM-DD`) falls in this range |
| `minVacancyCount` | int | `0` | Drop listings with fewer open positions |
| `keyword` | string | – | Substring match on title/profession/company |
| `directApplicationOnly` | bool | `false` | Only listings with direct online application |
| `topRatedEmployerOnly` | bool | `false` | Only ausbildung.de-flagged top employers |
| `includeJobDescription` | bool | `false` | Fetch full description + contact details per listing (slower) |
| `maxItems` | int | `20` | Hard cap (1–300). The actor pages through results (~20/page for city searches, ~3/page for narrow profession searches) until the cap is reached or the source pool is exhausted. |

#### Example: IT apprenticeships in Berlin

```json
{
  "mode": "byCity",
  "citySlug": "berlin",
  "category": "it",
  "maxItems": 20
}
```

#### Example: nationwide search for a specific profession, with full descriptions

```json
{
  "mode": "byProfession",
  "professionSlug": "mechatroniker",
  "includeJobDescription": true,
  "maxItems": 10
}
```

#### Example: top-rated employers offering Abitur-level training in Hamburg

```json
{
  "mode": "byCity",
  "citySlug": "hamburg",
  "category": "kaufmaennisch",
  "expectedGraduation": "abitur",
  "topRatedEmployerOnly": true
}
```

#### Example: nationwide keyword search for an employer

```json
{
  "mode": "byQuery",
  "searchQuery": "McDonald's",
  "maxItems": 20
}
```

### Use cases

- **Career counseling platforms** — surface current openings by region and field
- **Vocational-training research** — track apprenticeship supply across German cities/industries
- **Recruiting intelligence** — monitor which employers post the most apprenticeship openings
- **Education-tech aggregators** — build a searchable apprenticeship index
- **Labor-market analysis** — measure apprenticeship demand per profession and diploma level

### Limitations

- The actor pages through ausbildung.de's server-rendered results (via `?page=N`) up to 25 pages, stopping early once several consecutive pages yield no new listings — this handles ausbildung.de's pool-recycling behavior for narrow queries (e.g. rare profession + city combos) without looping forever. Very broad queries may still not reach `maxItems` if the underlying pool is smaller than requested.
- City + specific-profession combinations (e.g. "altenpfleger in Berlin") are not directly filterable — use `mode=byCity` with a broad `category`, or `mode=byProfession` for nationwide profession-only results.
- Company-directory browsing and German-state-level (`Bundesland`) listing pages are navigation-only on ausbildung.de (they link out to individual cities) and are not exposed as a separate mode.

### FAQ

**What's ausbildung.de?**  A German job board run by Studitemps GmbH dedicated to `Ausbildung` (vocational apprenticeship) and dual-study openings across all industries and regions in Germany.

**What does "category" mean in `byCity` mode?**  A broad topic filter ausbildung.de itself curates per city — industries (`it`, `handwerk`, `medien`), required diploma (`abitur`, `hauptschulabschluss`), or specific popular occupations. Not every category has listings in every city; an empty result for a rare combination is expected, not an error.

**How do I find valid `professionSlug` values?**  Browse [ausbildung.de/berufe/glossar/](https://www.ausbildung.de/berufe/glossar/) for the full alphabetical list of ~700 professions. Common examples: `fachinformatiker`, `kauffrau-im-einzelhandel`, `mechatroniker`, `altenpfleger`, `bankkaufmann`, `koch`, `elektroniker-betriebstechnik`.

**Why do some listings lack a `postalCode`?**  ausbildung.de sometimes shows only the city name (e.g. "Berlin") without a postal code for postings that cover multiple locations within a region.

**Why does a valid-looking `professionSlug` sometimes return 0 listings?**  A handful of glossary entries describe occupations that have been superseded or merged into newer training paths (e.g. the legacy `altenpfleger` title was folded into the unified `pflegefachmann` qualification after Germany's 2020 nursing-education reform) or are university-track roles ausbildung.de lists for reference only (e.g. `arzt`, `apotheker`). These pages exist but currently carry no active apprenticeship postings — 0 records is the correct, real-time answer, not a scraper bug.

**Is proxy or login required?**  No. The actor reads ausbildung.de's public, server-rendered pages directly.

**How fresh is the data?**  Real-time — the actor reads the same server-rendered page a browser visitor would see at request time.

# Actor input Schema

## `mode` (type: `string`):

What to fetch.

## `citySlug` (type: `string`):

German city name/slug, e.g. `berlin`, `muenchen`, `hamburg`, `koeln`. Umlauts should be transliterated (ä→ae, ö→oe, ü→ue, ß→ss) and spaces become hyphens — the actor also normalizes common input automatically.

## `category` (type: `string`):

Broad topic/industry to filter the city search. `kaufmaennisch` (commercial/office) is the broadest category and is populated for virtually every city. Not every category has listings in every city — an unlisted combination returns 0 records, not an error. Note: `alle-berufe` (unfiltered) is intentionally excluded because ausbildung.de renders it as an infinite-scroll page with no listings in the initial server response.

## `professionSlug` (type: `string`):

Exact ausbildung.de profession slug, nationwide search (no city filter). Examples: `fachinformatiker`, `kauffrau-im-einzelhandel`, `mechatroniker`, `altenpfleger`, `bankkaufmann`, `koch`, `elektroniker-betriebstechnik`. Browse the full glossary at ausbildung.de/berufe/glossar/ for all ~700 slugs.

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

Free-text keyword searched nationwide across profession titles and company names, e.g. `Fachinformatiker`, `Bäcker`, `McDonald's`. Broader than `professionSlug` (exact slug match) — matches partial/fuzzy profession and employer names.

## `expectedGraduation` (type: `string`):

Filter results to listings requiring this school-leaving qualification.

## `apprenticeshipType` (type: `string`):

Filter by the type of vocational training program.

## `startDateFrom` (type: `string`):

Only keep listings whose training start date (`startsNoEarlierThan`) is on or after this date.

## `startDateTo` (type: `string`):

Only keep listings whose training start date (`startsNoEarlierThan`) is on or before this date.

## `minVacancyCount` (type: `integer`):

Drop listings offering fewer open positions than this.

## `keyword` (type: `string`):

Case-insensitive substring match against title, profession title, and company name.

## `directApplicationOnly` (type: `boolean`):

Only keep listings that support direct online application (no email/postal-only listings).

## `topRatedEmployerOnly` (type: `boolean`):

Only keep listings from employers ausbildung.de has flagged as top-rated.

## `includeJobDescription` (type: `boolean`):

For each listing, also fetch its detail page and add the full description text, contact/address details, and employment type. Slower (1 extra request per record) but much richer output.

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

Hard cap on emitted records. The actor pages through ausbildung.de's results (~20 listings per page for city searches, ~3 for narrow profession searches) until this cap is reached or the source pool is exhausted (stops automatically after several pages return no new listings).

## Actor input object example

```json
{
  "mode": "byCity",
  "citySlug": "berlin",
  "category": "kaufmaennisch",
  "professionSlug": "fachinformatiker",
  "searchQuery": "Fachinformatiker",
  "expectedGraduation": "",
  "apprenticeshipType": "",
  "minVacancyCount": 0,
  "keyword": "",
  "directApplicationOnly": false,
  "topRatedEmployerOnly": false,
  "includeJobDescription": false,
  "maxItems": 20
}
```

# Actor output Schema

## `listings` (type: `string`):

Dataset containing all scraped ausbildung.de apprenticeship listings.

# 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 = {
    "mode": "byCity",
    "citySlug": "berlin",
    "category": "kaufmaennisch",
    "professionSlug": "fachinformatiker",
    "searchQuery": "Fachinformatiker",
    "expectedGraduation": "",
    "apprenticeshipType": "",
    "minVacancyCount": 0,
    "keyword": "",
    "directApplicationOnly": false,
    "topRatedEmployerOnly": false,
    "includeJobDescription": false,
    "maxItems": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("crawlerbros/ausbildung-de-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 = {
    "mode": "byCity",
    "citySlug": "berlin",
    "category": "kaufmaennisch",
    "professionSlug": "fachinformatiker",
    "searchQuery": "Fachinformatiker",
    "expectedGraduation": "",
    "apprenticeshipType": "",
    "minVacancyCount": 0,
    "keyword": "",
    "directApplicationOnly": False,
    "topRatedEmployerOnly": False,
    "includeJobDescription": False,
    "maxItems": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("crawlerbros/ausbildung-de-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 '{
  "mode": "byCity",
  "citySlug": "berlin",
  "category": "kaufmaennisch",
  "professionSlug": "fachinformatiker",
  "searchQuery": "Fachinformatiker",
  "expectedGraduation": "",
  "apprenticeshipType": "",
  "minVacancyCount": 0,
  "keyword": "",
  "directApplicationOnly": false,
  "topRatedEmployerOnly": false,
  "includeJobDescription": false,
  "maxItems": 20
}' |
apify call crawlerbros/ausbildung-de-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,crawlerbros/ausbildung-de-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/cWWMSirAahkeMVTd9/builds/9ZjyvmmVIeq7ak3QH/openapi.json
