# Platsbanken & Arbetsförmedlingen Jobs Scraper - Sweden (`kadi_bence/sweden-jobs-scraper`) Actor

Search all ~40,000 live Swedish job ads on Platsbanken / Arbetsförmedlingen (Arbetsformedlingen) by keyword and city name, no region IDs. Input: keywords, cities, employer, remote, posted-within days. Returns per ad: title, employer, city, SEK salary, deadline, URL. Default: 20. $0.80/1K.

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

## Pricing

from $0.80 / 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.

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

## Sweden Jobs Scraper: export Platsbanken / Arbetsförmedlingen job ads

### What is Sweden Jobs Scraper?

Sweden Jobs Scraper exports job ads from **Platsbanken**, the national job board of **Arbetsförmedlingen** (the Swedish Public Employment Service), to JSON, CSV or Excel. It covers **all 40,000+ live ads in Sweden** and the **archive of every ad since 2016**.

It uses Arbetsförmedlingen's official open-data API (JobTech JobSearch and Historical ads). There is no browser, no login, no API key and no proxy, so runs are fast and cheap.

**What makes it different**

- **No 2,100-result cap.** The official API stops paging at 2,100 hits per search. This Actor walks the results by publication date, so it can export **every** live ad in Sweden in one run (tested: 9,982 of 9,982 ads in Stockholm County in about 2 minutes).
- **Historical ads since 2016**, with the same fields and filters, for trend analysis.
- **Plain-English input.** City and county names (including English spellings like Gothenburg), occupation fields and contract types. You don't need taxonomy codes.
- **Salary in SEK** parsed from the ad text ("24 900–31 000 kronor per månad" becomes 24900 / 31000 / SEK / MONTH). Benefits like *friskvårdsbidrag* are ignored.
- **Only new jobs.** Monitoring mode outputs, and charges for, only ads you haven't seen before.
- **GDPR-safe by default.** Contact persons' names, e-mails and phone numbers are removed. Personal identity numbers of sole traders are never output, and street addresses are left out.

#### Use cases

- **Recruiters and staffing agencies:** get every new ad for the roles you place, by municipality or county, every morning.
- **Sales and lead generation:** find Swedish employers that are hiring (company name, organisation number, location, logo, apply link). These are hiring signals for HR tech, training and relocation services.
- **Labour-market research and journalism:** analyse demand by occupation, region, contract type and time, using 10 years of historical ads.
- **Job boards and apps:** fill your platform with fresh Swedish jobs, refreshed daily in monitoring mode.
- **Students and juniors:** pull all "no experience required" or part-time jobs around a city.
- **AI agents and RAG apps:** give an LLM fresh, structured Swedish job data through the API or the Apify MCP server.

#### Data fields you get

| Field | Description | Example |
|---|---|---|
| `title` | Ad headline | `AI-first developer` |
| `jobId` | Platsbanken ad ID | `31550008` |
| `url` | Link to the ad on Platsbanken | `https://arbetsformedlingen.se/platsbanken/annonser/31550008` |
| `externalUrl` | Employer's own application link, if any | `https://karriar.sveavikenpm.se/jobs/...` |
| `employer` / `employerWorkplace` | Employer name and workplace name | `Sveaviken PM AB` |
| `organizationNumber` | Swedish organisation number (legal entities only) | `5593871030` |
| `employerUrl` / `logoUrl` | Employer website and logo image | `https://sveavikenpm.se/` |
| `occupation` / `occupationGroup` / `occupationField` | Occupation, group and field (Swedish labels) | `Systemutvecklare/Programmerare` / `Data/IT` |
| `city` / `municipality` / `municipalityCode` | Place of work | `Stockholm` / `Stockholm` / `0180` |
| `postalCode` | Postal code (no street address) | `12030` |
| `region` / `regionCode` | County (län) | `Stockholms län` / `01` |
| `country` | Country | `Sverige` |
| `latitude` / `longitude` | Coordinates of the workplace | `59.30098` / `18.08405` |
| `locations` | All workplaces of the ad | `["12030, Stockholm, Stockholms län"]` |
| `postedDate` / `publishedAt` | Publication date and timestamp | `2026-10-03` / `2026-10-03T13:22:15` |
| `deadline` | Application deadline | `2026-12-01` |
| `employmentType` | `permanent`, `fixed_term`, `substitute`, `on_call`, `seasonal`, `regular`, `summer_job` | `permanent` |
| `employmentTypeLabel` | Original Swedish label | `Tillsvidareanställning (inkl. eventuell provanställning)` |
| `duration` | Duration as shown in the ad | `Tills vidare` |
| `workingTime` | `full_time` or `part_time` | `full_time` |
| `scopeOfWorkMin` / `scopeOfWorkMax` | Scope of work in percent | `100` / `100` |
| `remote` | `true` for remote or hybrid ads | `true` |
| `workMode` | `remote`, `hybrid` or empty when unknown | `hybrid` |
| `salaryMin` / `salaryMax` | Parsed pay range (numbers) | `24900` / `31000` |
| `salaryCurrency` / `salaryPeriod` | Currency and `HOUR`, `MONTH` or `YEAR` | `SEK` / `MONTH` |
| `salaryText` | Pay text from the ad | `24900-31000 kronor` |
| `salaryType` | `fixed`, `commission` or `fixed_and_variable` | `fixed` |
| `openPositions` | Number of vacancies | `1` |
| `experienceRequired` | Whether work experience is required | `true` |
| `drivingLicenseRequired` / `drivingLicenses` / `accessToOwnCar` | Driving licence and car requirements | `false` / `[]` / `false` |
| `requiredSkills` / `preferredSkills` | Skills listed as required or nice to have | `[]` |
| `requiredLanguages` / `preferredLanguages` | Languages listed as required or nice to have | `["Svenska"]` |
| `labels` | Ad labels, e.g. *nystartsjobb* | `[]` |
| `applyViaArbetsformedlingen` | Whether you apply through Arbetsförmedlingen | `false` |
| `sourceType` | How the ad reached Platsbanken | `VIA_JOBPOSTING` |
| `removed` / `removedDate` | Removal status and date (historical ads) | `false` / `null` |
| `source` | `current` or `historical` | `current` |
| `description` | Job description as plain text | `Vill du bygga AI som används på riktigt?…` |
| `descriptionHtml` | Description with HTML formatting (only if you choose HTML or both) | `null` |
| `isNew` | Set in monitoring mode for ads not seen before | `true` |
| `scrapedAt` | When the ad was scraped (UTC) | `2026-10-05T00:16:28Z` |

### How to use Sweden Jobs Scraper

1. Open the Actor and enter **keywords** (Swedish or English, e.g. `utvecklare`, `data engineer`, `sjuksköterska`) and/or **locations** (`Stockholm`, `Gothenburg`, `Skåne län`). The prefill is `developer` in `Stockholm` with 20 results, which finishes in a few seconds and costs about $0.02.
2. Optional: add filters such as occupation field, employment type, full-/part-time, remote, or published within N days. Set **Max results** to `0` to get every matching ad.
3. Click **Start**.
4. When the run finishes, open the **Output** tab and download the data as JSON, CSV, Excel or HTML, or connect it to Google Sheets, Zapier, Make, n8n or your own code.
5. To get only new ads every day, turn on **Only new jobs** and create a **Schedule** (see [Integrations and scheduling](#integrations-and-scheduling)).

#### Input guide

**Keywords (`keywords`)**

One search per line: job titles, skills or employer names, in Swedish or English. Each line is a separate search in Platsbanken's API; an ad found by several lines is saved only once. Leave it empty to get all ads that match the filters.

- Good: `utvecklare`, `data engineer`, `sjuksköterska`, `lastbilschaufför`
- Bad: `developer in Stockholm` (put places in **Locations**), `IT jobs` (use **Occupation fields** instead)
- Tip: Swedish ads are mostly written in Swedish. Searching both `developer` and `utvecklare` finds more ads.

**Locations (`locations`)**

Swedish municipalities (`Stockholm`, `Göteborg`, `Malmö`) or counties (`Skåne län`, `Västra Götalands län`). English and ASCII spellings work too (`Gothenburg`, `Malmo`, `Scania`), and so do codes (`0180` for a municipality, `12` for a county). With several locations, an ad in any of them is returned.

- Good: `Stockholm` (the municipality), `Stockholms län` or `Stockholm county` (the whole county), `Uppsala`, `1480`
- Bad: `Södermalm` (a district, not a municipality), `Sweden` (leave the field empty for all of Sweden)
- Warning: a bare name means the municipality, so `Stockholm` is the city, not the county.
- Unknown names are skipped with a warning (also listed in `RUN_SUMMARY`). If none is known, the run stops with an error.

**Filters**

All filters are sent to Arbetsförmedlingen's API, so only matching ads are downloaded and charged.

- `occupationFields`: occupation fields (yrkesområden) such as `it`, `healthcare`, `education`, `construction` or `transport_logistics`.
- `employer`: employer name (e.g. `Volvo Car Corporation`) or organisation number (e.g. `556074-3089`; dashes and spaces are removed).
- `employmentTypes`: `permanent`, `fixed_term`, `substitute`, `on_call`, `seasonal`. Leave empty for any.
- `workingTime`: `any` (default), `full_time` or `part_time`.
- `remoteOnly`: only ads that Arbetsförmedlingen classifies as remote work (distans / hemifrån).
- `noExperienceRequired`: only jobs that don't require previous work experience.
- `publishedWithinDays`: only ads from the last N days, e.g. `7`.
- `coordinates` + `radiusKm`: radius search around a point, e.g. `59.33,18.07` (central Stockholm) and `15`. The radius defaults to 10 km.

**Historical data (`dataSource`, `publishedFrom`, `publishedTo`)**

- `dataSource`: `current` (default) is the live Platsbanken; `historical` is Arbetsförmedlingen's archive of every ad since 2016 (8M+ ads).
- `publishedFrom` / `publishedTo`: a date range, `YYYY-MM-DD`. Works for both sources. With `publishedWithinDays` too, the later start date wins.
- Warning: a historical search without a date range covers all ads since 2016. Always set a date range, a keyword or a location.

**Max results (`maxResults`)**

A limit for the whole run, across all keywords. `0` means no limit. The Console prefill is 20 for a quick test; the default when calling via API, MCP or an AI agent is 20. With no keywords, no filters and no limit, you get all ~40,000 live ads.

**Output options**

- `descriptionFormat`: `text` (default), `html`, `both` or `none` (smaller dataset).
- `stripContactInfo` (default on): removes the names of listed contact persons, e-mail addresses and phone numbers from descriptions. Keep it on to avoid storing personal data.

**Monitoring and proxy**

`onlyNewJobs` and `monitorName`: see [Monitoring mode](#monitoring-mode-only-new-jobs). `proxyConfiguration` is off by default and not needed.

Example input:

```json
{
  "keywords": ["developer", "utvecklare"],
  "locations": ["Stockholm", "Göteborg"],
  "occupationFields": ["it"],
  "workingTime": "full_time",
  "publishedWithinDays": 7,
  "maxResults": 1000,
  "onlyNewJobs": true
}
```

### Output

Each job ad is one item in the run's dataset. Here is one real item from a test run on 2026-10-05 (description shortened):

```json
{
  "title": "Teknisk Supportspecialist med intresse för systemutveckling!",
  "jobId": "31548465",
  "url": "https://arbetsformedlingen.se/platsbanken/annonser/31548465",
  "externalUrl": "https://www.academicwork.se/lediga-jobb/p/platsbanken/YJK1FW",
  "employer": "Academic Work Sweden AB",
  "employerWorkplace": "Academic Work Sweden AB",
  "organizationNumber": "5565595450",
  "employerUrl": null,
  "logoUrl": "https://arbetsformedlingen.se/rest/employer-logo-api/api/v1/organisation/5565595450/logotyper/logo.png",
  "occupation": "Systemutvecklare/Programmerare",
  "occupationGroup": "Mjukvaru- och systemutvecklare m.fl.",
  "occupationField": "Data/IT",
  "city": "Stockholm",
  "municipality": "Stockholm",
  "municipalityCode": "0180",
  "postalCode": "11363",
  "region": "Stockholms län",
  "regionCode": "01",
  "country": "Sverige",
  "latitude": 59.3472636884668,
  "longitude": 18.0307250985521,
  "locations": ["11363, Stockholm, Stockholms län"],
  "postedDate": "2026-10-02",
  "publishedAt": "2026-10-02T15:10:33",
  "deadline": "2027-03-31",
  "employmentType": "regular",
  "employmentTypeLabel": "Vanlig anställning",
  "duration": "6 månader eller längre",
  "workingTime": "full_time",
  "scopeOfWorkMin": 100,
  "scopeOfWorkMax": 100,
  "remote": true,
  "workMode": "hybrid",
  "salaryMin": null,
  "salaryMax": null,
  "salaryCurrency": null,
  "salaryPeriod": null,
  "salaryText": null,
  "salaryType": "fixed",
  "openPositions": 1,
  "experienceRequired": true,
  "drivingLicenseRequired": false,
  "drivingLicenses": [],
  "accessToOwnCar": false,
  "requiredSkills": [],
  "requiredLanguages": ["Svenska"],
  "preferredSkills": [],
  "preferredLanguages": [],
  "labels": [],
  "applyViaArbetsformedlingen": false,
  "sourceType": "VIA_JOBPOSTING",
  "removed": false,
  "removedDate": null,
  "source": "current",
  "description": "Har du en teknisk förståelse, erfarenhet av service och vill växa i en utvecklingsnära supportroll? …",
  "descriptionHtml": null,
  "scrapedAt": "2026-10-05T00:14:14Z"
}
```

Notes:

- `employmentType` is in English. `regular` is Arbetsförmedlingen's general type "Vanlig anställning"; the contract length is then in `duration`. The original label stays in `employmentTypeLabel`.
- `remoteOnly` uses Arbetsförmedlingen's own classification. For other ads, `workMode` is detected from the text ("på distans", "hybrid", "remote"), and `remote` is `true` for both remote and hybrid ads.
- `organizationNumber` is only output for companies and other legal entities. Sole traders use their personal identity number, so it is left out.
- Empty values are `null` (lists are `[]`), so every item has the same columns in CSV and Excel.

#### Dataset views

The **Output** tab has two views of the same data:

| View | What it shows |
|---|---|
| **Jobs** | A compact table: title, employer, city, county, published date, deadline, employment type, working time, salary range and link. Best for a quick look. |
| **Full details** | Adds occupation, occupation field, organisation number, all locations, scope of work, open positions, salary text, required skills and languages, work mode, description and the external apply link. |

Every export (JSON, CSV, Excel, API) contains all fields, whichever view you look at. The run also writes a `RUN_SUMMARY` record to the key-value store: per keyword how many ads matched and were listed, any errors or unknown locations, and the number of jobs saved.

#### How to export the data

- **In the Console:** Output tab > **Export** > JSON, CSV, Excel, HTML, XML or RSS. You can pick fields and the view.
- **Google Sheets:** add the Google Sheets integration to the Actor or a schedule (Integrations tab), or use `=IMPORTDATA("https://api.apify.com/v2/datasets/<DATASET_ID>/items?format=csv&token=<TOKEN>")`.
- **API:** `https://api.apify.com/v2/datasets/<DATASET_ID>/items?format=json` (also `csv`, `xlsx`, `xml`). Add `&view=overview` for the compact table.

### Pricing

This Actor uses **pay per event**. You pay **$0.80 per 1,000 jobs** ($0.0008 per job saved to the dataset), plus Apify's standard Actor start fee of **$0.00005 per run**. Platform compute is included in the price, and there is no separate fee for details.

| Example run | Jobs saved | Cost |
|---|---|---|
| Prefill test (developer, Stockholm, 20 jobs) | 20 | about $0.02 |
| Any search with Max results 1,000 | 1,000 | about $0.80 |
| All live ads in Stockholm County | 9,982 | about $8.00 |
| All live ads in Sweden | ~40,000 | about $32 |
| Daily monitoring, ~50 new ads per day for 30 days | 1,500 | about $1.20 per month |

What you don't pay for:

- ads that don't match your filters (they are never downloaded),
- ads already seen in monitoring mode,
- searches that fail,
- the `RUN_SUMMARY` record.

To cap spending, set **Max results** or **Max charge per run** in the run options; the Actor stops cleanly at that limit and keeps what it saved. Apify's free plan includes monthly platform credit you can use for this Actor.

### Use it via API

Get your API token in the Apify Console under **Settings > API & Integrations**. The examples below run the Actor, wait for it to finish and read the jobs.

**JavaScript / Node.js** (`npm install apify-client`)

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });

const run = await client.actor('kadi_bence/sweden-jobs-scraper').call({
    keywords: ['data engineer', 'utvecklare'],
    locations: ['Stockholm', 'Göteborg'],
    workingTime: 'full_time',
    maxResults: 500,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(`${items.length} jobs`, items[0]);
```

**Python** (`pip install apify-client`)

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")

run = client.actor("kadi_bence/sweden-jobs-scraper").call(run_input={
    "keywords": ["data engineer", "utvecklare"],
    "locations": ["Stockholm", "Göteborg"],
    "workingTime": "full_time",
    "maxResults": 500,
})

for job in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(job["title"], job["employer"], job["city"], job["salaryMin"], job["url"])
```

**cURL** (runs the Actor and returns the jobs in one request; best for runs under 5 minutes)

```bash
curl -X POST "https://api.apify.com/v2/acts/kadi_bence~sweden-jobs-scraper/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"keywords": ["developer"], "locations": ["Stockholm"], "maxResults": 20}'
```

**Apify CLI**

```bash
apify call kadi_bence/sweden-jobs-scraper --input '{"keywords": ["developer"], "locations": ["Stockholm"], "maxResults": 20}' --output-dataset
```

**MCP server for AI agents** (Claude, Cursor, VS Code and other MCP clients)

Add the Apify MCP server with this Actor as a tool. Your client will ask you to sign in to Apify (OAuth), or you can send your token as an `Authorization: Bearer YOUR_APIFY_TOKEN` header.

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com/?actors=kadi_bence/sweden-jobs-scraper"
    }
  }
}
```

Then ask your agent, for example: "Find all nursing jobs (sjuksköterska) in Skåne län published in the last 7 days and list the employers and deadlines."

### Integrations and scheduling

- **Schedules:** in the Console go to **Schedules > Create new**, pick this Actor (or a saved task with your input) and a time, e.g. every day at 07:00. Each run gets its own dataset.
- **Webhooks:** on the Actor's **Integrations** tab, add a webhook for "Run succeeded" to send the run and dataset ID to your server.
- **Zapier, Make and n8n:** use the Apify app or node. Trigger "Actor run finished", then "Get dataset items", then send each job to Slack, e-mail, a CRM or Airtable.
- **Google Sheets:** the Google Sheets integration appends each run's jobs to a sheet, which is the easiest job-alert setup.
- **Slack and e-mail:** Apify's built-in Slack and e-mail integrations can notify you when a run finishes.

#### Monitoring mode (only new jobs)

Turn on **Only new jobs** (`onlyNewJobs: true`) and schedule the Actor:

1. The first run outputs all matching ads and saves their IDs as a baseline.
2. Every later run outputs only ads that weren't listed before. In monitoring mode every item has `isNew: true`.
3. You pay only for those new ads.

The "already seen" list is stored in a named key-value store (`sweden-jobs-monitor`) in your own Apify account, one list per **Monitor name** and input. Changing any search setting (keywords, locations, filters, dates, description format) starts a new list; **Max results** and the proxy don't. If a run is cut short by **Max results** or **Max charge per run**, only the ads it saved are remembered, so the rest still count as new next time.

Two schedules with the same search need different **Monitor names**. To start over, use a new monitor name.

### Other job scrapers by the same developer

All of them use the same output fields where possible, so you can merge datasets.

- [Workday Jobs Scraper](https://apify.com/kadi_bence/workday-jobs-scraper): every job from company career sites on Workday (myworkdayjobs.com), by company name, with no 2,000-job cap.
- [Greenhouse, Lever & Ashby Jobs Scraper](https://apify.com/kadi_bence/ats-jobs-scraper): jobs from Greenhouse, Lever, Ashby, Workable, Recruitee and Personio boards, by company name.
- [Oracle, Taleo, BambooHR & Rippling Jobs Scraper](https://apify.com/kadi_bence/ats-plus-jobs-scraper): nine more applicant tracking systems, including Oracle Recruiting Cloud, Taleo, Teamtailor and Jobvite.
- [Germany Jobs Scraper - Arbeitsagentur](https://apify.com/kadi_bence/arbeitsagentur-jobs-scraper): 1M+ German job offers from the federal employment agency's Jobbörse.
- [EURES Jobs Scraper](https://apify.com/kadi_bence/eures-jobs-scraper): EU job vacancies from 31 countries via the official European Job Mobility Portal.
- [Remote Jobs Scraper](https://apify.com/kadi_bence/remote-jobs-scraper): remote jobs from RemoteOK, Himalayas, Jobicy and Arbeitnow in one de-duplicated feed.

Related company data for B2B leads: [SEC Form D Scraper](https://apify.com/kadi_bence/sec-form-d-funding) (startup funding rounds), [New Business Filings USA](https://apify.com/kadi_bence/us-new-business-filings) (newly registered companies), [Website Tech Stack Detector](https://apify.com/kadi_bence/tech-stack-detector) (technologies a company uses) and [EU Public Tenders Scraper (TED)](https://apify.com/kadi_bence/ted-tenders-scraper) (public contracts in Sweden and the rest of the EU).

### FAQ

**How does Sweden Jobs Scraper work?**
It calls Arbetsförmedlingen's official JobSearch API (live ads) or Historical ads API (archive since 2016). Each request returns 100 full ads, so no extra detail requests are needed. Searches with more than 2,100 matches are walked newest-first in publication-date windows, and duplicates are removed by ad ID.

**Is there an official Platsbanken API?**
Yes. JobTech Dev publishes [JobSearch](https://jobsearch.api.jobtechdev.se) and [Historical ads](https://historical.api.jobtechdev.se), open and without a key. This Actor adds paging past 2,100 results, English filters, SEK salary parsing, contact stripping, monitoring and exports.

**How many results can I get? Is there a limit?**
All of them. There's no 2,100 limit. Your only limit is `maxResults`, which you can set to `0`. One edge case is the historical archive: if more than 2,100 ads share the exact same publication timestamp, some are skipped and the log and `RUN_SUMMARY` tell you. Narrow the search with a location or keyword to avoid that.

**How fast is it?**
About 4,000–5,000 jobs per minute. The 20-job prefill run takes a few seconds, and all 9,982 ads in Stockholm County took about 2 minutes in a test.

**Why do I get fewer jobs than Platsbanken shows?**
Usually because of `maxResults`, a filter, or an unrecognized location (see `RUN_SUMMARY`). `Stockholm` means the municipality; use `Stockholms län` for the whole county.

**Why is salary often empty?**
Most Swedish ads don't state a figure ("lön enligt överenskommelse"). The Actor fills `salaryMin`/`salaryMax` when the ad gives a number, and `salaryText` / `salaryType` otherwise.

**Do I need a proxy or an API key?**
No. The API is open and needs no key. Leave the proxy off.

**Is it legal to scrape Platsbanken?**
Yes. The Actor uses Arbetsförmedlingen's official open-data API, which publishes the ads under **CC0 (public domain)** for anyone to reuse, commercially too. The data comes from Arbetsförmedlingen / JobTech Dev, and attribution is appreciated. The Actor collects only public job ads, checks robots.txt, and strips contact persons' names, e-mails and phone numbers by default. If you re-use descriptions that still mention people, treat them according to GDPR.

**Can I use it from Python or another app?**
Yes. Use the Apify API, the JavaScript or Python client, the CLI, or the MCP server, as shown in [Use it via API](#use-it-via-api).

**How do I get only new jobs every day?**
Turn on **Only new jobs** and create a schedule. See [Monitoring mode](#monitoring-mode-only-new-jobs).

**The run failed or a field is missing. What should I do?**
Open an issue on the **Issues** tab with the run link or your input. Fixes usually land within 24–48 hours. See the changelog below for recent changes.

### Related Actors

More low-cost Actors by the same developer, built on official APIs and public data:

- [EURES Jobs Scraper](https://apify.com/kadi_bence/eures-jobs-scraper) — EU job vacancies from 31 countries
- [Arbeitsagentur Jobs Scraper](https://apify.com/kadi_bence/arbeitsagentur-jobs-scraper) — 1M+ German job offers by keyword, city and radius
- [Greenhouse, Lever & Ashby Jobs Scraper](https://apify.com/kadi_bence/ats-jobs-scraper) — all open jobs of a company from 6 applicant systems, plus Workday
- [Workday Jobs Scraper](https://apify.com/kadi_bence/workday-jobs-scraper) — open jobs of any company by name (NVIDIA, Salesforce), plus Greenhouse/Lever fallback
- [Remote Jobs Scraper](https://apify.com/kadi_bence/remote-jobs-scraper) — remote jobs from We Work Remotely, RemoteOK, Himalayas and more
- [Oracle, Taleo, BambooHR & Rippling Jobs Scraper](https://apify.com/kadi_bence/ats-plus-jobs-scraper) — jobs from 9 more applicant tracking systems
- [TED Tenders Scraper](https://apify.com/kadi_bence/ted-tenders-scraper) — EU public tenders and contract award winners

All my Actors: [apify.com/kadi_bence](https://apify.com/kadi_bence)

### Changelog

- **1.0 (2026-10-05):** First release. Current and historical ads, no 2,100 cap, English filters, SEK salary parsing, GDPR contact stripping and monitoring mode.

# Actor input Schema

## `keywords` (type: `array`):

One search per line: job titles, skills or employer names, in Swedish or English (e.g. 'utvecklare', 'data engineer', 'sjuksköterska'). Each line is a separate search; an ad found by several lines is saved once. Most ads are in Swedish, so add Swedish terms too. Put places in 'Locations', not here. Leave empty to get all jobs matching the filters below.

## `locations` (type: `array`):

Swedish municipalities (Stockholm, Göteborg / Gothenburg, Malmö...) or counties (Skåne län, Västra Götalands län...). Codes like 0180 (municipality) or 12 (county) work too. A bare name means the municipality: 'Stockholm' is the city, 'Stockholms län' the whole county. Unknown names are ignored with a warning; if none is known, the run stops. Leave empty for all of Sweden.

## `occupationFields` (type: `array`):

Only jobs in these occupation fields (yrkesområden). Leave empty for all.

## `employer` (type: `string`):

Only jobs from this employer: name (e.g. 'Volvo Car Corporation') or organisation number (e.g. 556074-3089).

## `employmentTypes` (type: `array`):

Leave empty for any.

## `workingTime` (type: `string`):

Full-time or part-time.

## `remoteOnly` (type: `boolean`):

Only ads that mention remote work (distans / hemifrån), as classified by Arbetsförmedlingen.

## `noExperienceRequired` (type: `boolean`):

Only jobs that do not require previous work experience (good for students and juniors).

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

Only ads published in the last N days. Leave empty for any date.

## `coordinates` (type: `string`):

Optional radius search around a point, e.g. '59.33,18.07' (central Stockholm). Use together with 'Radius'.

## `radiusKm` (type: `integer`):

Radius around the coordinates above.

## `dataSource` (type: `string`):

'Current ads' = live Platsbanken ads. 'Historical ads' = Arbetsförmedlingen's archive of every ad since 2016 (8M+), for research and trend analysis. Always set a date range below (or a keyword / location) when you use the archive.

## `publishedFrom` (type: `string`):

Only ads published on or after this date, YYYY-MM-DD. Works for both sources.

## `publishedTo` (type: `string`):

Only ads published on or before this date, YYYY-MM-DD.

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

Stop after this many jobs in total, across all keywords. 0 = no limit (all ~40,000 live ads without filters). You pay per saved job, so this also caps the cost. The default without input (API, MCP and AI-agent calls) is 20.

## `descriptionFormat` (type: `string`):

Full job description as plain text, HTML, both, or none (smaller dataset).

## `stripContactInfo` (type: `boolean`):

Recommended (GDPR). Removes the names of listed contact persons, e-mail addresses and phone numbers from descriptions.

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

Remember returned jobs and output only NEW ones on the next runs with the same search (items get isNew: true). The first run outputs all matching ads as a baseline. Ideal for daily schedules. You only pay for new jobs.

## `monitorName` (type: `string`):

Separate 'already seen' lists for different schedules with the same search. Use a new name to start over.

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

Not needed: Arbetsförmedlingen's official API is open and needs no key. Leave it off.

## Actor input object example

```json
{
  "keywords": [
    "developer"
  ],
  "locations": [
    "Stockholm"
  ],
  "workingTime": "any",
  "remoteOnly": false,
  "noExperienceRequired": false,
  "radiusKm": 10,
  "dataSource": "current",
  "maxResults": 20,
  "descriptionFormat": "text",
  "stripContactInfo": true,
  "onlyNewJobs": false,
  "monitorName": "default",
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `jobs` (type: `string`):

All scraped jobs (table view).

## `jobsFull` (type: `string`):

All scraped jobs with every field.

## `summary` (type: `string`):

Per-site/company counts, what was found and any problems.

# 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": [
        "developer"
    ],
    "locations": [
        "Stockholm"
    ],
    "maxResults": 20,
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("kadi_bence/sweden-jobs-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": ["developer"],
    "locations": ["Stockholm"],
    "maxResults": 20,
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("kadi_bence/sweden-jobs-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": [
    "developer"
  ],
  "locations": [
    "Stockholm"
  ],
  "maxResults": 20,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call kadi_bence/sweden-jobs-scraper --silent --output-dataset

```

## MCP server setup

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