# JobMittelland.ch Scraper - Mittelland Region Job Board (`maximedupre/miit`) Actor

Collect public JobMittelland.ch jobs by keyword or job URL. Get titles, employers, locations, workload, and full job text, plus pay and contact details when listed. Use the data for hiring research and job lists.

- **URL**: https://apify.com/maximedupre/miit.md
- **Developed by:** [Maxime Dupré](https://apify.com/maximedupre) (community)
- **Categories:** Jobs, Business, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$2.70 / 1,000 job listings

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

### 🔎 Collect JobMittelland.ch jobs for hiring research

Recruiters and job-market researchers can use this JobMittelland.ch scraper to turn public listings into data for job lists and hiring research. Search by keyword or submit job URLs to get titles, employers, locations, workload, and full job text. Pay, dates, application links, and public contacts are included when the source lists them.

- Find **[Jobs in Bern](https://apify.com/maximedupre/miit/examples/jobs-in-bern)** for a local job list.
- Use **[Part Time Jobs Switzerland](https://apify.com/maximedupre/miit/examples/part-time-jobs-switzerland)** to find roles with a smaller workload.
- Collect **[Direct Employer Jobs Switzerland](https://apify.com/maximedupre/miit/examples/direct-employer-jobs-switzerland)** for hiring research.
- Find **[Recruitment Agency Jobs Switzerland](https://apify.com/maximedupre/miit/examples/recruitment-agency-jobs-switzerland)** to review agency listings.
- Review **[Latest Jobs Switzerland](https://apify.com/maximedupre/miit/examples/latest-jobs-switzerland)** with newer listings first.

#### 📦 Job and employer data you get

Each saved row is one unique JobMittelland.ch job listing. It includes the job ID, title, URL, and employer name. Other fields depend on what the source makes public.

You can get the full job description, workload range, employment terms, remote-work details, and location. Available employer details include a website, description, address, logo, social links, and benefits. Listed pay, dates, application links, and contacts help you review each role.

The first eligible match is saved as it is found. Later matches for the same job are ignored. A saved row is not changed to collect later matches.

#### 🚀 Run a JobMittelland.ch search

1. Choose `Keyword search` and enter a job title or search term.
2. Add location, workload, or employer filters if needed. All keywords share these filters.
3. Keep `Maximum jobs` small for your first run.
4. Run the Actor, then open `Job listings` to view the dataset.

For known jobs, choose `Job URLs` and paste their JobMittelland.ch listing URLs. Search filters and `Maximum jobs` do not apply to this mode.

#### ⚙️ Input

**Input fields**

| Field | Type | What it does |
| --- | --- | --- |
| `discoveryMethod` | string | Required. Use `keywords` for keyword search or `urls` for known job URLs. |
| `keywords` | array of strings | Job titles or search terms. All keywords use the same filters. |
| `locations` | array of strings | Swiss cantons, districts, or cities for keyword search. Leave empty for all locations. |
| `minWorkload` | integer | Lowest workload percentage for keyword search, from 0 to 100. |
| `maxWorkload` | integer | Highest workload percentage for keyword search, from 0 to 100. Must be at least the minimum. |
| `employerType` | string | `all`, `direct`, or `agency` for keyword search. Defaults to `all`. |
| `sortBy` | string | `newest` or source `relevance` order for keyword search. Defaults to `newest`. |
| `jobUrls` | array of URL entries | JobMittelland.ch listing URLs for URL mode. Add each URL as an object with a `url` field. Search filters do not apply. |
| `maxItems` | integer | Stops keyword search after this many jobs. Minimum 1, with no fixed upper bound. Leave empty to return all available matches until the source is exhausted. Does not limit submitted job URLs. |

**Example input**

This input comes from a successful default-input run:

```json
{
  "discoveryMethod": "keywords",
  "keywords": [
    "Softwareentwickler"
  ],
  "employerType": "all",
  "sortBy": "newest",
  "maxItems": 1
}
```

#### 🧾 Output

Open the `jobs` output link to view the default dataset. Both input modes return the same job shape. `id`, `title`, `url`, and `employer.name` are required. Other fields may be absent when the source does not provide them.

**Job listing fields**

| Field | Type | What it does |
| --- | --- | --- |
| `id` | string | Source job ID. Use it to match the same job across runs. |
| `title` | string | Job title as listed by the source. |
| `url` | string | Source job listing URL. |
| `employer` | object | Employer name and available profile details. |
| `employer.name` | string | Employer name. |
| `employer.websiteUrl` | string | Linked employer website. |
| `employer.description` | string | Public employer description. |
| `employer.address` | string | Public employer address. |
| `employer.logoUrl` | string | Employer logo URL. |
| `employer.socialProfiles` | array of strings | Social profile URLs listed by the source. |
| `employer.benefits` | array of strings | Listed employer benefits. |
| `location` | object | Listed job location. |
| `location.city` | string | City where the job is based. |
| `location.district` | string | District where the job is based. |
| `location.canton` | string | Swiss canton. |
| `location.postalCode` | string | Listed postal code. |
| `location.country` | string | Listed country. |
| `workload` | object | Advertised workload range in percent. |
| `workload.min` | number | Lowest advertised workload percentage. |
| `workload.max` | number | Highest advertised workload percentage. |
| `employmentTerms` | array of strings | Listed terms, such as contract type or duration. |
| `remoteWork` | string | Listed remote-work arrangement. |
| `description` | string | Complete public job description as text. |
| `applicationUrl` | string | Application destination linked by the source. |
| `publishedAt` | string | Source publication date or time. |
| `expiresAt` | string | Source expiration date or time. |
| `compensation` | object | Listed pay amounts, currency, and pay period. |
| `compensation.min` | number | Lowest advertised pay amount. |
| `compensation.max` | number | Highest advertised pay amount. |
| `compensation.currency` | string | Currency stated for pay. |
| `compensation.period` | string | Stated pay period, such as hour or year. |
| `contacts` | array of objects | Public job application and contact details. |
| `contacts[].name` | string | Listed contact name. |
| `contacts[].role` | string | Listed contact role. |
| `contacts[].email` | string | Public contact email. |
| `contacts[].phone` | string | Public contact phone number. |

**Example job listing**

This complete row comes from a successful run of the current beta build:

```json
{
  "id": "367426",
  "title": "Web-Developer:in Fokus Support – 80–100%",
  "url": "https://www.jobmittelland.ch/job/vacancy/367426",
  "employer": {
    "name": "Previon Plus AG",
    "websiteUrl": "https://previon.ch/",
    "description": "Wir können vieles.\n\nZusammen können wir alles.\n\nGegründet 2013 in Aarau hat sich Previon von einer mutigen Idee zu einer schweizweit gefragten KI- und Digitalagentur entwickelt, die digitale und KI-Lösungen für die Unternehmensziele von morgen schafft. Unser Anspruch: Menschen in den Mittelpunkt zu stellen und Technologie so einzusetzen, dass sie begeistert, verbindet – und wirkt.\n\nErfahre hier mehr über unsere Story.",
    "address": "Aeschbachweg 12 5000 Aarau Schweiz",
    "logoUrl": "https://barberry.jobmittelland.ch/0d32e3f1fa808b97a1d6_176x88bgFFFFFFcanvas176x88trimFFFx5.jpeg"
  },
  "location": {
    "city": "Aarau",
    "postalCode": "5000",
    "canton": "Aargau",
    "country": "ch"
  },
  "workload": {
    "min": 80,
    "max": 100
  },
  "employmentTerms": [
    "Festanstellung"
  ],
  "remoteWork": "Homeoffice",
  "description": "Deine Mission bei Previon\n\nKommunikation als Kernaufgabe : Du bist für unsere Kund:innen die erste Anlaufstelle, im Ticket, per Mail oder auch mal per Telefon. Du hörst zu, fragst nach, erklärst Technisches verständlich und gibst auch dann eine ehrliche Rückmeldung, wenn es länger dauert oder etwas schiefgelaufen ist.\n\nSupport-Tickets: Du nimmst Anfragen unserer Kund:innen entgegen, klärst nach, ordnest ein und bearbeitest sie, von der Konfigurations-Anpassung bis zum echten Bug oder einer kleinen Erweiterung.\n\nSupport-Desk im Griff : Du überwachst den Support-Desk selbständig, behältst Prioritäten und Fristen im Blick, koordinierst dich mit dem Team und sorgst dafür, dass nichts liegen bleibt.\n\nErste Schritte in der Entwicklung : Du setzt kleinere Anpassungen und Bugfixes selbst auf Basis von Drupal, Laravel und JavaScript um. Je nach Wissen auch im Frontend mit HTML und CSS.\n\nKI im Entwicklungsalltag : Du arbeitest von Beginn weg mit KI-gestützten Tools wie Claude Code und lernst, wo sie dich schneller machen und wo du selber hinschauen musst.\n\nLernen im Team : Code Reviews, Pair Programming und erfahrene Kolleg:innen, die dir zeigen, warum eine Lösung nicht nur funktioniert, sondern auch in Jahren noch trägt.\n\nDeine Entwicklung : Je nach Eignung und Interesse entwickelst du dich weiter; Richtung Backend, Frontend, Requirements und Projektarbeit. Den Weg bestimmst du mit.\n\nBei Previon bekommst du eine saubere Einarbeitung, Kolleg:innen, die deine Fragen ernst nehmen, und ein Team, das nicht nur gut zusammenarbeitet, sondern auch gut zusammen lacht.\n\nDas bringst du mit\n\nDu bist ausgesprochen kommunikativ. Du gehst offen auf Menschen zu, schreibst verständlich und behältst auch dann einen freundlichen Ton, wenn dein Gegenüber gestresst oder verärgert ist.\n\nAbgeschlossene Ausbildung als Informatiker:in EFZ Fachrichtung Applikationsentwicklung. Ob du direkt ab Lehre kommst oder bereits zwei bis drei Jahre Berufserfahrung mitbringst, spielt für uns keine Rolle, wir richten die Aufgaben nach deinem Stand aus.\n\nGrundlegende Kenntnisse in Webtechnologien sind notwendig: PHP, HTML, CSS und JavaScript solltest du nicht zum ersten Mal sehen.\n\nDu organisierst dich gut, arbeitest zuverlässig und bleibst an einem Thema dran, bis es erledigt ist.\n\nDu arbeitest strukturiert und fragst nach, statt zu raten.\n\nNeugier auf KI-gestützte Entwicklungstools und Lust, damit deine eigene Arbeitsweise zu schärfen.\n\nDeutsch stilsicher in Wort und Schrift, Englisch für technische Dokumentation und den Austausch mit deinen Kolleg:innen.\n\nTogether With Us\n\nWir sind ein ambitioniertes Team mit vielfältigen Hintergründen und einer gemeinsamen Leidenschaft: das grosse Ganze denken und trotzdem über die kleinen Details diskutieren.\n\nBei uns findest du:\n\nFlexibilität : Hybrides Arbeiten und flexible Arbeitszeiten.\n\nWeiterentwicklung : Gezielte Schulungen und Trainings, damit deine Skills nicht auf dem Stand von gestern bleiben.\n\nTeamkultur : Gemeinsame Kaffee- und Bierpausen, anspruchsvolle Projekte und Teamevents, über die noch Monate später gesprochen wird.\n\nLeidenschaft fürs Leben : Wir sind Mütter, Väter, Ehepartner:innen, Hobbyköch:innen, Sportler:innen und Geniesser:innen – und wissen, dass gute Arbeit ein gutes Leben daneben braucht.\n\nWir sind überzeugt: Mit Leidenschaft und dem richtigen Team lässt sich viel bewegen und unsere Arbeit macht für unsere Kund:innen einen echten Unterschied.\n\nPrevion Plus AG\n\nAeschbachweg 12\n\n5000 Aarau\n\nClaudio Scicchitano\n\nCOO\n\n+41 58 680 28 28\n\ncscicchitano@previon.ch",
  "publishedAt": "2026-09-15 14:18:31.796459+0200",
  "expiresAt": "2026-10-15",
  "contacts": [
    {
      "name": "Claudio Scicchitano",
      "role": "COO",
      "email": "cscicchitano@previon.ch",
      "phone": "+41 58 680 28 28"
    }
  ]
}
```

#### 💳 Pricing

This Actor uses pay-per-event pricing. Each unique public job listing saved to the dataset creates one `Job listing` charge. Runs with no saved jobs do not create this charge. Check the current price shown on the Actor page before running.

Use `maxItems` to limit jobs from keyword search. For URL mode, the number of submitted job URLs bounds the work.

#### 🔌 Integrations

Export the dataset as JSON or CSV for your own tools. You can run the Actor through the Apify API, set an Apify schedule, or use an Apify webhook after a run. For repeated research, compare job IDs across your saved exports.

https://www.youtube.com/watch?v=bNACk1_S_6w\&list=PLObrtcm1Kw6MUrlLNDbK9QRg8VDJg0gOW\&index=4

#### ❓ FAQ

##### Do filters apply to submitted job URLs?

No. Location, workload, employer, and search-order settings apply only to keyword search. `maxItems` also applies only to keyword search.

##### Can each keyword use its own filters?

No. All keywords share the same search settings in a run. Use separate runs for different filters.

##### Why are pay or contact fields missing?

Those fields are included only when the source makes them public. Missing extra details do not prevent a useful job row from being saved.

##### Can I leave the job limit empty?

Yes. Leave `maxItems` empty to return all available matches until the source is exhausted. There is no fixed upper bound in the input schema.

##### Are duplicate jobs saved again in the same run?

No. The first eligible occurrence is saved. Later matches for the same source job are ignored, and the saved row keeps its first match.

##### Does the Actor track job changes or apply for jobs?

It returns current public listings. It does not keep a history, label changes, apply for jobs, or contact employers. You can compare saved exports in your own workflow.

##### Do I need a JobMittelland.ch account?

No. The Actor reads public listings without buyer authentication.

### 📝 Changelog

**v0.0** (04-10-2026)

- Initial release.

### 🆘 Support

For issues, questions, or feature requests, [file a ticket](https://console.apify.com/actors/maximedupre~miit/issues) and I'll fix or implement it in less than 24h 🫡

### 🔗 Related Actors

- [Welcome to the Jungle Jobs Scraper](https://apify.com/maximedupre/welcometothejungle-jobs-extractor) collects job listings across English and French markets for broader hiring research.
- [CWjobs Scraper](https://apify.com/maximedupre/cwjobs-scraper) collects UK tech jobs for role and salary research.
- [Jobsite Scraper](https://apify.com/maximedupre/jobsite-scraper) collects broader UK job listings with employer and application details.
- [Handshake Jobs Scraper](https://apify.com/maximedupre/handshake-jobs-scraper) collects public Handshake jobs for job-market research.
- [JobMittelland.ch Scraper - Mittelland Region Job Board](https://apify.com/santamaria-automations/jobmittelland-ch-scraper) offers another way to collect listings from the same Swiss job source.

**Made with ❤️ by Maxime Dupré**

# Actor input Schema

## `discoveryMethod` (type: `string`):

Search with keywords or fetch jobs from their listing URLs.

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

Enter one or more job titles or search terms. All keywords use the same search filters.

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

Restrict the search to Swiss cantons, districts, or cities. Enter one place per line, such as Bern. Leave empty to search all locations.

## `minWorkload` (type: `integer`):

Lowest workload percentage to include in keyword search. Use a value from 0 to 100.

## `maxWorkload` (type: `integer`):

Highest workload percentage to include in keyword search. Use a value from 0 to 100, at least as high as the minimum.

## `employerType` (type: `string`):

Choose which employers to include in keyword search.

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

Show the newest jobs first or use the source relevance order.

## `jobUrls` (type: `array`):

Add JobMittelland.ch job listing URLs. Search filters do not apply to these jobs.

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

Stop keyword search after this many jobs. Leave empty to return all available matches until the source is exhausted. This limit does not apply to submitted job URLs.

## Actor input object example

```json
{
  "discoveryMethod": "keywords",
  "keywords": [
    "Softwareentwickler"
  ],
  "employerType": "all",
  "sortBy": "newest",
  "maxItems": 1
}
```

# Actor output Schema

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

Open the job listings saved 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 = {
    "discoveryMethod": "keywords",
    "keywords": [
        "Softwareentwickler"
    ],
    "maxItems": 1
};

// Run the Actor and wait for it to finish
const run = await client.actor("maximedupre/miit").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 = {
    "discoveryMethod": "keywords",
    "keywords": ["Softwareentwickler"],
    "maxItems": 1,
}

# Run the Actor and wait for it to finish
run = client.actor("maximedupre/miit").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 '{
  "discoveryMethod": "keywords",
  "keywords": [
    "Softwareentwickler"
  ],
  "maxItems": 1
}' |
apify call maximedupre/miit --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,maximedupre/miit"
        }
    }
}
```

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/21XWOvhDqoMZECe8e/builds/yD3ZQBnjZT5160fhn/openapi.json
