# Jobs.ch Scraper - Swiss Job Listings API (`kamerozkan/jobs-ch-scraper`) Actor

Scrape job listings from jobs.ch, Switzerland's largest job board: full descriptions, company, address, workload (Pensum), skills, languages and apply links. Filter by keyword, location and date. New-jobs-only mode for job alerts.

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

## Pricing

from $0.72 / 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.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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 Scraper - Swiss Job Listings API

**Scrape job listings from jobs.ch, Switzerland's largest job board**, as clean structured data: title, company, street address, canton, workload (Pensum), required languages, skills, apply method and link, publication and expiry dates, plus the **full job description**. Search by keyword and location, keep only recent jobs, or run it on a schedule in **new-jobs-only mode** so you pay only for listings you have not seen yet.

No jobs.ch account, API key, cookies or proxy setup needed.

### What does Jobs.ch Scraper do?

It runs the same keyword and location search you would run on [jobs.ch](https://www.jobs.ch) and returns every matching job as one row, with the details page already opened for you. Results come as JSON, CSV, Excel or via the Apify API, so you can feed a job board, a CRM, a spreadsheet or a dashboard without copying anything by hand. Like every Apify Actor, it can be scheduled, called from code and connected to Make, n8n, Zapier or a webhook.

### Who is it for?

- **Recruiters and staffing agencies in Switzerland**: see which companies are hiring for your specialties in Zürich, Bern, Basel, Geneva or Lausanne, with workload and language requirements, and contact them first.
- **Job boards and aggregators**: import fresh Swiss listings daily with stable job IDs, expiry dates and apply links.
- **HR and labour-market analysts**: track demand for roles, skills and languages by canton and over time.
- **Sales teams selling to HR**: build lead lists of companies that are actively hiring, with company type (SME or large company).

### What data can you get from jobs.ch?

| Field | Example |
|---|---|
| `jobId` | `24bed6ed-7416-480a-b55f-6400d13e8285` |
| `title` | `.NET Software Engineer` |
| `company` | `Furado AG` |
| `companyType` | `SME` or `large company` |
| `street`, `postalCode`, `city`, `canton`, `country` | `Tödistrasse 46`, `8810`, `Horgen`, `ZH`, `CH` |
| `latitude`, `longitude` | `47.26055`, `8.58444` |
| `workloadMinPercent`, `workloadMaxPercent` | `80`, `100` (the Swiss "Pensum") |
| `languages` | `[{"language": "de", "level": 3}, {"language": "en", "level": 2}]` |
| `skills` | `["Business Development", "Key Account Management"]` when the employer lists them |
| `applicationMethod`, `quickApply` | `form`, `true` |
| `externalUrl` | the employer's own application link when the job uses one |
| `url` | jobs.ch link in English, German or French |
| `publishedAt`, `firstPublishedAt`, `expiresAt` | `2026-09-10T15:38:06+02:00`, `2026-09-10T13:38:06+00:00`, `2026-10-11` |
| `logoUrl` | company logo on jobs.ch |
| `description` | full job text, plain text without HTML |

Contact persons are never returned as fields, and private e-mail addresses inside descriptions are masked. Anonymous postings have `companyVisible: false` and an empty `company`.

### How much does it cost to scrape jobs.ch?

You pay only for jobs delivered to your dataset: **$0.90 per 1,000 jobs** on the Free plan, with lower prices on paid Apify plans (up to 20% off). Platform usage is included.

Worked example: a daily alert for "Software Engineer" in Zürich that returns 40 new jobs a day costs 40 x $0.0009 = $0.036 per day, about $1.08 per month. A one-off export of 1,000 jobs costs $0.90. Set **Max jobs** or a maximum cost per run to cap spending; the run stops cleanly at your limit.

### How to scrape jobs.ch

1. Click **Try for free**.
2. Enter one or more **search terms** (for example `Software Engineer`, `Pflegefachfrau` or `comptable`) and a **location** such as `Zürich`, or leave the location empty for all of Switzerland.
3. Optionally set **Published within (days)**, turn on **Only new jobs** for alerts, and set **Max jobs**.
4. Click **Start**. A run of 50 jobs with descriptions takes about 10 seconds.
5. Download the results as JSON, CSV or Excel, or read them through the API.

For a daily job alert, save the input as a task, turn on **Only new jobs** and add an Apify Schedule. Each run then returns only listings that earlier runs did not deliver.

### Input example

```json
{
  "searchTerms": ["Software Engineer"],
  "location": "Zürich",
  "publishedWithinDays": 7,
  "includeDescription": true,
  "urlLanguage": "en",
  "onlyNewJobs": false,
  "maxItems": 20
}
```

jobs.ch returns at most 2,000 jobs per search term. For larger exports, split the search by term or location.

### Output example

A real row from a test run on 2026-10-09 (description shortened):

```json
{
  "jobId": "24bed6ed-7416-480a-b55f-6400d13e8285",
  "title": ".NET Software Engineer",
  "company": "Furado AG",
  "companyVisible": true,
  "companyType": "SME",
  "place": "Horgen",
  "street": "Tödistrasse 46",
  "postalCode": "8810",
  "city": "Horgen",
  "canton": "ZH",
  "country": "CH",
  "latitude": 47.26055,
  "longitude": 8.58444,
  "workloadMinPercent": 100,
  "workloadMaxPercent": 100,
  "languages": [{"language": "de", "level": 3}, {"language": "en", "level": 2}],
  "applicationMethod": "form",
  "quickApply": true,
  "externalUrl": null,
  "url": "https://www.jobs.ch/en/vacancies/detail/24bed6ed-7416-480a-b55f-6400d13e8285/",
  "publishedAt": "2026-09-10T15:38:06+02:00",
  "firstPublishedAt": "2026-09-10T13:38:06+00:00",
  "expiresAt": "2026-10-11",
  "description": "Your main responsibilities:\nMaintain, support, and further develop existing .NET desktop applications in combination with SQL Server.\n...",
  "searchQuery": "Software Engineer",
  "searchLocation": "Zürich",
  "scrapedAt": "2026-10-09T12:23:38Z"
}
```

The dataset has two views: **Overview** (title, company, city, canton, workload, apply method, dates, links) and **With description**.

### Integrations and API

Run it from your code with the Apify API or the `apify-client` package, schedule it in Apify, or connect it to Make, n8n, Zapier, Google Sheets or a webhook.

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("kamerozkan/jobs-ch-scraper").call(run_input={
    "searchTerms": ["Software Engineer"], "location": "Zürich", "onlyNewJobs": True, "maxItems": 100,
})
for job in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(job["title"], job["company"], job["city"], job["url"])
```

With a webhook on `ACTOR.RUN.SUCCEEDED` you can push every new job to Slack, a database or your ATS as soon as the run finishes.

### FAQ

**Do I need a jobs.ch account or API key?** No. The Actor reads the same public listings anyone can see on jobs.ch.

**Which languages does it handle?** All of them. The job text stays in the language the employer used (German, French, Italian or English); `urlLanguage` only sets the language of the jobs.ch link.

**Why is `company` empty for some jobs?** Some employers post anonymously or through an agency. Those rows have `companyVisible: false`.

**Can I get only new jobs every day?** Yes. Turn on **Only new jobs** and schedule the Actor. Jobs delivered by earlier runs with the same search are skipped and not charged.

**Is it legal to collect this data?** It collects publicly available job listings that companies publish to attract applicants. Contact persons are not returned as fields. You are responsible for how you use the data, including privacy laws like the Swiss FADP and GDPR, and the terms of jobs.ch.

**Something is not working?** Open an issue on the Issues tab with your run link and it will be fixed quickly.

### Support and feedback

- Found a bug or missing a field? Open an issue on the **Issues** tab of this Actor. We reply within
  48 hours and ship most fixes within a few days.
- Have an idea for a feature? Issues are the fastest way to get it built.
- If the Actor saves you time, a short review on this page helps other users find it.

# Actor input Schema

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

Job titles or keywords, as you would type them on jobs.ch, for example "Software Engineer", "Pflegefachfrau" or "comptable". Each term is searched separately and duplicates are removed. Leave empty to get all jobs in the location.

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

City, region or postal code in Switzerland, for example "Zürich", "Genève" or "3011". jobs.ch also returns jobs from nearby places. Leave empty to search all of Switzerland.

## `publishedWithinDays` (type: `integer`):

Only jobs published or refreshed in the last N days, for example 1 for a daily feed or 7 for a weekly one. Leave empty for all active jobs.

## `includeDescription` (type: `boolean`):

Fetch the full description, street address, skills and expiry date for every job. Turn off for faster runs when titles, companies and places are enough. The price per job is the same.

## `urlLanguage` (type: `string`):

Language of the jobs.ch page that the url field points to. The job text itself stays in the language the employer wrote it in.

## `onlyNewJobs` (type: `boolean`):

Return only jobs that earlier runs with the same search did not return. Use with an Apify Schedule for job alerts: you pay only for new listings.

## `historyKey` (type: `string`):

Optional name for the new-jobs-only history. Runs with the same key share one history. By default the key is derived from the search terms, location and date filter.

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

Stop after this many jobs. You are charged per job, so this also caps the cost of the run. jobs.ch returns at most 2,000 jobs per search term.

## Actor input object example

```json
{
  "searchTerms": [
    "Software Engineer"
  ],
  "location": "Zürich",
  "includeDescription": true,
  "urlLanguage": "en",
  "onlyNewJobs": false,
  "maxItems": 20
}
```

# Actor output Schema

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

One row per result 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 = {
    "searchTerms": [
        "Software Engineer"
    ],
    "location": "Zürich",
    "maxItems": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("kamerozkan/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": ["Software Engineer"],
    "location": "Zürich",
    "maxItems": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("kamerozkan/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": [
    "Software Engineer"
  ],
  "location": "Zürich",
  "maxItems": 20
}' |
apify call kamerozkan/jobs-ch-scraper --silent --output-dataset

```

## MCP server setup

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