# jobs.ch Swiss Jobs Scraper (`loudtzu/jobs-ch-scraper`) Actor

Scrape Swiss job ads from jobs.ch: title, company, place, workload, dates and opt-in full description, salary, skills and benefits. Recruiter names and phones removed.

- **URL**: https://apify.com/loudtzu/jobs-ch-scraper.md
- **Developed by:** [LOUDTZU TZULOUD](https://apify.com/loudtzu) (community)
- **Categories:** Jobs
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.10 / 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

## jobs.ch Swiss Jobs Scraper

Scrapes public job ads from [jobs.ch](https://www.jobs.ch), Switzerland's largest job board, in German, French or English.

**What you get per job:** job ID, URL, title, company (name, ID, page), place, workload % (min/max), employment type and position IDs, first and latest publication date, "new" and "paid" flags and the logo.

**With "Include job details" switched on (opt-in, charged per job):** the full description and employer text, company website, posting/start/expiry dates, number of openings, employment type, work hours, postcode and locality, industry, category, salary range (when jobs.ch shows it), skills, benefits and languages.

### Privacy

- Recruiter contact fields (names, phones, photos) from jobs.ch are **never** copied.
- Names, phone numbers and e-mails inside descriptions are replaced with `[name]`, `[phone]` and `[email]` by a German/French/English masker. It is built on openly licensed name lists: Wikidata (CC0) given names and surnames for Germany, Switzerland, France, Belgium, Luxembourg, Albania, Kosovo, North Macedonia and other countries, and SCOWL (permissive licence) for common English words. Masking is heuristic: it errs on the side of masking, so a company named after a person (e.g. "Walter Mäder AG") may be masked too, and so may a company or department name placed right after a contact heading (e.g. "Kontakt\nMigros Aare" becomes "Kontakt\n\[name]"). Product prefixes such as "MS SQL" or "MS Office" are kept. After strong contact cues ("Kontakt:", "Ihre Ansprechperson ist", "Your contact is", "Bewerbung an", "X (HR) freut sich") an unlisted two-word name is masked too, unless a word is an ordinary German word form (Wikidata lexemes, CC0, `src/data/de_wikidata_forms.txt.xz`), a Swiss or German place word (Wikidata, CC0, `src/data/ch_places.txt.xz`, `src/data/de_places.txt.xz`), a common English word, or a company/department word (AG, GmbH, Recruiting, Klinik, Service …). All data files are CC0, SCOWL (MIT-style) or OGL v3; no GPL data.
- Phone numbers and e-mails get a final pass over every text field just before saving (shared masker, 0.2.6): Swiss, German, Austrian, Dutch, Polish and other international formats (+CC, 00CC, (0), brackets, dots, slashes, digits glued to "T"/"Tel"/"WhatsApp") and spelled-out e-mails ("at"/"dot", "(at)", "punkt"). Labelled reference numbers (Ref., Referenz-Nr., UID, CHE-…) and salaries are kept. Links, image URLs and IDs are never changed.
- French/Italian/English contact cues with a role title ("Votre contact: responsable RH …", "Persona di contatto: responsabile …", "Your contact: Head of HR …") and same-line greetings ("Freundliche Grüsse, …") are masked. Known over-mask: a role word followed by a project or place name ("Kontakt: Bauleiter Neubau Süd") can become "Bauleiter \[name]".

### How it works

Only the public HTML search and vacancy pages are read (no `/api/` calls, which robots.txt disallows), with plain HTTP requests over Apify datacenter proxy. No login.

### Input

| Field | Description |
|---|---|
| Search terms | Keywords, e.g. `python`, `Pflege`, `comptable`. jobs.ch no longer has a keyword-less "all jobs" listing, so if you leave this and Start URLs empty the Actor searches the default keyword `Informatik` and says so in the run status. |
| Locations | Swiss places or cantons, e.g. `Zürich`, `Genève`. Every term is searched in every location. |
| Search URLs | Optional jobs.ch search page URLs, with any filters set on jobs.ch. |
| Max jobs | Total cap (default 100, up to 50,000). |
| Include job details | Opens every vacancy page (slower, charged per job). |
| Language | `de`, `fr` or `en` (labels and links). |

### Pricing

Pay per event (beta):

| Event | Price |
|---|---|
| Run start (once per run, charged only after the first job is saved; failed runs and runs with 0 jobs cost $0) | $0.0007 |
| Job (search results data) | $0.0001 ($0.10 per 1,000) |
| Job details (opt-in, per job whose vacancy page was read) | $0.0001 ($0.10 per 1,000) |

So 1,000 jobs cost $0.1007 for search data, or $0.2007 with details.

#### How this compares (Apify Store, checked 2026-10-24, cheapest tier shown)

| Actor | Per 1,000 jobs | Start fee | 1,000 jobs |
|---|---|---|---|
| **This Actor** | $0.10 (+$0.10 details) | $0.0007 | $0.10 / $0.20 with details |
| santamaria-automations | search $2.87 Free / $2.75 Bronze / $2.60 Silver / $2.49 Gold+; details $5.00 Free+Bronze / $4.75 Silver / $4.50 Gold+ | $0.001 | $2.49–$2.87 / $6.99–$7.87 with details |
| lexis-solutions | $1.91 Free → $1.27 Gold+ | $0.0025 | $1.27–$1.91 |
| blackfalcondata | $2.00 | $0.001 | $2.00 |
| gubidonius | $0.01 | $0.00001 | $0.01 |
| deriverge | $0.50 Free → $0.25 Gold+, details included | none | $0.25–$0.50 |
| automation-lab | $1.84 → $0.448 | $0.005 | from $0.45 |
| northbell | $0.80 → $0.64 | $0.01 | from $0.65 |
| piotrv1001 | $0.80 | none | $0.80 |
| jpmarketdata | $0.90 | none | $0.90 |
| plainrows | $1.20 → $0.90 | none | from $0.90 |
| unfenced-group | $1.50 → $0.90 | none | from $0.90 |
| shahidirfan | $0.99 | $0.0005 | $0.99 |
| scrapestorm (search, 56 users) | $2.89 | $0.00005 | $2.89 (details: separate Actor, $2.99 / 1k) |

**Honest notes:**

- **gubidonius is cheaper at every run size** ($0.01 per 1,000 jobs; it has 2 users).
- **deriverge is cheaper for very small runs:** under 5 jobs on its Gold tier (under 2 on Free), or under 14 jobs with details on Gold (tie at 14; under 3 on Free). Above that, this Actor costs less.
- It is cheaper than santamaria-automations, lexis-solutions, blackfalcondata, scrapestorm and every other jobs.ch Actor listed above at every run size and on every plan (e.g. 1 job: $0.0008 against santamaria's $0.0035+; 1,000 jobs with details: $0.2007 against $6.99+).
- **What it does not do:** no recruiter contact fields (by design; santamaria's details include contact details), no Italian site language (only de/fr/en), and no "new jobs only" / incremental mode (blackfalcondata and deriverge have one).
- **Masking gaps:** names are found by cues (Kontaktperson, Ansprechperson, Ihr Kontakt, Votre contact, Persona di contatto, 'steht Ihnen (gerne)', 'erteilt Ihnen gerne', 'beantwortet', 'Cordialement,', 'Kind regards,', 'X Y freut sich', a name line followed by a role or phone line) and by the name lists. A name with no cue and not on a list, in running text, can still get through; a company named after a person can be masked.

# Actor input Schema

## `searchTerms` (type: `array`):

Keywords, e.g. 'python' or 'Pflege'. jobs.ch has no keyword-less listing, so if you leave this (and Start URLs) empty the Actor searches the default keyword 'Informatik'.

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

Swiss places or cantons, e.g. 'Zürich', 'Genève'. Each term is searched in each location.

## `startUrls` (type: `array`):

Optional jobs.ch search page URLs (with any filters set on jobs.ch).

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

Stop after this many jobs in total.

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

Open every vacancy page for the description, salary, skills, benefits and more (charged per job).

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

jobs.ch site language for labels and links.

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

Datacenter proxy is enough.

## Actor input object example

```json
{
  "searchTerms": [
    "python"
  ],
  "locations": [
    "Zürich"
  ],
  "maxItems": 20,
  "includeDetails": false,
  "language": "de",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `results` (type: `string`):

All jobs, overview view.

# 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 = {
    "searchTerms": [
        "python"
    ],
    "locations": [
        "Zürich"
    ],
    "maxItems": 20,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("loudtzu/jobs-ch-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 = {
    "searchTerms": ["python"],
    "locations": ["Zürich"],
    "maxItems": 20,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("loudtzu/jobs-ch-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 '{
  "searchTerms": [
    "python"
  ],
  "locations": [
    "Zürich"
  ],
  "maxItems": 20,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call loudtzu/jobs-ch-scraper --silent --output-dataset

```

## MCP server setup

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