Job-Room.ch Jobs Scraper avatar

Job-Room.ch Jobs Scraper

Pricing

from $0.79 / 1,000 job scrapeds

Go to Apify Store
Job-Room.ch Jobs Scraper

Job-Room.ch Jobs Scraper

Scrape job listings from Job-Room.ch (arbeit.swiss), Switzerland's official public employment service. Search by keyword and canton, or check specific job URLs. Export JSON, CSV, Excel.

Pricing

from $0.79 / 1,000 job scrapeds

Rating

0.0

(0)

Developer

ParseBird

ParseBird

Maintained by Community

Actor stats

1

Bookmarked

2

Total users

1

Monthly active users

a day ago

Last modified

Categories

Share

Job-Room.ch Jobs Scraper

Extract job listings from Job-Room.ch (arbeit.swiss) — Switzerland's official public employment service portal, run by SECO. Job-Room.ch Jobs Scraper returns clean, structured JSON for every listing: title, company, location, canton, workload percentage, full description, contact details, and how to apply.

Search by keyword and Swiss canton, filter by workload percentage and posting recency, or check a specific job URL directly — every listing is enriched from its own detail page for the full description and contact/apply details, with an optional statistics mode for cheap labour-market snapshots and workflow resume state.

Copy to your AI assistant

Copy this block into ChatGPT, Claude, Cursor, or any LLM to start using this actor.

Job-Room.ch Jobs Scraper (parsebird/job-room-ch-jobs-scraper) scrapes job listings from job-room.ch (arbeit.swiss), the Swiss public employment service. Inputs: searchQueries (array of strings — one search per keyword, deduplicated), directUrls (array of job-room.ch job URLs or plain IDs — skips search mode), cantonCodes (array of Swiss canton codes like ["ZH","BE","SG"], default all cantons), sortBy (date_desc / date_asc / "" default), workloadMin/workloadMax (integers, default 10/100 — Pensum percentage), onlineSinceDays (integer, default 60), maxResultsPerQuery (integer, default 100, 0 = all), maxResults (integer, default 0 = unlimited total cap across all queries), statsMode (off default / include / only — see below), proxyConfiguration (Swiss residential, set by default). Output per job: id, title, company, location, canton, job_status (direct-URL mode only), employment_type, workload_min, workload_max, description_snippet, description_full, posted_at, expires_at, source_url, source_platform, contact_salutation/firstname/lastname/email/phone, apply_url, apply_email, company_url, search_query, scraped_at. statsMode adds type:"stats" (per query: totalAvailable from X-Total-Count, pagesFetched, resultsEmitted, stopReason, resume) and type:"run_summary" items; a STATS record is always written to the run's key-value store. Pricing: pay-per-event, $0.00099 per job on Free down to $0.00079 on Gold; stats items are never charged. API: https://apify.com/parsebird/job-room-ch-jobs-scraper/api - Token: https://console.apify.com/account/integrations

What is Job-Room.ch Jobs Scraper?

Job-Room.ch Jobs Scraper is an Apify Actor that extracts job listings from Job-Room.ch (branded arbeit.swiss), the official job board of Switzerland's public employment service (SECO / RAV). Give it a keyword — "Pflege", "Informatik", "Buchhaltung" — and it returns every matching listing as structured JSON, with title, company, canton, workload, full description, and contact/apply details.

It works as a practical arbeit.swiss API alternative, since job-room.ch does not expose a public search API of its own (its documented API is an employer-only publishing channel that requires registered credentials). This Actor calls the same JSON endpoint the job-room.ch website itself uses to render search results.

What can Job-Room.ch Jobs Scraper do?

  • 🔍 Keyword search — run multiple search queries in one job, deduplicated automatically.
  • 🇨🇭 Canton filtering — restrict results to one or more of Switzerland's 26 cantons (full code table below).
  • 🎚️ Workload & recency filters — minimum/maximum workload percentage (Pensum) and how many days back to look.
  • 🔗 Direct URL / ID mode — paste specific job URLs or IDs to check whether they're still live, skipping search entirely.
  • 📄 Full listing detail — every result is enriched from its own detail page for the complete description, contact person, and apply channel — not just the short search-result snippet.
  • 🔀 Sorting — newest first, oldest first, or the platform's default relevance order.
  • 📊 Statistics mode — get per-query totals and a run summary instead of (or alongside) job data, for cheap market snapshots and workflow resume state.
  • ⚡ Runs on Apify with scheduling, API access, integrations, and export to JSON, CSV, Excel, HTML, or XML.

What data can you extract from Job-Room.ch?

FieldDescription
id / source_urlJob-Room.ch listing ID and canonical URL
title / companyJob title and hiring company
location / cantonCity and canton code
employment_typefull-time or part-time, derived from workload
workload_min / workload_maxWorkload percentage range (Pensum)
description_snippet / description_fullShort preview and complete job description
posted_at / expires_atPublication start and end dates
job_statusListing status (PUBLISHED_PUBLIC, etc.) — direct URL mode only
contact_salutation / contact_firstname / contact_lastname / contact_email / contact_phoneNamed contact, when published
apply_url / apply_emailHow to apply
company_urlEmployer's website, when published

Not every field is always available: salary is not exposed by the arbeit.swiss data at all (always null), and detailed requirements aren't reliably separable from the description (always an empty array).

How to scrape Job-Room.ch

  1. Open Job-Room.ch Jobs Scraper on Apify Store and click Try for free.
  2. Enter one or more Search queries.
  3. (Optional) Restrict to specific Canton codes, set a workload range, or a posting-recency window.
  4. (Optional) Use Direct job URLs instead, to check specific listings.
  5. Click Start, then open the Dataset tab. Export as JSON, CSV, Excel, HTML, or XML.
{
"searchQueries": ["Pflege", "IT", "Buchhaltung"],
"cantonCodes": ["ZH", "BE"],
"maxResultsPerQuery": 50,
"sortBy": "date_desc"
}
{
"searchQueries": ["Software Engineer"],
"cantonCodes": ["ZH"],
"maxResultsPerQuery": 200
}

Input example — direct URLs (still-alive checks)

{
"directUrls": [
"https://www.job-room.ch/job-search/abc123-def456",
"https://www.job-room.ch/job-search/xyz789-uvw012"
]
}

Output example

{
"id": "abc123-def456",
"title": "Dipl. Pflegefachperson HF/FH",
"company": "Universitätsspital Zürich",
"location": "Zürich, ZH",
"canton": "ZH",
"job_status": null,
"employment_type": "full-time",
"workload_min": 80,
"workload_max": 100,
"description_snippet": "Wir suchen eine engagierte Pflegefachperson...",
"description_full": "Wir suchen eine engagierte Pflegefachperson für unsere Abteilung...",
"requirements": [],
"posted_at": "2026-08-15T00:00:00.000Z",
"expires_at": "2026-09-14T00:00:00.000Z",
"source_url": "https://www.job-room.ch/job-search/abc123-def456",
"source_platform": "arbeit.swiss",
"contact_salutation": "Frau",
"contact_firstname": "Maria",
"contact_lastname": "Müller",
"contact_email": "jobs@usz.ch",
"contact_phone": "+41442551111",
"apply_url": "https://careers.usz.ch/apply/123",
"apply_email": "bewerbung@usz.ch",
"company_url": "https://www.usz.ch",
"search_query": "Pflege",
"scraped_at": "2026-09-05T12:00:00.000Z"
}

Download the dataset in JSON, CSV, Excel, HTML, or XML from the Dataset tab.

Statistics mode

Set statsMode to get per-query statistics alongside or instead of job data — useful for workflow control (resume state, "was it worth a full scrape?") and cheap labour-market snapshots.

ModeDataset outputCost
off (default)Jobs only, no stats items — unchanged behaviourStandard per-result pricing
includeJobs and one type: "stats" item per query and one type: "run_summary" itemStandard per-result pricing — stats items are free
onlyStats and run_summary only — no job data, no detail-page fetchesOne page fetch per query, no per-result charges

Each stats item carries the platform-reported total (from arbeit.swiss's X-Total-Count header — the same number the job-room.ch UI shows), how many pages were fetched, how many results were emitted, why the query stopped (stopReason), and — if it stopped early — the page/offset to resume from. A STATS record ({queries: [...], summary: {...}}) is always written to the run's key-value store, regardless of statsMode, so a calling workflow can read resume state without parsing the dataset.

Swiss canton codes

CodeCantonCodeCanton
AGAargauNWNidwalden
AIAppenzell InnerrhodenOWObwalden
ARAppenzell AusserrhodenSGSt. Gallen
BEBernSHSchaffhausen
BLBasel-LandschaftSOSolothurn
BSBasel-StadtSZSchwyz
FRFribourgTGThurgau
GEGenèveTITicino
GLGlarusURUri
GRGraubündenVDVaud
JUJuraVSValais
LULuzernZGZug
NENeuchâtelZHZürich

Pass these in cantonCodes, e.g. ["ZH", "BE", "SG"]. Leave empty to search all cantons.

Use cases

  • 🧲 Recruitment sourcing — pull Swiss job openings by keyword and canton for a talent pipeline.
  • 📊 Labour-market research — use statsMode: "only" to track how many openings exist for a keyword or region over time, without paying for job data.
  • 🏢 Employer monitoring — track a company's open roles on the official Swiss public job board.
  • 🔁 Still-alive checks — feed listing URLs from your own database into directUrls on a schedule to detect closed or removed postings.
  • 🤖 AI & data pipelines — feed structured job data into LLM agents through the Apify MCP server.

Turn one scrape into a recurring job monitor

Save an input and run it on an Apify Schedule:

  • Daily/weekly keyword tracking: sortBy: "date_desc", a modest maxResultsPerQuery, and onlineSinceDays matching your schedule interval so each run only reflects genuinely new postings.
  • Labour-market snapshots: statsMode: "only" on a batch of keywords — one cheap page fetch per keyword, no per-result charges.
  • Still-alive checks: batch known listing IDs into directUrls to detect closures.

If you also need fresh listing detail refreshes at scale for your own tracked jobs, run this Actor's directUrls mode on a schedule against your saved job IDs.

How it works

  1. The Actor builds a search request per query, with your canton, workload, and recency filters.
  2. It calls job-room.ch's own search endpoint (the same one the website uses) and paginates through results up to maxResultsPerQuery / maxResults.
  3. Each result from search carries a short, highlighted excerpt; the Actor fetches that listing's own detail page to get the complete description and contact/apply information.
  4. In directUrls mode, each URL/ID is resolved straight to its detail page — no search step.
  5. Each job is billed as one pay-per-event result; stats/run_summary items are never charged.

How much does it cost to scrape Job-Room.ch?

Job-Room.ch Jobs Scraper uses pay-per-event pricing. You are charged once per job listing.

PlanPrice per jobPrice per 1,000 jobs
Free$0.00099$0.99
Bronze$0.00089$0.89
Silver$0.00089$0.89
Gold$0.00079$0.79

Scraping 1,000 jobs costs about $0.99 on the Free plan. statsMode: "only" runs cost nothing per result — only Apify platform usage (a handful of small requests). Apify platform usage (compute and proxy) is billed separately. See the Apify pricing page.

API usage examples

Run Job-Room.ch Jobs Scraper with the Apify API.

Python

from apify_client import ApifyClient
client = ApifyClient("<YOUR_API_TOKEN>")
run_input = {
"searchQueries": ["Pflege"],
"cantonCodes": ["ZH", "BE"],
"maxResultsPerQuery": 50,
"sortBy": "date_desc",
}
run = client.actor("parsebird/job-room-ch-jobs-scraper").call(run_input=run_input)
for job in client.dataset(run["defaultDatasetId"]).iterate_items():
print(job["title"], "-", job["company"], "-", job["canton"])

JavaScript

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: '<YOUR_API_TOKEN>' });
const run = await client.actor('parsebird/job-room-ch-jobs-scraper').call({
searchQueries: ['Software Engineer'],
cantonCodes: ['ZH'],
maxResultsPerQuery: 100,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.map((j) => `${j.title} @ ${j.company}`));

Connect finished datasets to Google Sheets, Slack, Zapier, Make, webhooks, or your own pipeline.

Job-Room.ch Jobs Scraper reads only publicly visible data — the same job listings any visitor sees on job-room.ch, a public Swiss government employment service. It does not log in or access private account data. You should still review job-room.ch's Terms of Use and make sure your use case complies with applicable laws. For background, read Apify's guide: Is web scraping legal?.

FAQ

Do I need a job-room.ch or arbeit.swiss account? No. The Actor uses job-room.ch's own public search data — no login or API key.

Why does the input mention residential proxies? job-room.ch's search backend is a Swiss government service that can restrict traffic from cloud/datacenter IP ranges. A Swiss residential proxy is set by default and recommended for reliable, sustained use — see the proxy configuration in Advanced.

Why is salary always null? arbeit.swiss's job data doesn't include salary information at all — it isn't hidden by the Actor, it simply isn't published on the platform.

What's in requirements? It's always an empty array. Requirements text isn't published as a separate structured field by arbeit.swiss — it's part of the free-text description_full.

How do I get only new postings on a repeated run? Set onlineSinceDays to match how often you run the Actor (e.g. 7 for a weekly schedule) and sortBy: "date_desc", or use statsMode to check the total count cheaply before deciding whether to run a full scrape.

Can I check whether specific jobs are still active? Yes — put their URLs or IDs in directUrls. Removed or invalid listings are skipped with a warning in the log rather than causing an error.

Can I schedule recurring runs? Yes. Use Apify schedules — see "Turn one scrape into a recurring job monitor" above.

Can I use this as an arbeit.swiss API? Yes. Call the Actor through the Apify API, use webhooks, or connect it to AI assistants with the Apify MCP server.

Something looks wrong or missing. Report it on the Issues tab and it will be looked at quickly.