Jobs.ch Scraper - Swiss Job Board
Pricing
from $2.20 / 1,000 jobs
Jobs.ch Scraper - Swiss Job Board
Scrape job listings from Jobs.ch: search by keyword, location, or canton, paste a pre-filtered search URL, or check specific job URLs. Full descriptions, contacts, and company data. Export JSON, CSV, Excel.
Pricing
from $2.20 / 1,000 jobs
Rating
0.0
(0)
Developer
ParseBird
Maintained by CommunityActor stats
1
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share
Jobs.ch Scraper - Swiss Job Board
Jobs.ch Scraper extracts job listings from Jobs.ch, Switzerland's largest job board: full descriptions, requirements, contacts, salary ranges, and company profile data — filtered by keyword, canton, or location.
| Paste a jobs.ch search URL, search by keyword and canton, or re-check specific job URLs for still-alive status — with strict canton filtering and full contact/company enrichment on every listing. |
Copy to your AI assistant
Copy this block into ChatGPT, Claude, Cursor, or any LLM to start using this actor.
parsebird/jobs-ch-scraper on Apify. Call: ApifyClient("TOKEN").actor("parsebird/jobs-ch-scraper").call(run_input={"searchQueries":["Software Engineer"],"locations":["Zurich"],"maxResultsPerQuery":50}), then client.dataset(run["defaultDatasetId"]).list_items().items for results. Three modes: startUrls (array of pasted jobs.ch search URLs — filters extracted automatically), directUrls (array of job detail URLs — still-alive checks, returns job_status), or searchQueries + locations/cantons (array combinations, deduplicated by job ID). Key inputs: language (de|fr|en), maxResultsPerQuery, maxResults (0=unlimited), employmentType (permanent|temporary|freelance), workloadMin/workloadMax (0-100, strictly bounds the job's own posted range), publicationDate (1|3|7|30 days), companyFilter (all|exclude-hr|only-hr), includeJobDetails (boolean, full description/contacts/company data vs a fast title-only pass), maxConcurrency (1-50). Output rows include title, company, location, canton, employment_type, workload_min/max, description_full, requirements, contact_firstname/lastname/email/phone, apply_url/apply_email, company_website/rating/review_count/benefits, posted_at, source_url. Full actor spec: GET https://api.apify.com/v2/acts/parsebird~jobs-ch-scraper (Bearer TOKEN). Get token: https://console.apify.com/account/integrations
What is Jobs.ch Scraper?
Jobs.ch Scraper is an Apify Actor for extracting structured listing data from Jobs.ch, the largest job board in Switzerland, covering German-, French-, and English-language postings across all 26 cantons. Point it at a search URL, a set of keywords and cantons, or a list of specific job URLs, and it returns clean structured rows — title, company, location, full description, contacts, and company profile data.
Use it as a Jobs.ch API alternative, a Swiss job market research tool, or a repeatable pipeline for recruiting, lead generation, or labor-market analysis. Results download as JSON, CSV, Excel, XML, or HTML, or you can fetch them programmatically through the Apify API.
What can Jobs.ch Scraper do?
- 🔗 Start URL mode — paste any jobs.ch search URL and every filter in it (keywords, locations, categories, employment type, workload) is extracted automatically
- 🔎 Search mode — combine keywords × locations × cantons; every combination runs as its own search, deduplicated by job ID
- ♻️ Direct URL mode — re-check specific job URLs and get back
online,offline, orexpiredstatus, ideal for periodic "still alive" checks - 🗺️ Strict canton filtering — each selected canton gets its own result quota, and every job is confirmed to actually be in that canton before it's returned
- 📋 Full detail enrichment — description, requirements, contact person, application links, salary text, and company profile (website, employee count, rating, reviews, benefits)
- 🏢 HR agency filter — include or exclude recruitment-agency postings to focus on direct employers
- ⏱️ Publication-date filter — pull only jobs posted in the last 1/3/7/30 days for daily scheduled monitoring
- ⚙️ Fast mode — turn off full details for a cheap, quick title/company/location-only pass
- 🔌 Run on demand, schedule recurring runs, or connect results to Apify integrations like Google Sheets, Zapier, Make, and webhooks
What data can you extract from Jobs.ch?
| Field | Description |
|---|---|
title, company, location, canton | Core listing identity, with canton resolved and verified |
employment_type, workload_min, workload_max | Contract type and Pensum (workload) percentage range |
description_full, requirements | Full job description and an extracted requirements list |
contact_firstname, contact_lastname, contact_email, contact_phone | Hiring contact, when published |
apply_url, apply_email | Where the application actually goes |
company_website, company_employee_count, company_rating, company_benefits | Company profile enrichment |
posted_at, expires_at | Publication and expiry dates |
job_status | online / offline / expired — Direct URL mode only |
Input parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
startUrls | array of strings | [] | Pre-filtered jobs.ch search URLs — filters extracted from the URL |
directUrls | array of strings | [] | Direct job URLs to check (still-alive mode) |
companyNames | array of strings | [] | Company names to search for |
searchQueries | array of strings | ["Software Engineer"] | Keywords to search |
locations | array of strings | [] (all Switzerland) | City/region names, e.g. Zurich, Basel |
cantons | array of strings | [] (all cantons) | Canton codes, e.g. ZH, BE, AG |
language | string | de | de, fr, or en |
maxResultsPerQuery | integer | 100 | Cap per keyword/location/canton combination |
maxResults | integer | 0 | Total cap across all queries. 0 = unlimited |
employmentType | string | "" (all) | permanent, temporary, or freelance |
workloadMin / workloadMax | integer | — | Workload / Pensum percentage (0-100) |
publicationDate | string | "" (any time) | 1, 3, 7, or 30 days |
searchMode | string | semantic | semantic (AI-powered) or classic (keyword matching) |
includeJobDetails | boolean | true | Fetch full descriptions, contacts, and company data |
maxConcurrency | integer | 10 | Parallel detail-page workers (1-50) |
companyFilter | string | all | all, exclude-hr, or only-hr |
proxyConfiguration | object | Datacenter | Apify proxy settings — datacenter is sufficient |
Mode 1: Start URL (easiest)
Configure your search on jobs.ch with every filter you want, copy the URL from your browser, and paste it here:
{"startUrls": ["https://www.jobs.ch/de/stellenangebote/?term=javascript&location=st.%20gallen&location=z%C3%BCrich&category=171&category=174&employment-type=5&employment-grade-min=50&employment-grade-max=100"],"maxResults": 100}
Combine multiple search URLs to scrape different filter combinations in one run:
{"startUrls": ["https://www.jobs.ch/de/stellenangebote/?term=Software+Engineer&location=z%C3%BCrich","https://www.jobs.ch/fr/offres-emplois/?term=Developpeur&location=gen%C3%A8ve"],"maxResults": 200}
Mode 2: Search (multi-query)
Search multiple keywords, locations, and cantons at once — every combination runs as its own search, and results are deduplicated:
{"searchQueries": ["Software Engineer", "Softwareentwickler", "Backend Developer"],"locations": ["Zurich", "Basel"],"maxResultsPerQuery": 100,"maxResults": 0}
With includeJobDetails: true (default), full descriptions, requirements, and contact details are fetched:
{"searchQueries": ["Data Scientist", "Machine Learning"],"cantons": ["ZH", "BE", "BS"],"maxResultsPerQuery": 100,"includeJobDetails": true}
Every selected canton gets its own quota — with maxResultsPerQuery: 20 and 3 cantons, you get up to 20 jobs per canton (60 total), each one confirmed to actually be in that canton.
Mode 3: Direct URLs (still-alive checks)
When directUrls is set, the actor skips search entirely, visits each URL directly, and returns job_status (online, offline, or expired) plus full data if the job is still available — ideal for periodic re-checks after deduplication:
{"directUrls": ["https://www.jobs.ch/de/stellenangebote/detail/b475b944-eab5-4d69-b251-a325bd272d62/","https://www.jobs.ch/fr/offres-emplois/detail/a123b456-cd78-9012-efab-345678901234/","https://www.jobs.ch/en/vacancies/detail/c789d012-ef34-5678-90ab-cdef12345678/"]}
More examples
Part-time jobs in Basel (40-60% workload):
{"searchQueries": ["Buchhaltung"],"locations": ["Basel"],"workloadMin": 40,"workloadMax": 60,"maxResultsPerQuery": 50}
French-speaking region search:
{"searchQueries": ["Infirmier", "Aide-soignant"],"cantons": ["VD"],"language": "fr","maxResultsPerQuery": 100}
Direct employer postings only (no HR agencies):
{"searchQueries": ["Marketing Manager"],"locations": ["Zurich"],"companyFilter": "exclude-hr","maxResultsPerQuery": 100}
Daily scrape — only new listings from the last 24 hours:
{"searchQueries": ["Software Engineer"],"locations": ["Zurich"],"publicationDate": "1","maxResultsPerQuery": 100}
The date filter also works in Start URL mode — just include publication-date=N in the pasted URL.
Output example
{"id": "b475b944-eab5-4d69-b251-a325bd272d62","title": "Diplomierte Pflegefachperson","company": "Clienia Schloessli AG","location": "Oetwil am See","work_address": "Schloesslistrasse 8, 8618 Oetwil am See","canton": "ZH","job_status": "online","employment_type": "full-time","workload_min": 80,"workload_max": 90,"description_snippet": "Fuer unseren Bereich in der Kinder- und Jugendpsychiatrie...","requirements": ["Erfahrung im Bereich der Kinder- und Jugendpsychiatrie", "Offene, kommunikative Persoenlichkeit"],"posted_at": "2025-12-10T15:36:17.000Z","source_url": "https://www.jobs.ch/de/stellenangebote/detail/b475b944-eab5-4d69-b251-a325bd272d62/","source_platform": "jobs.ch","contact_firstname": "Irene","contact_lastname": "Walczewski","contact_phone": "+41 44 929 83 73","company_url": "https://www.jobs.ch/de/firmen/23141-clienia-schlossli-ag/","company_website": "https://www.clienia.ch/de/","company_employee_count": "501 - 1000 employees","company_job_count": 21,"company_rating": 2.5,"company_review_count": 8,"company_benefits": ["5 Wochen Ferien", "Attraktive Arbeitszeitformen", "Foerderung von Fort- und Weiterbildungen"],"search_query": "Pflegefachperson","scraped_at": "2026-08-17T14:16:53.609Z"}
job_status is only populated in Direct URL mode — search-mode results are assumed online since they just came from live search results.
Download in JSON, HTML, CSV, or Excel from the dataset page, or fetch rows programmatically through the API.
How to scrape Jobs.ch listings
- Open Jobs.ch Scraper on Apify and click Try for free.
- Pick a mode: paste a search URL, enter keywords/locations/cantons, or paste direct job URLs.
- Set
maxResultsPerQueryandmaxResultsto control run size and cost. - Start the run and wait for the dataset to populate.
- Download results as JSON, CSV, Excel, HTML, XML, or RSS.
- Automate it with Apify scheduling, integrations, or the Apify API.
How to use the Jobs.ch API in Python
from apify_client import ApifyClientclient = ApifyClient("YOUR_APIFY_TOKEN")run = client.actor("parsebird/jobs-ch-scraper").call(run_input={"searchQueries": ["Data Scientist", "Machine Learning"],"cantons": ["ZH", "BE", "BS"],"maxResultsPerQuery": 100,})items = client.dataset(run["defaultDatasetId"]).list_items().itemsprint(items[:2])
How to use the Jobs.ch API in JavaScript
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });const run = await client.actor('parsebird/jobs-ch-scraper').call({searchQueries: ['Software Engineer'],locations: ['Zurich', 'Basel'],maxResultsPerQuery: 100,});const { items } = await client.dataset(run.defaultDatasetId).listItems();console.log(items);
Use cases
- Recruiting & sourcing — Pull direct-employer listings (excluding HR agencies) for a specific role and region
- Labor market research — Compare workload, salary, and remote-work patterns across cantons
- Lead generation — Extract company websites, industries, and hiring contacts from active job postings
- Competitive monitoring — Track which roles a specific company is hiring for, canton by canton
- Daily job alerts — Schedule a run with
publicationDate: "1"to catch only new listings each day - Link health monitoring — Use Direct URL mode to periodically re-check whether saved job links are still live
How it works
- Resolves your input into one of three modes: pasted search URLs, keyword/location/canton combinations, or direct job URLs
- Calls jobs.ch's public search API and paginates through results
- Applies canton, location, workload, publication-date, and HR-agency filters locally — since jobs.ch's own PLZ/canton and workload data is richer than what the search API filters strictly enforce
- Deduplicates by job ID across every query combination in the run
- Optionally fetches each job's detail page and parses its full description, requirements, contacts, and company profile
- Pushes normalized rows to the dataset and stops once your spending limit is reached
How much does it cost to scrape Jobs.ch?
Jobs.ch Scraper uses pay-per-event pricing, with two events depending on how much data you request per job.
| Event | What it covers | Price per 1,000 |
|---|---|---|
job-search | A search-result row (title, company, location, dates) — used when includeJobDetails is off | $2.50 / $2.40 / $2.30 / $2.20 (Free / Bronze / Silver / Gold) |
job-detail | A complete listing with full description, contacts, and company data — used when includeJobDetails is on (default) | $4.50 / $4.40 / $4.30 / $4.20 (Free / Bronze / Silver / Gold) |
Scraping 100 fully-enriched jobs costs about $0.45 on the Free plan; the same 100 jobs without details costs about $0.25. Apify's free trial credits cover typical test runs.
Is it legal to scrape Jobs.ch?
Jobs.ch Scraper extracts publicly available job listing data from the same public search endpoint jobs.ch's own website uses to render search results and job pages. Scraping publicly accessible data is generally lawful, but you're responsible for how you use the results — always review jobs.ch's Terms of Use and Apify's guide on the legality of web scraping before running large or automated workloads.
Related job board scrapers
| Actor | Best for |
|---|---|
| Arbeitsagentur Scraper | Germany's federal job board, useful alongside German-speaking Swiss searches |
| HelloWork Jobs Scraper | French job listings, useful alongside French-speaking Swiss (Romandie) searches |
| Greenhouse Jobs Scraper | Company career pages running on the Greenhouse ATS |
FAQ
How does canton filtering actually work?
Each selected canton in cantons gets its own result quota (maxResultsPerQuery per canton). The actor resolves each job's canton from jobs.ch's own location data and only returns jobs confirmed to be in a selected canton — no guessing from city names alone.
What's the difference between locations and cantons?
locations matches a job's city/place name (e.g. "Zurich" matches both "Zürich" and "Zurich"). cantons matches the canton code directly (e.g. "ZH"). Use whichever fits your search — both can be combined with keywords.
Why does workloadMax sometimes exclude a job with a wide workload range?
If a job is posted as "50-100%", it genuinely doesn't fit a workloadMax: 60 (up to 60%) request — the actor strictly bounds the job's own posted range to your requested window, rather than returning any job that merely overlaps it.
What happens if a company doesn't publish a direct contact or email?
Those fields come back null. Not every jobs.ch listing publishes a named contact, phone number, or email — the actor never fabricates one.
Can I re-check jobs I've already scraped without re-running search?
Yes — that's exactly what Direct URL mode is for. Pass the job URLs you already have in directUrls and get back job_status (online, offline, expired) for each.
Can I schedule recurring runs?
Yes. Use Apify scheduling to run daily or weekly — pair it with publicationDate: "1" for a clean "what's new today" feed.
How do I report a problem or request a field? Open an issue from the Actor page in Apify Console and include the run ID, input, and the job URL that needs review.