# Sweden Public Job Ads Feed (`jetlaunch/nordic-public-job-feeds`) Actor

Search and monitor public job ads from the Swedish Public Employment Service open API in one clean schema.

- **URL**: https://apify.com/jetlaunch/nordic-public-job-feeds.md
- **Developed by:** [Chris O'Byrne](https://apify.com/jetlaunch) (community)
- **Categories:** Jobs, Lead generation
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.50 / 1,000 job ad returneds

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 Public Job Ads Feed

This Actor reads the public job ads of the Swedish Public Employment Service (Arbetsförmedlingen) from its official open JobSearch API and returns them in one clean, flat schema. You can search by keyword, occupation, municipality, county and publication date, or run it on a schedule in "new since last run" mode so that each run returns only ads you have not seen before.

It uses only the official open API at jobsearch.api.jobtechdev.se. There is no scraping, no login and no proxy. The ads are published as open data under the CC0 1.0 licence (public domain dedication), as stated in the API's own documentation.

### Who is it for

- Recruiters, staffing agencies and HR tech teams that need Swedish vacancies in a spreadsheet or database.
- Job boards and aggregators that want a steady feed of new ads.
- Labor market analysts who track demand by occupation, municipality or county.
- Developers who want a ready-made, normalized job record without reading the API documentation.

### What you get

One record per ad: source, id, title, employer name, occupation, occupation group and field, municipality, county, country, employment type, working hours (text and percent range), duration, workplace model, salary type, salary description, number of vacancies, publication date, application deadline, a plain text description (length capped by you), the application URL and the public ad page. Text labels such as occupation and employment type are in Swedish, as published by the source.

No personal data is returned. Contact persons, contact e-mail addresses and phone numbers are never requested from the API. E-mail addresses and phone numbers that employers type into the free text description are masked as \[email removed] and \[phone removed]. This masking is best effort and cannot catch every written-out contact detail.

### Input

| Field | Meaning |
| --- | --- |
| country | SE (Sweden). The only value at the moment. |
| keywords | Free text words, searched in title, description and employer name. Any or all (keywordMatch). |
| occupation | A Swedish taxonomy occupation name such as Systemutvecklare/Programmerare, or a field such as Data/IT. Partial names match. |
| municipality | Swedish municipality names, for example Stockholm or Göteborg (or 4 digit codes). |
| region | Swedish county names, with or without län, for example Skåne (or 2 digit codes). |
| publishedSince | Only ads published on or after this date. |
| sort | Newest first (default) or relevance. |
| maxResults | 1 to 2,100. Default 25. |
| descriptionMaxChars | Cap for the description text. 0 removes it. Default 3,000. |
| mode | search, or new-since-last-run. |
| monitorName | Name of the saved search for new-since-last-run mode. |

The prefill (Sweden, keyword "developer", 25 results) finishes in a few seconds.

### Monitor mode

In new-since-last-run mode the Actor remembers the ids of the ads it has returned, in a named key-value store in your own account called nordic-job-feeds-state, under the key SEEN- plus your monitor name. Each run reads ads published in the 7 days before the previous run (or since your date, whichever is later), skips ids it has already returned and returns only the new ones, each marked isNew true. The first run of a monitor returns the newest matches up to maxResults. Use one monitor name per saved search and keep its filters the same between runs. Create a schedule in Apify to run it daily or hourly.

### Output example

```json
{
  "source": "arbetsformedlingen.se",
  "id": "31629347",
  "title": "Developer",
  "employer": "Example Consulting AB",
  "occupation": "Systemutvecklare/Programmerare",
  "occupationField": "Data/IT",
  "municipality": "Stockholm",
  "region": "Stockholms län",
  "country": "SE",
  "employmentType": "Tidsbegränsad anställning",
  "workingHours": "Heltid",
  "salaryType": "Fast månads- vecko- eller timlön",
  "publicationDate": "2026-10-22T00:00:00",
  "applicationDeadline": "2026-11-27T23:59:59",
  "description": "Senior Robotics Engineer ...",
  "applicationUrl": "https://arbetsformedlingen.se/platsbanken/annonser/31629347"
}
```

### Pricing

Pay per event. You pay only for ads written to the dataset, never for empty or failed runs.

| Event | Price | When it is charged |
| --- | --- | --- |
| job-record | $0.0015 per ad | Each ad returned in search mode |
| new-job-record | $0.002 per ad | Each new ad returned in new-since-last-run mode |

In monitor mode only new-job-record is charged, not job-record. Ads already seen are skipped and free. If your run reaches its spending limit, the Actor stops cleanly.

### FAQ

**Is it legal to use this data?** The API documentation states that the ads are licensed under CC0, which allows any use. See https://creativecommons.org/publicdomain/zero/1.0/. Employer names and ad texts are still subject to normal law, for example data protection rules if you combine them with personal data.

**Why only 2,100 results per query?** The API lets you page through the first 2,100 matches of a query (offset up to 2,000, 100 per page). Narrow the filters, or split by county or date, for larger sets.

**Why are labels in Swedish?** They come straight from the source taxonomy. Keyword search also works with English words found in ad texts.

**What about Finland?** Not included. The Finnish Työmarkkinatori job posting interface requires credentials issued by the authority and its terms do not allow passing listings on to third parties.

**How fresh is it?** The API is queried live on every run.

### Limitations

- Sweden only. Requests are sent one at a time, about two per second at most, with automatic retries and backoff.
- Ads removed at the source are not returned. An ad that changes keeps its id and is not reported as new.
- Monitor mode only sees ads whose publication date falls in the look-back window.

### Data source and disclaimer

Data: Arbetsförmedlingen (Swedish Public Employment Service), JobTech JobSearch open API, https://jobsearch.api.jobtechdev.se, ads licensed CC0 1.0. This Actor is not affiliated with or endorsed by Arbetsförmedlingen, JobTech Dev or the Swedish government.

### Support

Questions, bug reports and feature requests are welcome in the Issues tab of this Actor.

# Actor input Schema

## `country` (type: `string`):

Only Sweden (SE) is available at the moment.

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

Free text search words, one per line, for example developer or sjuksköterska. They are searched in the ad title, description and employer name. Leave empty to list the newest ads.

## `keywordMatch` (type: `string`):

Any: an ad matches when it contains at least one keyword. All: an ad must contain every keyword.

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

Optional. A Swedish occupation name from the Arbetsförmedlingen taxonomy, for example Systemutvecklare/Programmerare, or an occupation field such as Data/IT or Hälso- och sjukvård. A partial name matches every occupation containing it.

## `municipality` (type: `array`):

Optional. Swedish municipality names, one per line, for example Stockholm or Göteborg. A 4 digit municipality code also works.

## `region` (type: `array`):

Optional. Swedish county names, one per line, with or without län, for example Skåne or Västra Götaland. A 2 digit county code also works.

## `publishedSince` (type: `string`):

Optional. Only ads published on or after this date (YYYY-MM-DD).

## `sort` (type: `string`):

Newest first, or by relevance to the keywords.

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

Maximum number of ads to return. The API exposes the first 2,100 matches of any query, so narrow the filters for larger sets. You are charged per ad returned.

## `descriptionMaxChars` (type: `integer`):

Maximum characters of plain text description per ad. Set 0 for no description.

## `mode` (type: `string`):

Search: return the matching ads every run. New since last run: return only ads not returned by an earlier run of the same monitor name (the first run returns the newest matches). Billed as new-job-record per new ad.

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

Used only in new-since-last-run mode. Runs with the same name share one list of seen ad ids, so use one name per saved search and keep the filters the same between runs.

## Actor input object example

```json
{
  "country": "SE",
  "keywords": [
    "developer"
  ],
  "keywordMatch": "any",
  "sort": "newest",
  "maxResults": 25,
  "descriptionMaxChars": 3000,
  "mode": "search",
  "monitorName": "default"
}
```

# Actor output Schema

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

One record per job ad with title, employer, occupation, place, employment terms, dates, description and application link.

# 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 = {
    "country": "SE",
    "keywords": [
        "developer"
    ],
    "maxResults": 25
};

// Run the Actor and wait for it to finish
const run = await client.actor("jetlaunch/nordic-public-job-feeds").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 = {
    "country": "SE",
    "keywords": ["developer"],
    "maxResults": 25,
}

# Run the Actor and wait for it to finish
run = client.actor("jetlaunch/nordic-public-job-feeds").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 '{
  "country": "SE",
  "keywords": [
    "developer"
  ],
  "maxResults": 25
}' |
apify call jetlaunch/nordic-public-job-feeds --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,jetlaunch/nordic-public-job-feeds"
        }
    }
}
```

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/Ja6sMezqe2MeUDlb1/builds/KoHXkEaAtGB0PbruK/openapi.json
