# Swedish Job Ads – Platsbanken (Arbetsförmedlingen) (`inkhaan/swedish-jobs-jobtech`) Actor

Get Swedish job ads from Arbetsförmedlingen's open JobTech API (CC0). Filter by keyword, location and occupation, or fetch only ads that are new or changed since your last run. Contact persons are removed.

- **URL**: https://apify.com/inkhaan/swedish-jobs-jobtech.md
- **Developed by:** [Mattias Olsson](https://apify.com/inkhaan) (community)
- **Categories:** Jobs
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

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

## Swedish Job Ads – Arbetsförmedlingen (Platsbanken) with daily delta

Get job ads from **Platsbanken**, the Swedish Public Employment Service's job board, as clean JSON. The data comes from Arbetsförmedlingen's open **JobTech** APIs. It covers all current Platsbanken ads, which was about 44,000 ads in October 2026.

**Why this Actor**

- **Daily delta.** Turn on *Only new or changed since last run* and schedule the Actor daily. Each run returns only the ads that were published or changed since the previous run, so you never pay twice for the same unchanged ad.
- **Contact persons removed.** Contact persons are never output. Their names, emails and phone numbers are also removed from the ad text by rules (see Limitations).
- **Skills included.** Skills are extracted from the ad text with JobTech's JobAd Enrichments model.
- **Official open data.** No scraping, no proxies and no login. The source is the public JobTech API (CC0).

### Input

| Field | Type | Description |
|---|---|---|
| `keywords` | string | Free-text search, e.g. `java utvecklare`. |
| `location` | string | Municipality, city or county, e.g. `Göteborg` or `Skåne`. |
| `occupation` | string | Occupation, occupation group or field in Swedish, e.g. `sjuksköterska`. |
| `maxItems` | integer | The maximum number of ads per run (default 100). |
| `onlyNewSinceLastRun` | boolean | Daily delta mode. The first run covers the last 24 hours, or starts at `changedSince` if you set it. |
| `changedSince` | date | Only ads published or changed after this date or time, e.g. `2026-10-26`. At most 31 days back. |
| `enrichSkills` | boolean | Adds `enrichedSkills` (default `true`). |

Example: `{ "keywords": "sjuksköterska", "location": "Malmö", "maxItems": 20 }`

The delta state is stored per filter combination. Several scheduled tasks with different filters therefore do not affect each other. If a run stops at `maxItems`, the next run continues where it stopped, without duplicates.

### Output

One item per ad. This example is a real ad, with the description shortened:

```json
{
  "id": "31650623",
  "url": "https://arbetsformedlingen.se/platsbanken/annonser/31650623",
  "title": "Kommun i söder söker sjuksköterskor",
  "employer": "Ofelia Vård AB",
  "employerWorkplace": "Ofelia Vård",
  "employerOrgNumber": "5565792131",
  "occupation": "Sjuksköterska, grundutbildad",
  "occupationGroup": "Grundutbildade sjuksköterskor",
  "occupationField": "Hälso- och sjukvård",
  "municipality": "Malmö",
  "region": "Skåne län",
  "city": "Stockholm",
  "country": "Sverige",
  "salaryType": "Fast månads- vecko- eller timlön",
  "salary": null,
  "employmentType": "Behovsanställning",
  "workingHours": null,
  "duration": null,
  "vacancies": 1,
  "publishedAt": "2026-10-27T13:56:04",
  "applicationDeadline": "2026-11-02T23:59:59",
  "applyUrl": null,
  "description": "Ofelia Vård AB är tillsammans med Skandinavisk Hälsovård, … Vi söker för kunds räkning sjuksköterska. …",
  "requiredSkills": [],
  "niceToHaveSkills": [],
  "enrichedSkills": ["Konsultchefer", "Vårderfarenhet", "Arbetsmiljö"],
  "source": "Arbetsförmedlingen / JobTech (CC0)"
}
```

`salary` holds the employer's salary text when the employer provides one. Most Platsbanken ads only give `salaryType`, and the details are in `description`. `city` is the postal city of the workplace address, so it can differ from `municipality`.

### Pricing

This Actor uses pay-per-event pricing:

- **$0.001** per run (Actor start)
- **$0.002** per job ad saved

For example, a run that returns 100 ads costs $0.201. Set a maximum cost per run in the Apify Console to cap your spend.

### Data source and license

- Job ads: [JobTech JobSearch and JobStream APIs](https://jobtechdev.se) by **Arbetsförmedlingen**, published under **CC0 1.0**.
- Skills: [JobAd Enrichments](https://data.jobtechdev.se/dataset/jobad-enrichments/) by Arbetsförmedlingen, published under [CC0 1.0](https://creativecommons.org/publicdomain/zero/1.0/).
- This Actor is not affiliated with Arbetsförmedlingen.

The Actor follows the API rate limits. It sends one JobStream request per minute, as JobStream's documentation requires. Other requests go at most about 3 per second. It backs off when an API returns errors or `429`.

### Limitations

- Search mode returns at most about 2,100 ads per query, because JobSearch stops paging at offset 2000. Narrow the filters or use delta mode to get more.
- In delta mode the filters run on the Actor side, so every day of changes for all of Sweden is downloaded (about 25–60 MB per day). Each extra day of `changedSince` adds about one minute, because of the JobStream rate limit. A daily delta needs a single request.
- Removed (expired) ads are not output.
- Personal data in free text is removed by rules. The Actor removes each part of a listed contact's name, sentences that point to a contact, emails and phone numbers. Names can remain in the ad text when they are not listed as contacts, or when they are misspelt in a sentence that has no contact wording or contact details. Employer names are kept, and for a sole trader the employer name is a person's name.

# Actor input Schema

## `keywords` (type: `string`):

Free-text search, e.g. "java utvecklare". In delta mode every word must appear in the title, description, employer or occupation.

## `location` (type: `string`):

Municipality, city or county (län), e.g. "Göteborg" or "Skåne". Matched as text against the workplace address.

## `occupation` (type: `string`):

Occupation, occupation group or field in Swedish, e.g. "sjuksköterska" or "Data/IT".

## `maxItems` (type: `integer`):

Maximum number of ads to save in this run.

## `onlyNewSinceLastRun` (type: `boolean`):

Daily delta: return only ads published or changed since the previous run with the same filters. The first run covers the last 24 hours (or 'Changed since' if set). Use with a daily schedule.

## `changedSince` (type: `string`):

Only ads published or changed after this date/time (ISO 8601, e.g. 2026-10-26 or 2026-10-26T08:00:00Z). At most 31 days back. JobStream allows one request per minute, so each extra day adds about a minute. Leave empty to search all current ads.

## `enrichSkills` (type: `boolean`):

Extract skills from the ad text with JobTech's JobAd Enrichments API (CC0).

## Actor input object example

```json
{
  "keywords": "utvecklare",
  "maxItems": 100,
  "onlyNewSinceLastRun": false,
  "enrichSkills": true
}
```

# Actor output Schema

## `jobAds` (type: `string`):

Job ads from Platsbanken, one item per ad.

# 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": "utvecklare"
};

// Run the Actor and wait for it to finish
const run = await client.actor("inkhaan/swedish-jobs-jobtech").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": "utvecklare" }

# Run the Actor and wait for it to finish
run = client.actor("inkhaan/swedish-jobs-jobtech").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": "utvecklare"
}' |
apify call inkhaan/swedish-jobs-jobtech --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,inkhaan/swedish-jobs-jobtech"
        }
    }
}
```

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/12Y9FZcgHmXxwezUw/builds/GL7xlGXJNMsLQpZ18/openapi.json
