# Swedish Jobs Scraper - Platsbanken API (`teddythebuilder/swedish-jobs-monitor`) Actor

Scrape all Swedish job ads from Platsbanken via Arbetsförmedlingen's official JobTech API. Get title, employer, org number, occupation, location, salary type, skills and apply URL. New/removed-ad tracking and 'companies hiring' lists. JSON/CSV/Excel, API or MCP.

- **URL**: https://apify.com/teddythebuilder/swedish-jobs-monitor.md
- **Developed by:** [Teddy Wasserman](https://apify.com/teddythebuilder) (community)
- **Categories:** Jobs, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.83 / 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.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

### What does Swedish Jobs Scraper do?

**Swedish Jobs Scraper** is a fast **Platsbanken API** for every job ad published in Sweden. It reads the official **Arbetsförmedlingen** JobTech API, the open-data feed behind Platsbanken, so it needs no login, no browser and no proxy. You get clean, typed JSON for each ad: headline, employer, **employer org number**, occupation and SSYK code, municipality and region, employment type, salary type, skills, application deadline and apply URL.

Three things set it apart from a plain Swedish jobs scraper:

- **Monitor mode** returns only the ads that are new since your last run. It also returns a `removed` event when a tracked ad is taken down, which usually means the position was filled.
- **Employer mode** turns thousands of ads into a "companies hiring now" lead list: one row per employer org number, with open ads, top occupations and locations.
- **Personal data is stripped.** Recruiter names, e-mails and phone numbers are never output.

Run it once for a snapshot of the Swedish job market, or schedule it daily for a stream of hiring signals.

### Why use Swedish Jobs Scraper?

- **Official source, stable schema.** It uses Arbetsförmedlingen's JobTech JobSearch and JobStream APIs (CC0 open data) instead of scraping HTML, so it doesn't break when the Platsbanken website changes.
- **Complete coverage.** All ads currently in Platsbanken, about 40,000 at any time, including ads that employers post through job boards and staffing agencies.
- **No login, no API key, no proxy.** Runs at 256 MB and returns 20 ads in a few seconds.
- **Org numbers on every company ad.** Join them with Bolagsverket data, your CRM or our [Nordic Company Registry API](https://apify.com/teddythebuilder/nordic-company-registry).
- **Removed-ad detection.** Know when a job is filled or withdrawn, not just when it appears.
- **GDPR-friendly by design.** Contact persons, recruiter e-mails and phone numbers are dropped. E-mail addresses and phone numbers inside ad texts are redacted, and sole traders (whose org number is a personal identity number) are anonymised.
- **Cheap.** $1.50 per 1,000 job ads, with volume discounts on higher Apify plans.
- **Works everywhere.** Export JSON, CSV or Excel. Schedule runs, trigger webhooks, call it from Make, Zapier or n8n, or let an AI agent call it through the Apify API or MCP.

### What data can you extract?

#### Job ads (output type `ads`)

| Field | Example | Description |
|---|---|---|
| `adId` | `31549556` | Platsbanken ad ID |
| `eventType` | `ad`, `new`, `removed` | `new`/`removed` are used in monitor mode |
| `headline` | `FPGA Validation Engineer` | Ad title |
| `employerName` | `Ericsson AB` | Employer (sole traders are redacted) |
| `employerOrgNumber` | `556056-6258` | Swedish organisation number |
| `employerWebsite` | `www.ericsson.com` | When provided |
| `occupation` | `Systemutvecklare/Programmerare` | Occupation name (Arbetsförmedlingen taxonomy) |
| `occupationGroup` / `ssykCode` | `2512` | SSYK 2012 occupation group |
| `occupationField` | `Data/IT` | Top-level occupation field |
| `municipality`, `municipalityCode` | `Stockholm`, `0180` | Workplace municipality |
| `region`, `regionCode` | `Stockholms län`, `01` | County (län) |
| `employmentType`, `workingHours`, `duration` | `Heltid` | Contract details |
| `salaryType`, `salaryDescription` | `Fast månadslön` | Salary form, plus a free-text description when given |
| `numberOfVacancies` | `3` | Positions in the ad |
| `mustHaveSkills`, `niceToHaveSkills`, `requiredLanguages` | `["Python"]` | Structured requirements when the employer filled them in |
| `experienceRequired`, `drivingLicenseRequired` | `true` | Flags |
| `publishedAt`, `applicationDeadline` | `2026-10-02T18:25:03` | Swedish local time |
| `applyUrl`, `adUrl` | URL | Apply link (never an e-mail) and Platsbanken link |
| `description` | text | Ad text with e-mails/phones redacted (optional, truncated) |

#### Hiring employers (output type `employers`)

| Field | Example | Description |
|---|---|---|
| `employerOrgNumber` | `556056-6258` | Organisation number |
| `employerName` | `Ericsson AB` | Most common name in the ads |
| `openAds` / `totalVacancies` | `14` / `22` | How much the company is hiring |
| `topOccupations` | `[{"occupation": "Systemutvecklare", "ads": 6}]` | What it hires for |
| `occupationFields`, `municipalities` | `["Data/IT"]`, `["Stockholm", "Linköping"]` | Where and in which fields |
| `remoteAds` | `3` | Ads marked remote or hybrid |
| `newestAdPublishedAt`, `oldestAdPublishedAt` | dates | Hiring recency |
| `sampleAdUrls` | URLs | Up to 3 example ads |

### How to use Swedish Jobs Scraper (step by step)

1. Click **Try for free** and open the actor's **Input** tab.
2. Type a **search text** (e.g. `python`, `sjuksköterska`, `lagerarbetare göteborg`) or leave it empty to get all ads.
3. Optionally narrow by **occupation field**, **region (län)**, **municipality codes**, **employer org numbers** or **remote only**.
4. Set **Published within last N days** (default 3) and **Max results** (default 20).
5. Choose **Output**: job ads, or employers hiring (aggregated lead list).
6. Click **Start**. Download the results as JSON, CSV or Excel, or connect an integration. For a daily feed, switch on **Monitor mode** and add a **Schedule** (for example every morning at 07:00).

### Input example

Daily IT jobs in Stockholm and Gothenburg, new and removed ads only:

```json
{
  "outputType": "ads",
  "query": "python",
  "occupationFields": ["apaJ_2ja_LuF"],
  "regions": ["CifL_Rzy_Mku", "zdoY_6u5_Krt"],
  "publishedWithinDays": 3,
  "onlyNew": true,
  "includeRemoved": true,
  "monitorId": "it-sthlm-gbg",
  "maxResults": 500
}
```

A "companies hiring nurses" lead list:

```json
{
  "outputType": "employers",
  "query": "sjuksköterska",
  "publishedWithinDays": 30,
  "maxAdsToScan": 5000,
  "maxResults": 200
}
```

### Output example

Two real job ads (descriptions shortened):

```json
[
  {
    "adId": "31549539",
    "eventType": "ad",
    "headline": "Integrationsutvecklare",
    "employerName": "Cyberway AB",
    "employerOrgNumber": "559477-7608",
    "employerWorkplace": "Cyberway AB",
    "employerWebsite": "cyberway.se",
    "occupation": "Systemutvecklare/Programmerare",
    "occupationGroup": "Mjukvaru- och systemutvecklare m.fl.",
    "occupationField": "Data/IT",
    "ssykCode": "2512",
    "municipality": "Malmö",
    "municipalityCode": "1280",
    "region": "Skåne län",
    "regionCode": "12",
    "country": "Sverige",
    "employmentType": "Tillsvidareanställning (inkl. eventuell provanställning)",
    "workingHours": "Heltid",
    "duration": "Tills vidare",
    "salaryType": "Fast månads- vecko- eller timlön",
    "numberOfVacancies": 3,
    "experienceRequired": true,
    "drivingLicenseRequired": false,
    "publishedAt": "2026-10-02T18:37:10",
    "applicationDeadline": "2026-11-30T23:59:59",
    "applyUrl": "https://www.cyberway.se/job/fullstack-developer",
    "adUrl": "https://arbetsformedlingen.se/platsbanken/annonser/31549539",
    "description": "På Cyberway tror vi att teknik kan göra vardagen enklare, smartare och mer hållbar …",
    "source": "Arbetsförmedlingen JobTech JobSearch API (CC0)",
    "retrievedAt": "2026-10-04T09:53:16+00:00"
  },
  {
    "adId": "31549556",
    "eventType": "ad",
    "headline": "FPGA Validation Engineer",
    "employerName": "Ericsson AB",
    "employerOrgNumber": "556056-6258",
    "employerWebsite": "www.ericsson.com",
    "occupation": "Systemutvecklare/Programmerare",
    "occupationField": "Data/IT",
    "ssykCode": "2512",
    "municipality": "Stockholm",
    "municipalityCode": "0180",
    "region": "Stockholms län",
    "regionCode": "01",
    "employmentType": "Vanlig anställning",
    "workingHours": "Heltid",
    "numberOfVacancies": 1,
    "publishedAt": "2026-10-02T18:25:03",
    "applicationDeadline": "2026-10-16T23:59:59",
    "applyUrl": "https://ericsson-ab.contactrh.com/jobs/9669/44481423",
    "adUrl": "https://arbetsformedlingen.se/platsbanken/annonser/31549556",
    "description": "Join Ericsson in Stockholm to work on innovative 5G and 6G mobile communication solutions …",
    "source": "Arbetsförmedlingen JobTech JobSearch API (CC0)",
    "retrievedAt": "2026-10-04T09:53:16+00:00"
  }
]
```

Every run's dataset can be exported as **JSON, CSV, Excel, XML or RSS** from the Storage tab or via the API. The dataset has ready-made table views for job ads and employers.

### How much does it cost?

Swedish Jobs Scraper uses **pay-per-event** pricing. You only pay for results delivered, plus a tiny start fee.

| Event | Price (Free plan) | Bronze | Silver | Gold | Platinum | Diamond |
|---|---|---|---|---|---|---|
| Run start (per GB memory) | $0.0005 | $0.0005 | $0.0005 | $0.0005 | $0.0005 | $0.0005 |
| Job ad (or removed-ad event) | $0.0015 | $0.001275 | $0.00105 | $0.000825 | $0.000825 | $0.000825 |
| Hiring-employer row | $0.01 | $0.0085 | $0.007 | $0.0055 | $0.0055 | $0.0055 |

Higher Apify plans get the discounts automatically: −15% (Bronze), −30% (Silver) and −45% (Gold, Platinum and Diamond). Platform usage is included in the price.

Worked examples (Free plan prices):

- **1,000 job ads** in one run cost $0.0005 + 1,000 × $0.0015 ≈ **$1.50**.
- **A daily monitor** of IT jobs in Stockholm with about 150 new ads per day costs about 150 × $0.0015 = $0.23 per day, roughly **$7 per month**. Days with fewer new ads cost less.
- **A lead list of 200 hiring employers** built from 5,000 scanned ads costs 200 × $0.01 = **$2.00**. Scanning ads in employer mode is free; only employer rows are charged.

Apify's free plan includes $5 of monthly credit, which is enough for about 3,000 job ads a month. Set **Max results** to cap any run's cost, and the actor also stops cleanly when your maximum charge per run is reached.

### Use cases

- **Recruiters and talent sourcers.** Get every new ad for your roles each morning, find out which companies hire the profiles you place, and spot when competitors' positions are filled.
- **Staffing and recruitment agency sales.** Use employer mode to build a "companies hiring now" list with org numbers, filtered by occupation field and region, then prioritise employers with many open ads or long-open positions.
- **B2B sales and marketing.** Hiring is a buying signal. A company hiring 10 developers needs laptops, software, office space and consultants. Feed new employers into your CRM daily.
- **Labour-market analysts and researchers.** Track demand by occupation (SSYK), region and contract type over time. Removed-ad events let you estimate time-to-fill.
- **Job boards and aggregators.** Keep a Swedish job index in sync, including removals, without scraping HTML.
- **AI agents.** Give an assistant a tool that answers "which companies in Göteborg are hiring nurses right now?" with structured data.

### Use with AI agents, MCP and the API

The actor works well as a tool for AI agents: inputs are small, defaults run in seconds, and the output is flat JSON.

**Apify MCP server.** Add the Apify MCP server (`https://mcp.apify.com`) to Claude, Cursor or any MCP client and let the agent call `teddythebuilder/swedish-jobs-monitor` with a search text.

**curl** (synchronous run, returns the items):

```bash
curl -X POST "https://api.apify.com/v2/acts/teddythebuilder~swedish-jobs-monitor/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"query": "data engineer", "publishedWithinDays": 7, "maxResults": 50}'
```

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

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("teddythebuilder/swedish-jobs-monitor").call(run_input={
    "outputType": "employers",
    "query": "sjuksköterska",
    "publishedWithinDays": 14,
    "maxResults": 100,
})
for row in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(row["employerName"], row["employerOrgNumber"], row["openAds"])
```

### Integrations

- **Google Sheets, Airtable, Slack, e-mail** through Apify integrations or Make/Zapier/n8n.
- **Webhooks** on run success, to push new ads into your ATS, CRM (HubSpot, Pipedrive, Salesforce) or data warehouse.
- **Schedules** in Apify Console for daily or hourly monitoring. Use a different **Monitor ID** for each saved search.
- **Apify API and SDKs** for JavaScript and Python, plus the dataset API for CSV/Excel downloads.

### Data source and legality

All data comes from **Arbetsförmedlingen's JobTech Dev APIs** (JobSearch and JobStream), published as open data under **CC0**. Arbetsförmedlingen provides them for reuse, so this is not website scraping and there are no terms of service to break.

The actor is built to avoid personal data. Application contacts and recruiter names, e-mails and phone numbers are never output. E-mail addresses and phone numbers inside ad texts are replaced with `[email removed]` / `[phone removed]`. Apply links that are e-mail addresses are dropped. Employers whose organisation number is a personal identity number (sole traders) are shown as `[sole trader - redacted]` without the number. If you process the data further, you are still responsible for your own GDPR compliance.

### FAQ

#### How fresh is the data?

JobTech updates in near real time: an ad published in Platsbanken appears in the API within minutes. Each run reads live data.

#### How many ads can I get?

All ads currently published in Platsbanken, usually around 40,000. Set **Published within last N days** to 365 and raise **Max results** to fetch everything. The actor pages past the API's 2,000-result window automatically.

#### How does monitor mode work?

With **Monitor mode** on, the actor stores the IDs of ads it has delivered for your **Monitor ID** in your own Apify key-value store. The next run outputs only unseen ads (`eventType: "new"`) and, for tracked ads that were unpublished since the last run, a `removed` event. The first run outputs all current matches and saves the baseline.

#### Why is a field empty?

Employers fill in different parts of the ad. Skills, salary description and website are often missing in the source. The actor never invents values.

#### Can I use it on Apify's free plan?

Yes. The free plan's $5 monthly credit covers about 3,000 job ads. The default input returns 20 ads in a few seconds.

#### Does it cover Norway, Denmark or Finland?

Not yet. This actor covers Sweden (Platsbanken). For Nordic companies and public tenders, see the related actors below. Open an issue if you need another country.

#### What if the run returns no results?

The run still succeeds and writes one `_info` row explaining that nothing matched; that row is free. Widen the search text, remove filters or increase the number of days.

#### Can you add a field or filter?

Probably. Open an issue on the actor's **Issues** tab; we reply within 24 hours. If the actor saves you time, a short review helps other users find it.

### Related actors

- [Nordic Company Registry API](https://apify.com/teddythebuilder/nordic-company-registry): enrich employer org numbers with industry (SNI/NACE), legal form, address and registration date for Sweden, Norway and Finland.
- [Nordic Tenders Scraper - TED API](https://apify.com/teddythebuilder/nordic-public-tenders-monitor): public procurement tenders and contract awards from Swedish, Norwegian, Danish and Finnish buyers.
- [Career Site Jobs API](https://apify.com/teddythebuilder/career-site-jobs-api): jobs straight from company career sites on Greenhouse, Lever, Ashby, Workable, Recruitee and Teamtailor in one schema, with new/removed-job tracking.
- [Tech Stack Detector](https://apify.com/teddythebuilder/tech-stack-detector): bulk-detect the CMS, e-commerce platform, analytics, CDN and email provider behind any list of company domains.

### Changelog and support

- **1.1 (2026-10-04):** renamed to Swedish Jobs Scraper, lower price ($1.50/1k ads), quick default run (20 ads), an empty-result info row, and apply links that are e-mail addresses are dropped.
- **1.0 (2026-10-04):** first release with job ads, monitor mode with removed-ad detection, and employer aggregation.

Found a bug or need a feature? Open an issue on the **Issues** tab and we'll reply within 24 hours.

# Actor input Schema

## `outputType` (type: `string`):

ads = clean job-ad records. employers = 'companies hiring now' lead list: one row per employer org number with open ads, occupations and locations.

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

Free text, same as the Platsbanken search box. Example: 'python', 'sjuksköterska' or 'lagerarbetare göteborg'. Leave empty for all ads.

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

Arbetsförmedlingen occupation fields. Empty = all.

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

Empty = whole Sweden.

## `municipalityCodes` (type: `array`):

Optional 4-digit kommun codes, e.g. 0180 Stockholm, 1480 Göteborg, 1280 Malmö.

## `employerOrgNumbers` (type: `array`):

Only ads from these employers (e.g. track competitors' or customers' hiring).

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

Only ads marked as remote work.

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

Only ads published in the last N days. Use 365 to include all currently open ads (~40,000).

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

Outputs only ads you have not received before (eventType 'new') and, for ads you received earlier, a 'removed' event when they are taken down (usually = position filled). Schedule daily.

## `includeRemoved` (type: `boolean`):

Emit eventType 'removed' rows for previously delivered ads that were unpublished since the last run.

## `monitorId` (type: `string`):

Name of this saved search for monitor mode.

## `includeDescription` (type: `boolean`):

E-mail addresses and phone numbers in the text are redacted.

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

Truncate descriptions (0 = no limit).

## `maxAdsToScan` (type: `integer`):

How many ads to read when aggregating employers. Scanning is free; you pay per employer row.

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

Maximum rows to output; each row is one billable result. Example: 20 for a quick test, 5000 for a full daily export.

## Actor input object example

```json
{
  "outputType": "ads",
  "query": "python",
  "remoteOnly": false,
  "publishedWithinDays": 3,
  "onlyNew": false,
  "includeRemoved": true,
  "monitorId": "default",
  "includeDescription": true,
  "descriptionMaxChars": 3000,
  "maxAdsToScan": 5000,
  "maxResults": 20
}
```

# Actor output Schema

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

No description

# 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 = {
    "outputType": "ads",
    "query": "python",
    "publishedWithinDays": 3,
    "maxResults": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("teddythebuilder/swedish-jobs-monitor").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 = {
    "outputType": "ads",
    "query": "python",
    "publishedWithinDays": 3,
    "maxResults": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("teddythebuilder/swedish-jobs-monitor").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 '{
  "outputType": "ads",
  "query": "python",
  "publishedWithinDays": 3,
  "maxResults": 20
}' |
apify call teddythebuilder/swedish-jobs-monitor --silent --output-dataset

```

## MCP server setup

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

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/YKxLBLuZZucXokzOY/builds/M0SXbzkNWUGwyEpQ9/openapi.json
