# jobs.ch Scraper — Swiss Vacancies, Workload & Employers (`logiover/jobs-ch-scraper`) Actor

Scrape jobs.ch, Switzerland's largest job platform: title, employer, place of work, advertised workload percentage as a numeric range, contract type and easy-apply flag. Filter by keyword, location, workload and recency. Keyless. JSON, CSV or Excel.

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

## Pricing

from $1.50 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
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

## jobs.ch Scraper — Swiss Vacancies, Workload & Employers

Export vacancies from **jobs.ch**, Switzerland's largest job platform — title, employer, place of work, workload percentage and contract type — to JSON, CSV or Excel. Keyless, no login.

### What does jobs.ch Scraper do?

jobs.ch renders its results server-side, so this Actor reads them without a browser and stays cheap at volume.

The field that makes Swiss job data different is **workload**. Vacancies here are not simply full-time or part-time; they are advertised as a percentage range — "80 – 100%", "60 – 80%". That range is the single most important filter in the Swiss market and it is exported three ways: the label as printed, and the lower and upper bounds as numbers, so you can actually filter for "at least 80%" without parsing text.

The site is built with build-hashed atomic CSS, which means there is no stable card class to anchor on and any scraper written against those class names breaks on the next deploy. This Actor anchors on the vacancy link instead and reads each fact by its own label — "Place of work", "Workload", "Contract type" — which survives redesigns. Those labels are rendered as visually hidden text for screen readers, and that same accessibility markup is what makes the extraction reliable.

### Who is it for?

- **Recruitment agencies** tracking Swiss demand by role, canton and workload.
- **Employer-brand and HR teams** benchmarking how competitors advertise.
- **B2B sales teams** using active hiring as a buying signal in Switzerland.
- **Job aggregators** needing a clean, deduplicated Swiss feed.
- **Labour-market analysts** measuring part-time share and contract mix.

### Use cases

- Pull every engineering vacancy in Zurich advertised at 80% or more.
- Measure what share of vacancies in a canton are part-time.
- Build a list of companies hiring this month as sales prospects.
- Compare permanent versus temporary demand across regions.
- Track weekly hiring volume for a role on a schedule.

### Why use this Actor?

- **Workload as numbers** — from and to percentages, not just a label.
- **Employer name and logo** on every row.
- **Contract type** as its own column.
- **Redesign-resistant parsing** — anchored on labels, not on hashed CSS classes.
- **Easy-apply flag** to spot low-friction applications.
- **Keyless and browserless** — no login, no headless Chrome, low cost per row.

### What data can you extract?

Every row carries the job ID, title and URL, employer name and logo, place of work, the workload label plus numeric from/to percentages, contract type, the freshness label, and an easy-apply flag.

### How to use it

1. Enter your **keywords** — a job title, a skill or a company.
2. Optionally set a **location**: Zurich, Geneva, Bern, or a canton.
3. Narrow by workload percentage or how recently the vacancy was published.
4. Set **Maximum results** and run, then export JSON, CSV or Excel.

### Input example

```json
{
  "keywords": "data engineer",
  "location": "Zurich",
  "workloadFrom": 80,
  "publicationDate": 14,
  "maxResults": 1000
}
```

### Notes and limits

- Swiss adverts rarely publish salary, and jobs.ch does not show it on the result card, so there is no salary column — an always-empty field would be worse than none.
- The freshness label is relative ("2 weeks ago") because that is what the card provides; use the publication-date filter if you need a hard cut-off.
- Vacancies are posted in German, French, Italian and English depending on the region; the Actor requests the English interface, but the advert text stays in its original language.
- The card carries the summary fields only — open the job URL for the full description and application form.
- Postings are employer content; check the site's terms and applicable law for how you reuse them.

### FAQ

**Do I need a jobs.ch account?**
No. Search results are public and the Actor needs nothing from you.

**What does the workload percentage mean?**
It is the share of a full-time position. 100% is full-time, 80% is four days a week. Swiss employers advertise a range because they are often flexible.

**Can I search all of Switzerland?**
Yes — leave the location empty.

**Will this break when the site is redesigned?**
It is built to resist that: fields are found by their accessibility labels rather than by CSS class names, which change on every deploy.

**How am I charged?**
Pay per result — you pay for the vacancies delivered.

# Actor input Schema

## `keywords` (type: `string`):

Job title, skill or company to search for, e.g. "software engineer" or "Pflegefachfrau".

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

City, canton or postcode, e.g. Zurich, Geneva, Bern. Leave empty to search all of Switzerland.

## `workloadFrom` (type: `integer`):

Swiss vacancies are advertised as a workload percentage. 0 disables the filter.

## `workloadTo` (type: `integer`):

Upper bound of the advertised workload percentage. 0 disables the filter.

## `publicationDate` (type: `integer`):

Only return vacancies published in the last N days. 0 disables the filter.

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

Stop after this many vacancies. jobs.ch renders 20 per page and the Actor walks pages until the target is met.

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

jobs.ch renders its results server-side; the default datacenter proxy is enough.

## Actor input object example

```json
{
  "keywords": "software engineer",
  "workloadFrom": 0,
  "workloadTo": 0,
  "publicationDate": 0,
  "maxResults": 500,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `jobId` (type: `string`):

No description

## `jobTitle` (type: `string`):

No description

## `jobUrl` (type: `string`):

No description

## `companyName` (type: `string`):

No description

## `companyLogoUrl` (type: `string`):

No description

## `placeOfWork` (type: `string`):

No description

## `workloadLabel` (type: `string`):

No description

## `workloadFromPercent` (type: `string`):

No description

## `workloadToPercent` (type: `string`):

No description

## `contractType` (type: `string`):

No description

## `postedLabel` (type: `string`):

No description

## `isEasyApply` (type: `string`):

No description

## `country` (type: `string`):

No description

## `source` (type: `string`):

No description

## `scrapedAt` (type: `string`):

No description

# 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 = {
    "keywords": "software engineer",
    "location": "",
    "workloadFrom": 0,
    "workloadTo": 0,
    "publicationDate": 0,
    "maxResults": 500,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("logiover/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 = {
    "keywords": "software engineer",
    "location": "",
    "workloadFrom": 0,
    "workloadTo": 0,
    "publicationDate": 0,
    "maxResults": 500,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("logiover/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 '{
  "keywords": "software engineer",
  "location": "",
  "workloadFrom": 0,
  "workloadTo": 0,
  "publicationDate": 0,
  "maxResults": 500,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call logiover/jobs-ch-scraper --silent --output-dataset

```

## MCP server setup

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