work.swiss Scraper: Export Swiss Jobs to CSV

Need job listings from the official Swiss Job-Room (work.swiss, also known as arbeit.swiss) in Excel or in your own analysis? The Arbeit.Swiss Scraper collects the jobs for your keywords and cantons and returns them as a table: title, employer, place, canton, workload percentage, date and a link to the listing. No code, a few minutes.

German version

Level: Beginner
Time: 5 minutes
Cost: 30 jobs with full text: about $0.09
Tools: Apify Console (no code)
Open the Actor on Apify → See the cost Copy the Claude prompt

In this tutorial

  1. What you get
  2. All fields
  3. Example: logistics in the canton of Bern
  4. Step 1: Create an Apify account
  5. Step 2: Enter keyword and canton
  6. Step 3: Run the Actor
  7. Step 4: Export the data
  8. Prompt for Claude
  9. Available filters
  10. API and schedule
  11. Cost
  12. Use cases
  13. FAQ

What you get

The Job-Room, run by SECO (the Swiss State Secretariat for Economic Affairs), has no export function for jobs. Employers and the regional employment centres (RAV) post vacancies there, including some that may not appear on private job boards. The same data is served under four addresses: work.swiss (English), arbeit.swiss (German), travail.swiss (French) and lavoro.swiss (Italian). The Actor collects it in one run and stores it as a table you can download as CSV, Excel or JSON.

The Actor reads only publicly visible listings. You do not need a Job-Room account or an API key.

Two Swiss terms appear in the data. A canton (Kanton) is one of the 26 Swiss states, given as a two-letter code such as BE for Bern or ZH for Zürich. Workload (Pensum) is the job's share of a full-time position, in percent.

All fields at a glance

This is the field list from the Actor's output schema. Without includeJobDetails, the full listing text is missing and you only get the short snippet.

FieldTypeContent
idTextUnique Job-Room ID of the job (UUID)
titleTextJob title
companyTextEmployer; for recruitment agencies, the agency name
location / city / postal_codeTextPlace of work as “place, canton”, plus place and postal code of the workplace (not the company's head office)
canton / countryTextCanton code (for example BE) and country (CH)
job_statusTextonline, offline, expired or unknown
employment_typeTextEmployment type, in the example full-time or part-time
workload_min / workload_maxNumberWorkload percentage
contract_typeTextpermanent or temporary
start_date / starts_immediately / end_dateDate / BooleanStart date, “start immediately” flag, and end date for fixed-term jobs
work_formsListSpecial working patterns such as shift, night or Sunday work
description_snippetTextShort excerpt of the description
description_full / description_mdTextFull listing text as plain text and as Markdown (with details)
posted_at / expires_atDatePublication and expiry of the listing (day precision)
source_url / source_platformTextLink to the job on job-room.ch and the platform (arbeit.swiss)
apply_url / apply_emailTextApplication link and, if given, application email
company_urlTextEmployer website or profile, if available
contact_salutation, contact_firstname, contact_lastname, contact_email, contact_phoneTextContact person, if the listing names one
salary_min / salary_max / salary_currency / salary_periodNumber / TextSalary where given. The Job-Room usually does not publish salaries
remote_option / requirementsText / ListIn the schema, but not kept as structured data by the Job-Room. Empty in the example run
search_query / scraped_atTextThe keyword that found the job, and the time of collection

Example: logistics in the canton of Bern

We ran the Actor once locally (21 Oct 2026): keyword “Logistik” (German for logistics, since most listings are in German), canton of Bern, newest first, at most 30 jobs, with full listing text. This was the input:

{
  "searchQueries": ["Logistik"],
  "cantonCodes": ["BE"],
  "sortBy": "newest",
  "maxResults": 30,
  "includeJobDetails": true
}

The run returned 30 jobs and finished after a few seconds (measured locally; times on Apify can differ). The Job-Room reported 345 matches for this search in the last 60 days. The run therefore stopped at our maxResults limit, not because there were no more jobs. Three results, shortened and without contact persons:

[
  {
    "id": "409c48a9-7faa-48d1-b61c-7cb66591158c",
    "title": "Betriebsangestellte:r",
    "company": "Jungfraubahnen Management AG",
    "location": "Eigergletscher, BE",
    "postal_code": "3823",
    "canton": "BE",
    "job_status": "online",
    "employment_type": "full-time",
    "workload_min": 100,
    "workload_max": 100,
    "contract_type": "permanent",
    "starts_immediately": false,
    "posted_at": "2026-10-21T00:00:00.000Z",
    "expires_at": "2026-11-20T00:00:00.000Z",
    "source_url": "https://www.job-room.ch/job-search/409c48a9-7faa-48d1-b61c-7cb66591158c",
    "source_platform": "arbeit.swiss",
    "search_query": "Logistik"
  },
  {
    "id": "38dcda54-688f-4336-aaf9-3f78ed9731c9",
    "title": "Teamleitung SAP Services / Business Analyst Order-to-Cash (OTC) 80-100% (m/w/d)",
    "company": "Sanitas Troesch AG",
    "location": "Bern, BE",
    "postal_code": "3018",
    "canton": "BE",
    "employment_type": "full-time",
    "workload_min": 100,
    "contract_type": "permanent",
    "posted_at": "2026-10-21T00:00:00.000Z",
    "search_query": "Logistik"
  },
  {
    "id": "7d3a3ce7-2a00-4f90-ac8d-17445bf115d9",
    "title": "Fachspezialist/-in Administration",
    "company": "Institut für Virologie und Immunologie IVI",
    "location": "Mittelhäusern, BE",
    "canton": "BE",
    "employment_type": "full-time",
    "workload_min": 100,
    "contract_type": "permanent",
    "posted_at": "2026-10-21T00:00:00.000Z",
    "search_query": "Logistik"
  }
]

How many of the 30 jobs had each field filled:

Check the matches. The keyword also searches the listing text. In the example, “Logistik” appeared somewhere in all 30 jobs, but only 5 had it in the title. The others were, for example, operations staff or an SAP team lead. Use precise keywords or the titleFilter option (see below). Job titles are mostly in German, French or Italian, so search in the language of the canton.
Day precision. posted_at holds only the date; the time is always 00:00. All jobs in the selection above were posted on 20 or 21 October.
STEP 1

Create an Apify account

  1. Open the Arbeit.Swiss Scraper page on Apify.
  2. Click Try for free and sign up with Google or email.
  3. You land in the Apify Console on the Actor's Input tab. The monthly free credit of the Free plan is enough for small runs.
STEP 2

Enter keyword and canton

In searchQueries, enter one or more keywords. Each keyword runs as its own search, and duplicate jobs are removed across all keywords. In cantonCodes, enter the canton as a code, for example ["BE"] or ["ZH", "SG"]. Empty means all of Switzerland.

Start small. For your first run, set maxResults to 10 to 30. You see quickly whether the matches fit your keyword, and you pay only a few cents.
Default: last 60 days only. Without further settings, the Job-Room returns jobs that went online in the last 60 days. Use postedWithinDays to choose a shorter period.
STEP 3

Run the Actor and check the result

Click Save and Run at the bottom. On the run page, the Log tab shows progress and the Dataset tab shows the results as a table. Several keywords and cantons in one run look like this (“Pflege” is nursing care, “Lagerist” warehouse worker, “Buchhaltung” bookkeeping):

{
  "searchQueries": ["Pflege", "Lagerist", "Buchhaltung"],
  "cantonCodes": ["ZH", "BE"],
  "maxResultsPerQuery": 50,
  "includeJobDetails": false
}
STEP 4

Export the data

  1. In the run, open the Dataset tab.
  2. Click Export.
  3. Choose the format: CSV, Excel, JSON and more. With the field selection you export only the columns you need, for example title, company, location, workload_min, posted_at and source_url.

Prompt for Claude to copy

In Claude, add the Apify MCP server as a custom connector with this URL (see Apify's MCP documentation). The URL limits Claude to this one Actor:

https://mcp.apify.com?tools=santamaria-automations/arbeit-swiss-scraper

Then paste this prompt and replace keyword and canton with your own. Claude tells you the cost first and waits for your OK before the run starts:

Use the Apify MCP server. Run the Actor santamaria-automations/arbeit-swiss-scraper with the keyword
"Logistik", canton BE, sortBy newest and at most 30 results.
Before you start the run, tell me what it will cost and wait for my OK.
When it is done, give me a table with title, employer, place, workload and date, newest first.

We tested the Actor and the inputs, not the prompts over MCP; Claude may word the cost statement differently.

Available filters

The Actor filters the search by these settings:

There is no filter for industry, salary or contract type. You do that afterwards in the table, for example with contract_type and employment_type.

Fetch by API and on a schedule

You can also call the Actor from your own scripts, n8n or Make. This call starts a run and returns the results directly (Apify endpoint run-sync-get-dataset-items):

curl -X POST "https://api.apify.com/v2/acts/santamaria-automations~arbeit-swiss-scraper/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"searchQueries": ["Logistik"], "cantonCodes": ["BE"], "sortBy": "newest", "maxResults": 50}'

You find your API token in the Apify Console under Settings → API & Integrations. For recurring exports, create a schedule in the Console under Schedules. Set postedWithinDays to 1 for daily runs and compare the results with your last export (field id) so you only process new jobs.

What it costs

The Actor charges per result (prices from the Apify Store, Free plan, as of 21 Oct 2026):

Each job is charged once, when it is saved to the result. The full listing text (includeJobDetails) costs nothing extra. Worked example: 30 jobs = $0.00005 + 30 x $0.003 = $0.09005, about $0.09. All 345 matches of the example (logistics, canton of Bern, 60 days) would cost about $1.04. You can always find the current prices on the Actor's Apify page.

What people use the data for

Track the Swiss labour market by canton

Run the newest jobs for an occupation and a canton on a schedule and count how many appear per week, or which employers advertise most. The data comes from the official SECO platform.

Source roles for candidates and relocation clients

Recruiters and relocation firms can filter by canton and workload and open the original listing through source_url. Use expires_at and job_status to drop expired listings from your list.

Find employers that are hiring

The company column shows who is hiring in your region. Note that recruitment agencies can appear there too.

Analyse workload and fixed-term jobs

With workload_min, workload_max and contract_type you can see how many jobs are part-time or temporary.

Frequently asked questions

Do I need to code to scrape work.swiss?

No. In the Apify Console you fill in a form, click Save and Run and download the table. You only need code if you want to call the Actor from your own system through the API.

Is work.swiss the same as arbeit.swiss and the SECO Job-Room?

Yes. work.swiss (English), arbeit.swiss (German), travail.swiss (French) and lavoro.swiss (Italian) are the four language versions of the Job-Room run by SECO, the Swiss State Secretariat for Economic Affairs (job-room.ch). The Actor reads the shared data, so you get the same jobs whichever language the site uses.

Does the data include salaries?

Usually not. The fields salary_min, salary_max, salary_currency and salary_period exist in the schema, but the Job-Room does not publish salaries. In the example run, none of the 30 jobs had a salary.

How many jobs do I get per search?

By default at most 100 per keyword (maxResultsPerQuery). Set both maxResultsPerQuery and maxResults to 0 to get every match; the Actor then fetches 100 jobs per page until the list ends. For scale: in the example, the Job-Room reported 345 matches for logistics in the canton of Bern.

How do I get only new jobs?

Set postedWithinDays to 1 for the last 24 hours or 7 for the last week. The filter runs on the Job-Room side. Without it, the default is 60 days. For recurring runs, also compare the id field with your previous export.

How much does the work.swiss scraper cost?

$0.003 per job plus $0.00005 per run start. The detail page is included. 30 jobs with full text cost about $0.09.

Am I allowed to use this data?

That depends on your use case, especially for personal contact details. Some listings name a contact person with email or phone. Check data protection rules (the Swiss FADP, and the GDPR if EU residents are involved) before you store or reuse such data.

Related links

Open the Actor on Apify → All tutorials