# Softgarden Jobs Scraper: DACH Career Boards to JSON (`iiphantom/softgarden-jobs-scraper`) Actor

Scrape public Softgarden (\*.softgarden.io) career boards into structured job JSON. No API token, no login. Pay only for jobs delivered. Obeys robots.txt; never hits /api/, /rest/, or /apply/.

- **URL**: https://apify.com/iiphantom/softgarden-jobs-scraper.md
- **Developed by:** [Elisha](https://apify.com/iiphantom) (community)
- **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

## Softgarden Jobs Scraper: DACH Career Boards to JSON

**Turn any public Softgarden career board into clean, structured job data. No API token, no login, pay only for the jobs you get.**

More than 2,000 employers in Germany, Austria and Switzerland run their careers pages on Softgarden (`*.softgarden.io`). Many of those jobs never reach LinkedIn or StepStone, or show up there days later. This Actor reads the **public** boards directly and gives you one consistent row per job: title, employer, locations with coordinates, contract type, remote status, posted date, description and link.

***

### Who it's for

- **Recruiting and staffing agencies (DACH).** Spot new openings at your target accounts the day they go live, then pitch candidates first.
- **Job boards and aggregators.** Add the Softgarden long tail of Mittelstand, retail, logistics and tech employers to your index with daily incremental feeds.
- **HR-tech and labour-market analysts.** Track hiring velocity, roles and locations across hundreds of DACH employers.
- **Sales teams selling to HR.** "Company X just opened 12 warehouse roles in Halle" is a buying signal.

***

### What you get

- ✅ **Jobs from a board** in one dataset: title, company, hiring legal entity, category, locations (city + lat/lng), country, contract type (normalized), remote/hybrid/on-site, experience level, posted date (ISO), salary text when the employer publishes it, description (text or HTML), job URL, apply URL string.
- ✅ **Many boards per run.** Paste URLs or just slugs (`home24`, `acme`, …).
- ✅ **Incremental monitoring (`onlyNew`).** Schedule it daily and you're charged only for **new or changed** jobs.
- ✅ **Filters before billing.** Keyword, location and category filters run before charging, so dropped jobs cost nothing.
- ✅ **Empty boards are free**, and so are duplicates and boards that fail.
- ✅ **Fast and light.** HTTP-only (no browser): one request per board for listings, plus one per job when you want full details.
- ✅ **Polite by design.** Obeys robots.txt, keeps one request at a time per board with a delay, and backs off on errors.
- ✅ **Privacy-first.** No applicant data, no contact-person fields, and emails/phones redacted from descriptions by default.
- ✅ Export as JSON, CSV, Excel, or via API, webhooks, Make, n8n or Zapier.

#### Pagination / coverage note (v1)

Softgarden classic boards (`*.softgarden.io/{lang}/vacancies`) server-render job rows into the first HTML response. On probed boards — including a **535-job** board — the pagination control (`ul#job-search-pagination`) was **empty** and `?page=2` returned the same set. v1 therefore reads **all jobs present in that first HTML document**.

If Softgarden later enables multi-page listing via a robots-allowed path, we will add it. Paths under `/wicket/bookmarkable/` and `/*/widgets/` are **disallowed** by Softgarden `robots.txt` and are **never** requested. Do not assume infinite scroll or widget endpoints are used.

***

### How to use

1. Click **Try for free**.
2. Under **Boards**, add Softgarden board URLs or slugs:
   - `https://home24.softgarden.io`
   - `https://acme.softgarden.io/de/vacancies`
   - `acme`
3. (Optional) Add **Keywords**, **Locations** or **Categories** to narrow results.
4. (Optional) Turn on **Only new jobs** and set a **State key** (e.g. `dach-it-weekly`), then add a **Schedule** (daily or weekly).
5. Click **Start** and download your dataset.

**Where do I find a company's board?** Open the company's careers page. If job links go to `something.softgarden.io/job/…`, then `something` is the slug.

#### Input fields

| Field | What it does | Default |
| --- | --- | --- |
| `boards` *(required)* | Softgarden board URLs or slugs | — |
| `language` | Board locale: `auto`, `de`, `en` | `auto` |
| `includeDetails` | Fetch full job pages (description, contract type, date, …) | `true` |
| `descriptionFormat` | `text`, `html` or `both` | `text` |
| `redactContactDetails` | Remove emails/phone numbers from descriptions | `true` |
| `keywords` / `locations` / `categories` | Case-insensitive filters, OR within a field | empty |
| `maxJobsPerBoard` / `maxJobs` | Caps per board and per run (`0` = no cap) | `0` / `1000` |
| `onlyNew` + `stateKey` | Incremental mode: only new/changed jobs since the last run | `false` / `default` |
| `maxConcurrency` / `requestDelayMs` | Politeness controls | `2` / `1500` |
| `proxyConfiguration` | Optional Apify datacenter proxy | off |

#### Sample input

```json
{
  "boards": ["https://musterwerk.softgarden.io", "alpenblick-reisen", "zuerichtech"],
  "language": "de",
  "includeDetails": true,
  "keywords": ["Informatiker", "Developer", "Logistik"],
  "locations": ["Berlin", "Wien", "Zürich"],
  "maxJobs": 1000,
  "onlyNew": true,
  "stateKey": "dach-it-weekly"
}
```

Prefill / try boards: `home24`, `gtmotive1`.

***

### Sample output

One dataset item per job (example data):

```json
{
  "postingId": "67118342",
  "title": "Fachinformatiker:in Systemintegration (m/w/d)",
  "companyName": "Musterwerk Logistik",
  "hiringEntity": "Musterwerk Logistik GmbH & Co. KG",
  "boardSlug": "musterwerk",
  "boardUrl": "https://musterwerk.softgarden.io/de/vacancies",
  "jobUrl": "https://musterwerk.softgarden.io/job/67118342",
  "applyUrl": "https://jobdb.softgarden.de/jobdb/public/jobposting/applyonline/click?jp=67118342",
  "category": "IT",
  "locations": [
    { "city": "Berlin", "geoName": "Berlin, Deutschland", "latitude": 52.5200066, "longitude": 13.404954 }
  ],
  "country": "DE",
  "employmentType": "Vollzeit",
  "employmentTypeNormalized": "FULL_TIME",
  "remoteStatus": "Hybrid",
  "remoteType": "HYBRID",
  "experienceLevel": "Mit Berufserfahrung",
  "postedDate": "2026-09-28",
  "postedDateRaw": "28.09.26",
  "language": "de",
  "salaryText": "52.000 – 61.000 € brutto/Jahr",
  "descriptionText": "Wir sind Musterwerk Logistik – über 600 Kolleg:innen an 9 Standorten. Deine Aufgaben: Betrieb und Weiterentwicklung unserer Microsoft-365- und Linux-Infrastruktur …",
  "detailError": null,
  "contentHash": "3f1c9a0d7e5b2c48a1f6e9d03b7c5a2e4d8f1b60",
  "isNew": true,
  "firstSeenAt": "2026-10-05T18:02:11Z",
  "scrapedAt": "2026-10-05T18:02:11Z"
}
```

The dataset has two views: **Overview** (title, company, city, type, remote, date, link) and **Full** (all fields).

***

### Pricing: pay per event

**$1.50 per 1,000 jobs** ($0.0015 per job delivered to your dataset).

| You run… | Jobs charged | You pay |
| --- | --- | --- |
| 1 board, 25 jobs | 25 | ~$0.04 |
| 300 boards weekly, `onlyNew`, ~2,000 new jobs/month | 2,000 | ~$3.00 / month |
| Full pull of 50,000 jobs | 50,000 | ~$75.00 |

**Free:** empty boards, filtered-out jobs, duplicates, already-seen jobs in `onlyNew` mode, and failed or blocked boards. There's no per-board or per-run fee from us (standard Apify platform start rules apply). Set a **maximum cost per run** in Apify, and the Actor stops cleanly when it's reached.

**Listing-only billing:** If a detail page fails after retries, the Actor still pushes the listing row (title, location, URL, …), sets `detailError`, and charges **once** for that job. It never double-charges if a detail fetch later succeeds in the same run.

***

### FAQ

**Do I need a Softgarden account or API key?** No. The Actor reads only publicly published career pages, the same ones any job seeker sees.

**Does it apply to jobs or collect applicant data?** No. It never opens application forms, never signs in, and never touches candidate or talent-pool data. The `applyUrl` field is the public link string only — it is never requested.

**Why is a board returning 0 jobs?** Either the employer has no open positions (free), the slug is wrong, or the board is on a custom domain (not supported in v1).

**Can it handle company career sites that embed Softgarden?** v1 supports `*.softgarden.io` boards. Paste the softgarden.io link from any job ad.

**Does it paginate large boards?** Softgarden boards probed for v1 put all vacancies into the first HTML response (including a 500+ job board) with an empty pager. v1 scrapes that document. Robots-disallowed Wicket/widget endpoints are not used. See the pagination note above.

**How fresh is the data?** As fresh as your schedule. Daily with `onlyNew` is the sweet spot.

**What if detail enrichment fails?** You still get the listing row with `detailError` set, charged once (see Pricing).

***

### Responsible use and legal

- **Independent tool.** This Actor is built and maintained by Frontiersman. It is **not affiliated with, endorsed by, or sponsored by softgarden e-recruiting GmbH**. "Softgarden" is used only to describe compatibility, and all trademarks belong to their owners.
- **Public data only.** It accesses only publicly available job advertisements on `*.softgarden.io`. It does **not** use Softgarden's partner/Frontend APIs, client IDs or tokens, does not bypass logins or CAPTCHAs, and does not request paths disallowed by `robots.txt` (e.g. `/api/`, `/rest/`, `/apply/`, `/*/widgets/`, `/wicket/bookmarkable/`).
- **Softgarden terms context (read 2026-10-05).** Softgarden's [General Terms and Conditions](https://softgarden.com/en/terms/) (Rev. 4.0, valid from 26.03.2026) govern the contractual relationship between softgarden e-recruiting GmbH and its **customer companies** (platform account holders), not a public visitor ToS aimed at job seekers. They describe the SaaS recruiting platform, application handling, and placement services. Softgarden's public privacy materials describe CAPTCHA/IP checks used to detect automated access to **forms** and product surfaces. Separately, Softgarden publishes GEO/feed guidance for making career-page job data easier for automated systems to consume. **This Actor does not create Softgarden accounts, does not access applicant data, and does not call partner APIs.** Users remain responsible for ensuring their use of public career pages complies with applicable law and with any terms that apply to them. Rights holders with concerns can contact us via the Issues tab; we respond within 12 hours on business days.
- **Polite crawling.** Defaults: one request at a time per board, ~1.5 s delay with jitter, retries with backoff, and an automatic stop on blocks. Please don't schedule it more often than hourly against the same boards.
- **Personal data.** Job ads are business information, but they can mention people (e.g. a contact person). The Actor never extracts contact names into fields and redacts emails/phone numbers by default. If your use involves personal data, you are the controller and must have a lawful basis under GDPR (and Swiss FADP). Don't use the output for unsolicited direct marketing to individuals.
- **Your responsibility.** Check that your use complies with the terms of the sites you access and with applicable law.

***

### Roadmap

*Planned, subject to demand. This is an independent community Actor, not a Softgarden product.*

- 🔜 **Board discovery:** give a company website and we find its public Softgarden board (following public links only).
- 🔜 Support for custom-domain Softgarden career sites with identical public markup.
- 🔜 Robots-allowed pagination if Softgarden exposes it for very large boards.
- 🔜 Cheaper "listing-only" event for high-volume monitoring.
- 🔜 Sibling Actors for other DACH ATS boards.

Missing a field? Open an issue. We read every one.

# Actor input Schema

## `boards` (type: `array`):

Softgarden board URLs (https://acme.softgarden.io or …/de/vacancies) or bare slugs (acme). Only public \*.softgarden.io hosts are accepted in v1.

## `language` (type: `string`):

Board UI locale to request (/{lang}/vacancies). auto follows the board redirect.

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

Fetch each /job/{id} page for description, contract type, remote status, experience and posted date. false = listing fields only (1 request per board).

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

Format of the description when includeDetails is true.

## `redactContactDetails` (type: `boolean`):

Strip email addresses and phone numbers from description text/HTML. Contact names are never put into structured fields.

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

Case-insensitive match on title (and description if details are on). OR logic. Filtering runs before charging.

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

Case-insensitive match on city/geoName (e.g. Berlin, München, Wien).

## `categories` (type: `array`):

Match on the Softgarden job category text.

## `maxJobsPerBoard` (type: `integer`):

Cap per board. 0 = no limit.

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

Global cap per run (protects buyer spend). 0 = unlimited (still bounded by Apify max-charge).

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

Incremental mode: emit (and charge) only jobs not seen in previous runs with the same stateKey, plus jobs whose content hash changed.

## `stateKey` (type: `string`):

Name of the KV-store record that holds seen IDs and hashes for incremental mode.

## `maxConcurrency` (type: `integer`):

Max parallel requests across boards. Per-host stays at 1 regardless.

## `requestDelayMs` (type: `integer`):

Minimum delay between requests to the same host (±30% jitter). Hard floor is 500 ms.

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

Optional Apify datacenter proxy for spreading load. Never used to evade a block.

## Actor input object example

```json
{
  "boards": [
    "home24",
    "gtmotive1"
  ],
  "language": "auto",
  "includeDetails": true,
  "descriptionFormat": "text",
  "redactContactDetails": true,
  "keywords": [],
  "locations": [],
  "categories": [],
  "maxJobsPerBoard": 0,
  "maxJobs": 1000,
  "onlyNew": false,
  "stateKey": "default",
  "maxConcurrency": 2,
  "requestDelayMs": 1500,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

Structured Softgarden job rows in the default dataset.

# 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 = {
    "boards": [
        "home24",
        "gtmotive1"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("iiphantom/softgarden-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 = { "boards": [
        "home24",
        "gtmotive1",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("iiphantom/softgarden-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 '{
  "boards": [
    "home24",
    "gtmotive1"
  ]
}' |
apify call iiphantom/softgarden-jobs-scraper --silent --output-dataset

```

## MCP server setup

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