# Platsbanken Scraper: Sweden Job Ads from Arbetsförmedlingen (`nightwave-owner/sweden-job-ads-platsbanken`) Actor

Returns Swedish job ads from Platsbanken (Arbetsförmedlingen) via the open JobTech API, one clean row per ad with employer, organisation number, location, occupation and deadline, without contact persons. Filter by keyword, county, municipality, occupation field and remote work. Supports onlyNew.

- **URL**: https://apify.com/nightwave-owner/sweden-job-ads-platsbanken.md
- **Developed by:** [Viktor Wiberg](https://apify.com/nightwave-owner) (community)
- **Categories:** Jobs, Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$3.00 / 1,000 job ads

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

## Platsbanken Scraper: Sweden Job Ads from Arbetsförmedlingen

Job ads from Platsbanken, the job board of the Swedish Public Employment Service (Arbetsförmedlingen), fetched from the open JobTech JobSearch API. You get one clean row per ad with headline, employer, organisation number, municipality, county, occupation, employment type, working hours, salary type, publication date, application deadline, a link to apply and the ad text.

Use it to follow hiring in an industry or region, to build a list of companies that are recruiting, to feed a job board or newsletter, or to analyse demand for skills. Schedule a daily run with `publishedAfter` set to `24` to get the ads published in the last day.

### What is covered

Platsbanken has the ads that employers publish with Arbetsförmedlingen and, through the JobTech service, many ads that employers publish on their own career sites and that Arbetsförmedlingen collects. On a normal weekday that is around 40 000 open ads. Only ads that are open right now are included; ads are removed from the API when they are filled or expire.

One search returns at most 2 000 ads, because the JobSearch API pages with an offset that stops at 2 000. If your search matches more, the run log says so. Split the search by county, municipality or occupation field and run it once per part.

### Example from a real run

This is the input and the first rows of a run on the Apify platform on 3 October 2026 (run `ltkLLQ5SxsUe2iKJj`, 150 rows in total). Nothing is edited except that long ad texts are shortened.

Input:

```json
{
  "query": "systemutvecklare",
  "regions": [
    "Stockholms län"
  ],
  "maxResults": 150
}
```

Output (excerpt):

```json
[
  {
    "id": "31549590",
    "headline": "Supply Chain Developer",
    "employerName": "Atlas Copco Industrial Technique Aktiebolag",
    "workplace": "Atlas Copco Industrial Technique AB",
    "organizationNumber": "5560449893",
    "municipality": "Nacka",
    "region": "Stockholms län",
    "country": "Sverige",
    "occupation": "Supply chain manager/SCM manager",
    "occupationGroup": "Civilingenjörsyrken inom logistik och produktionsplanering",
    "occupationField": "Yrken med teknisk inriktning",
    "employmentType": "Tillsvidareanställning (inkl. eventuell provanställning)",
    "duration": "Tills vidare",
    "workingHoursType": "Heltid",
    "salaryType": "Fast månads- vecko- eller timlön",
    "salaryDescription": null,
    "remote": null,
    "numberOfVacancies": 1,
    "experienceRequired": true,
    "drivingLicenseRequired": false,
    "publicationDate": "2026-10-02T19:29:30",
    "lastPublicationDate": "2026-10-12T23:59:59",
    "applicationDeadline": "2026-10-12T23:59:59",
    "applicationUrl": "https://www.jobs.atlascopcogroup.com/job-invite/175119/",
    "adUrl": "https://arbetsformedlingen.se/platsbanken/annonser/31549590",
    "descriptionText": "Do you have hands-on experience in production planning and enjoy turning data into better decisions? Join our Sales and Operations Planning (S&OP) team within ...",
    "sourceType": "VIA_ANNONSERA",
    "source": "Arbetsförmedlingen JobTech (Platsbanken)",
    "license": "CC0 1.0 (Arbetsförmedlingen open data)"
  },
  {
    "id": "31549556",
    "headline": "FPGA Validation Engineer",
    "employerName": "Ericsson AB",
    "workplace": "Ericsson AB",
    "organizationNumber": "5560566258",
    "municipality": "Stockholm",
    "region": "Stockholms län",
    "country": "Sverige",
    "occupation": "Systemutvecklare/Programmerare",
    "occupationGroup": "Mjukvaru- och systemutvecklare m.fl.",
    "occupationField": "Data/IT",
    "employmentType": "Vanlig anställning",
    "duration": "Tills vidare",
    "workingHoursType": "Heltid",
    "salaryType": "Fast månads- vecko- eller timlön",
    "salaryDescription": null,
    "remote": null,
    "numberOfVacancies": 1,
    "experienceRequired": true,
    "drivingLicenseRequired": false,
    "publicationDate": "2026-10-02T18:25:03",
    "lastPublicationDate": "2026-10-16T23:59:59",
    "applicationDeadline": "2026-10-16T23:59:59",
    "applicationUrl": "https://ericsson-ab.contactrh.com/jobs/9669/44481423",
    "adUrl": "https://arbetsformedlingen.se/platsbanken/annonser/31549556",
    "descriptionText": "Company description: Ericsson AB Job description:   Join our Team   About this opportunity:  Join Ericsson in Stockholm to work on innovative 5G and 6G mobile ...",
    "sourceType": "VIA_JOBPOSTING",
    "source": "Arbetsförmedlingen JobTech (Platsbanken)",
    "license": "CC0 1.0 (Arbetsförmedlingen open data)"
  }
]
```

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `query` | string | none | Free text search in headline, ad text and employer name. Put a phrase in double quotes and put `-` before a word to exclude it, for example `unix -linux`. |
| `regions` | array | all | Counties (län), for example `Stockholms län`. Short names (`Stockholm`, `Skåne`) and two digit county codes (`01`, `12`) also work. |
| `municipalities` | array | all | Municipality names or four digit municipality codes, for example `Göteborg` or `1480`. All 290 Swedish municipalities are accepted. |
| `occupationFields` | array | all | Occupation fields (yrkesområden), for example `Data/IT`, `Hälso- och sjukvård`, `Bygg och anläggning`. JobTech concept ids work too. |
| `employmentTypes` | array | all | `permanent`, `temporary`, `substitute`, `onDemand`, `seasonal`. |
| `remote` | boolean | not set | `true` for ads that mention remote work, `false` for ads that do not. Leave it out for all ads. |
| `publishedAfter` | string | none | A date (`2026-10-01`), a Swedish local datetime (`2026-10-01T08:00`) or a number of hours back (`24`). |
| `maxResults` | integer | `50` | Maximum number of ads, newest first. 1 to 2 000. |
| `onlyNew` | boolean | `false` | Return only ads that earlier runs with the same input did not deliver. See "Monitoring and scheduling". |

A run with empty input returns the 50 newest ads in Platsbanken.

Example input: permanent developer jobs in Stockholm and Uppsala counties published in the last three days.

```json
{
  "query": "systemutvecklare",
  "regions": ["Stockholms län", "Uppsala län"],
  "occupationFields": ["Data/IT"],
  "employmentTypes": ["permanent"],
  "publishedAfter": "72",
  "maxResults": 500
}
```

Most ads are written in Swedish, so Swedish search words find the most ads. The search also matches occupation names from the JobTech taxonomy, so a search for an occupation finds ads that Arbetsförmedlingen has classified under it.

### Output

| Field | Description |
|---|---|
| `id` | Platsbanken ad id |
| `headline` | Headline of the ad |
| `employerName` | Name of the employer. `null` when the employer is a private person (see below) |
| `workplace` | Name of the workplace as written in the ad. `null` for private persons |
| `organizationNumber` | Swedish organisation number of the employer, 10 digits. Only for legal entities, otherwise `null` |
| `municipality`, `region`, `country` | Where the job is |
| `occupation`, `occupationGroup`, `occupationField` | Occupation, occupation group (SSYK) and occupation field from the JobTech taxonomy |
| `employmentType` | For example `Vanlig anställning`, `Tidsbegränsad anställning`, `Vikariat` or `Behovsanställning` |
| `duration` | For example `Tills vidare` or `6 månader eller längre` |
| `workingHoursType` | `Heltid` or `Deltid` |
| `salaryType` | For example `Fast månads- vecko- eller timlön` |
| `salaryDescription` | Free text about the salary when the employer wrote one |
| `remote` | `true` or `false` when you filtered on remote work or the ad states its workplace model, otherwise `null` |
| `numberOfVacancies` | Number of positions |
| `experienceRequired` | Whether earlier experience is required |
| `drivingLicenseRequired` | Whether a driving licence is required |
| `publicationDate` | When the ad was published, Swedish local time |
| `lastPublicationDate` | When the ad is taken down |
| `applicationDeadline` | Last day to apply |
| `applicationUrl` | Link to apply: the employer's application page, or the Platsbanken ad when there is none |
| `adUrl` | The ad on arbetsformedlingen.se |
| `descriptionText` | The ad text as plain text, without contact persons, e-mail addresses and phone numbers |
| `sourceType` | How the ad reached Platsbanken, for example `VIA_ANNONSERA` (written in Platsbanken) or `VIA_JOBPOSTING` (collected from a career site) |
| `source`, `license` | Attribution for the data |

```json
{
  "id": "31545714",
  "headline": "Systemutvecklare",
  "employerName": "Combitech Aktiebolag",
  "workplace": "Combitech",
  "organizationNumber": "5562186790",
  "municipality": "Växjö",
  "region": "Kronobergs län",
  "country": "Sverige",
  "occupation": "Systemutvecklare/Programmerare",
  "occupationGroup": "Mjukvaru- och systemutvecklare m.fl.",
  "occupationField": "Data/IT",
  "employmentType": "Vanlig anställning",
  "duration": "Tills vidare",
  "workingHoursType": "Heltid",
  "salaryType": "Fast månads- vecko- eller timlön",
  "salaryDescription": null,
  "remote": null,
  "numberOfVacancies": 1,
  "experienceRequired": true,
  "drivingLicenseRequired": false,
  "publicationDate": "2026-10-02T10:14:08",
  "lastPublicationDate": "2026-10-23T23:59:59",
  "applicationDeadline": "2026-10-23T23:59:59",
  "applicationUrl": "https://www.aplitrak.com/?adid=ZS5hbmRlcnNzb24uMjcyOTQuMTM3NjVAc2FhYi5hcGxpdHJhay5jb20",
  "adUrl": "https://arbetsformedlingen.se/platsbanken/annonser/31545714",
  "descriptionText": "Vill du utveckla komplexa system som bidrar till Sveriges krisberedskap? ...\n[contact details removed]",
  "sourceType": "VIA_JOBPOSTING",
  "source": "Arbetsförmedlingen JobTech (Platsbanken)",
  "license": "CC0 1.0 (Arbetsförmedlingen open data)"
}
```

### Monitoring and scheduling

Set `onlyNew` to `true` to use the actor for recurring monitoring. The actor then remembers which ads it has delivered for the same input, in a named key-value store in your Apify account (`nightwave-state-sweden-job-ads-platsbanken`, one record per input). Each run returns and charges only ads that earlier runs did not deliver. The first run returns everything in the selection. A run without news finishes successfully with 0 rows.

An ad is identified by its Platsbanken ad id. Combine `onlyNew` with `publishedAfter` (for example `48` hours) so each run only looks at recent ads, and set `maxResults` above the number of ads your search gets in that window.

`onlyNew` and `maxResults` are not part of the remembered input, so you can change them without starting over. Changing any other field starts a fresh state. To start over with the same input, delete the record in the key-value store.

Example: a daily run at 06:00 Swedish time that returns new developer ads in Stockholm county. In Apify Console, open **Schedules**, create a schedule with the cron expression `0 6 * * *` and add this actor with the input below.

```json
{
  "query": "systemutvecklare",
  "regions": ["Stockholms län"],
  "publishedAfter": "48",
  "onlyNew": true,
  "maxResults": 500
}
```

The same schedule through the Apify API:

```sh
curl -X POST "https://api.apify.com/v2/schedules?token=<YOUR_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"name": "daily-sweden-job-ads-platsbanken", "cronExpression": "0 6 * * *", "timezone": "Europe/Stockholm", "isEnabled": true, "isExclusive": true,
       "actions": [{"type": "RUN_ACTOR", "actorId": "nightwave-owner~sweden-job-ads-platsbanken",
                    "runInput": {"contentType": "application/json; charset=utf-8", "body": "<the input above as a JSON string>"}}]}'
```

Connect a webhook or an integration (Slack, e-mail, Google Sheets) to the actor in Apify Console if you want the new rows sent somewhere when the run finishes.

### Good to know

- **Personal data is left out.** The actor never outputs the contact persons, application e-mail addresses or employer phone numbers that ads can contain. In the ad text, lines that introduce a contact person or a union representative are replaced with `[contact details removed]`, and so are short lines with an e-mail address or phone number. In longer paragraphs only the address or number is replaced with `[removed]`. This is done with rules, not by hand, so a name written into ordinary running text can in rare cases remain. Open `adUrl` for the employer's own contact details.
- **Private persons and sole traders.** Some employers are private persons, for example someone hiring a personal assistant, or sole traders whose organisation number is a personal identity number. For those ads `employerName`, `workplace` and `organizationNumber` are `null`, and the rest of the ad is kept.
- The `remote` filter is Arbetsförmedlingen's own phrase matching on the ad text, so it is approximate.
- Requests are retried three times on network errors, rate limits and server errors. A rejected search or a response in an unexpected format stops the run with a clear message instead of storing broken rows. A search without matches finishes successfully with 0 rows.
- To collect every ad in Platsbanken, Arbetsförmedlingen recommends its JobStream API rather than repeated searches. This actor is built for filtered searches.

### Use cases

- Find companies that are hiring in your target region or industry, with `employerName` and `organizationNumber`, as sales or recruitment leads.
- Run a niche job board or newsletter: a daily run with `onlyNew: true` gives you only the ads published since the last run.
- Measure demand for a skill or occupation per county by counting ads over time.
- Track hiring at a list of competitors or customers by searching for their names.
- Collect application deadlines and links for a career service or a school.

### FAQ

**How often is the data updated?**
Every run reads the JobTech API live. Ads appear there shortly after they are published in Platsbanken and disappear when they expire.

**What does 1 000 rows cost?**
3 USD (0.003 USD per ad, event `job-ad`). Platform usage is included.

**Can I schedule it?**
Yes. Set `onlyNew: true` and add the actor to an Apify schedule. See "Monitoring and scheduling" above.

**Can I use the data commercially?**
Yes. Arbetsförmedlingen publishes the ads as open data under CC0 1.0. The actor removes contact persons, e-mail addresses and phone numbers from the output.

### Data source and license

The data comes from the public [JobSearch API](https://jobsearch.api.jobtechdev.se) (`GET https://jobsearch.api.jobtechdev.se/search`) run by JobTech at Arbetsförmedlingen, the Swedish Public Employment Service. The API needs no API key. Its own description states that the ads are licensed under [CC0 1.0](https://creativecommons.org/publicdomain/zero/1.0/), and Arbetsförmedlingen publishes them as open data that anyone may use and share for any purpose ([data.arbetsformedlingen.se](https://data.arbetsformedlingen.se/)). CC0 does not require attribution, but every row carries `source` and `license` so you can show where the data comes from. Names of counties, municipalities, occupations and employment types come from the JobTech Taxonomy. The actor shortens and cleans the ads as described above but does not change their content otherwise.

The texts are written by the employers, who are responsible for them. This actor is not affiliated with Arbetsförmedlingen or JobTech.

### Pricing

Pay per result: 0.003 USD per row returned (event `job-ad`), which is 3 USD per 1 000 job ads. Platform usage is included, so you pay only per result. `maxResults` caps how many rows a run returns, so you always know the highest possible cost.

Rows are delivered only after they have been charged. If you set a maximum cost per run (maxTotalChargeUsd), the run stops there and its status message says how many rows were delivered.

### Contact

Built and maintained by Nightwave AB. Questions, bugs and feature requests: kontakt@nightwave.se

### På svenska

Actorn hämtar platsannonser från Platsbanken, Arbetsförmedlingens annonsdatabas, via det öppna JobSearch-API:t från JobTech. Varje annons blir en rad med rubrik, arbetsgivare, organisationsnummer, kommun, län, yrke, anställningsform, arbetstid, lönetyp, publiceringsdatum, sista ansökningsdag, ansökningslänk och annonstext.

- Filtrera på sökord, län, kommun, yrkesområde, anställningsform, distansarbete och publiceringsdatum. Länsnamn, kommunnamn och koder fungerar båda.
- En sökning ger högst 2 000 annonser, eftersom API:t bläddrar med en offset som slutar vid 2 000. Matchar fler, dela upp sökningen på län, kommun eller yrkesområde.
- Kontaktpersoner, e-postadresser och telefonnummer tas inte med. I annonstexten ersätts rader med kontaktpersoner och fackliga företrädare med `[contact details removed]`. Rensningen görs med regler, så ett namn i löpande text kan i sällsynta fall bli kvar.
- När arbetsgivaren är en privatperson eller en enskild firma med personnummer sätts arbetsgivarens namn, arbetsplats och organisationsnummer till `null`.
- Källa: Arbetsförmedlingen, JobTech JobSearch. Annonserna är öppna data under CC0 1.0 och får användas fritt. Ingen API-nyckel behövs.
- Med `onlyNew: true` levereras bara annonser som tidigare körningar med samma input inte har levererat, vilket passar för daglig bevakning (se "Monitoring and scheduling"). Tom input ger de 50 senaste annonserna.
- Pris: 0,003 USD per annons (3 USD per 1 000). Plattformsanvändningen ingår.
- Kontakt: kontakt@nightwave.se

# Actor input Schema

## `query` (type: `string`):

Optional. Free text search in headline, ad text and employer name, for example "systemutvecklare", "python" or "sjuksköterska". Swedish words find the most ads. Put a phrase in double quotes, and put - before a word to exclude it, for example "unix -linux".

## `regions` (type: `array`):

Optional. Only ads in these counties, for example \["Stockholms län"]. In the API you can also pass the county name in other spellings ("Stockholm") or the two digit county code ("01").

## `municipalities` (type: `array`):

Optional. Municipality names or four digit municipality codes, for example \["Göteborg"] or \["1480"]. All 290 Swedish municipalities are accepted.

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

Optional. Only ads in these occupation fields (yrkesområden), for example \["Data/IT"].

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

Optional. Only ads with these employment types, for example \["permanent"].

## `remote` (type: `boolean`):

Optional. true: only ads that mention remote work, for example true. Leave empty for all ads. Platsbanken detects remote work from phrases in the ad, so the filter is approximate.

## `publishedAfter` (type: `string`):

Optional. A date (2026-10-01), a Swedish local datetime (2026-10-01T08:00) or a number of hours back ("24" for the last day). Useful for daily scheduled runs.

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

Maximum number of ads to return, newest first, for example 50. One search can return at most 2 000 ads; split larger searches by county or occupation field. Each ad is one billable result. Defaults to 50.

## `onlyNew` (type: `boolean`):

For scheduled runs. When true, ads that an earlier run with the same input already delivered are skipped and not charged, so a daily run returns only ads published since the last run (among the newest maxResults). The first run returns everything. Defaults to false.

## Actor input object example

```json
{
  "query": "systemutvecklare",
  "regions": [
    "Stockholms län",
    "Skåne län"
  ],
  "municipalities": [
    "Göteborg"
  ],
  "occupationFields": [
    "Data/IT"
  ],
  "employmentTypes": [
    "permanent"
  ],
  "remote": true,
  "publishedAfter": "24",
  "maxResults": 50,
  "onlyNew": true
}
```

# Actor output Schema

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

All rows produced by the run, as JSON. Open in Apify Console or download via the dataset API.

# 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 = {
    "query": "systemutvecklare",
    "maxResults": 50,
    "onlyNew": false
};

// Run the Actor and wait for it to finish
const run = await client.actor("nightwave-owner/sweden-job-ads-platsbanken").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 = {
    "query": "systemutvecklare",
    "maxResults": 50,
    "onlyNew": False,
}

# Run the Actor and wait for it to finish
run = client.actor("nightwave-owner/sweden-job-ads-platsbanken").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 '{
  "query": "systemutvecklare",
  "maxResults": 50,
  "onlyNew": false
}' |
apify call nightwave-owner/sweden-job-ads-platsbanken --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,nightwave-owner/sweden-job-ads-platsbanken"
        }
    }
}
```

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/bRzR6KDLZmZgkXhHs/builds/uGfI5CJgn2QPWgUeW/openapi.json
