Nordic Jobs Scraper & Alerts: Norway, Sweden, Finland, Denmark
Pricing
from $0.90 / 1,000 jobs
Nordic Jobs Scraper & Alerts: Norway, Sweden, Finland, Denmark
Scrape job listings from NAV (Norway), Arbetsförmedlingen Platsbanken (Sweden) and EURES (Finland, Denmark, Iceland) via official public APIs. Daily job alerts with only new jobs to Slack, webhook or email. One clean schema, export CSV/JSON.
Pricing
from $0.90 / 1,000 jobs
Rating
0.0
(0)
Developer
Tidy Data
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Security
Limited permissionsShare
This Nordic jobs scraper collects job listings from official public job sources for Norway, Sweden, Finland, Denmark and Iceland and turns them into one clean dataset: Norway from NAV Arbeidsplassen, Sweden from Arbetsförmedlingen Platsbanken (JobTech open-data API), and Finland, Denmark and Iceland from EURES, the European Commission's job portal. Turn on job alerts to get only the jobs that are new since the last run, delivered to Slack, a webhook or e-mail. Search by keyword, location and posting date, and export to JSON, CSV or Excel.
- 🌍 Five countries, one schema. NAV, Platsbanken and EURES ads land in the same fields: job title, company, location, posted date, application deadline, employment type, full description and apply link.
- 🏛️ Official public APIs only. No login, no browser, no fragile HTML scraping. It uses NAV's public job feed and search, the JobTech open-data API behind Platsbanken, and the public EURES search.
- 🧹 Clean, de-duplicated data. Dates in ISO 8601 (UTC), normalized employment and contract types, plain-text descriptions, and the employer's organisation number where it is available. Reposted duplicates are removed.
- ⚡ Fast and light. In our tests, about 1,000 jobs from four countries (with full descriptions) took under 3 minutes on 256 MB of memory.
- 🔔 Built-in job alerts. Turn on
onlyNewJobs, schedule the Actor, and get only new jobs by Slack, e-mail or webhook. Jobs you already got are never charged again. - 💸 Pay only for results. You pay per job delivered. Duplicates, filtered-out ads and failed requests are never charged.
- 🔒 Contact details masked by default. The Actor does not extract contact persons into separate fields, and e-mail addresses and phone numbers in the ad texts are replaced with
[email removed]/[phone removed](redactContacts, on by default). Apply links and company websites are kept (see Personal data).
Scrape jobs in Norway
Norway uses NAV Arbeidsplassen, Norway's public job board, via NAV's search and its public job feed. Ads that NAV imports from FINN.no come without the full text (see Limits). Set countries: ["NO"] and search in Norwegian or English, e.g. utvikler or developer.
Scrape jobs in Sweden
Sweden uses Arbetsförmedlingen Platsbanken through the JobTech open-data API (often searched for as the "Arbetsförmedlingen API"). Every ad has a full description. Platsbanken's search does not translate, so use Swedish terms such as sjuksköterska or utvecklare.
Finland and Denmark job listings
Finland, Denmark (and Iceland) use EURES, the European Commission's job portal. Most Finnish ads come from Työmarkkinatori (Job Market Finland), and Danish ads are those that Jobnet and Danish employers share with EURES. EURES searches across languages.
What can you use it for?
- Job market research: compare demand for a role (e.g. nurses, developers, electricians) across Norway, Sweden, Finland and Denmark.
- Recruitment and staffing agencies: find companies that are hiring right now, with the organisation number for CRM enrichment.
- Job alerts and job boards: get notified about new jobs in Norway, Sweden, Finland or Denmark by Slack, e-mail or webhook (see Job alerts), or push them to Google Sheets, a database or your own site.
- Salary and skills analysis, HR tech and AI: feed structured job ads into dashboards, LLM pipelines or RAG search.
- Relocation and talent mobility: list English-language jobs in the Nordics for international candidates.
Input fields
| Field | Description |
|---|---|
countries | Any of NO, SE, FI, DK, IS. Default: Norway, Sweden, Finland and Denmark. |
searchTerms | Keywords, e.g. ["developer"] or local job titles ["sykepleier", "sjuksköterska", "sairaanhoitaja", "sygeplejerske"]. Every term is searched in every selected country and duplicates are removed. Leave empty to get the newest jobs of any kind. |
keywordMatch | How strictly a search term must match. title (default): the term must appear in the job title, the standardized job title or the occupation. fullText: anywhere in the ad, including the description. source: keep whatever the job site's own search returns (broadest, often loose). See Keyword matching. |
location | Optional city, municipality or region, e.g. Oslo, Bergen, Göteborg, Tampere, Aarhus. Select the matching country for best results. |
postedWithinDays | Only jobs published in the last N days, e.g. 1 for a daily schedule. |
postedAfter | Optional YYYY-MM-DD. Only jobs published on or after this date. |
maxItemsPerCountry | Stop after this many jobs per country. Default 100. 0 = all available. |
maxItems | Optional cap for the whole run. 0 = no cap. |
includeDescription | Fetch the full ad (description, apply URL, deadline, employer details). Default on. Turn off for a faster run with search data only (Sweden and the EURES countries still include the description). |
includeDescriptionHtml | Also return the original HTML description. Default off. |
dedupeByTitleAndCompany | Remove reposted ads with the same title, company and city. Default on. |
skipFinnImportedAds | Norway only: skip ads that NAV imports from FINN.no, which come without a full description (see Limits). Default off. |
redactContacts | Replace e-mail addresses and phone numbers in the ad texts with [email removed] / [phone removed] (see Personal data). Default on. |
onlyNewJobs | Job alert mode: return only jobs that previous runs of the same alert have not returned yet. See Job alerts. Default off. |
alertName | Name of the alert, e.g. oslo-developers. Each name keeps its own memory of seen jobs. Use one name per search. |
resetAlert | Forget the jobs this alert has seen and start a new baseline. Default off. |
webhookUrl | POST a JSON summary plus the job list to this URL when the run finds at least 1 job (Zapier, Make, n8n, your own API). |
slackWebhookUrl | Slack incoming webhook URL. Posts a message with the newest jobs and links when the run finds at least 1 job. |
emailTo | Send an e-mail with the newest jobs to your address when the run finds at least 1 job. Must be the e-mail address of your Apify account (an Apify rule). Adds a very small platform cost, see below. |
notifyTopN | How many jobs to list in the Slack message and e-mail. Default 10, max 40. |
proxyConfiguration | Apify Proxy (datacenter) by default, used only for the NAV search, which rate-limits shared cloud IP addresses. All other sources connect directly. |
Example:
{"countries": ["NO", "SE", "FI", "DK"],"searchTerms": ["developer", "utvikler", "utvecklare"],"postedWithinDays": 7,"maxItemsPerCountry": 200}
Job data fields
One dataset item per job:
{"jobId": "platsbanken-31686710","source": "Arbetsförmedlingen Platsbanken","country": "SE","countryName": "Sweden","title": "Lärare i SV/SVA till Klingsborgsskolan","jobTitle": "Lärare i grundskolan, årskurs 7-9","company": "Norrköpings kommun","companyId": "2120000456","location": "Norrköping, Östergötlands län","city": "Norrköping","region": "Östergötlands län","postedAt": "2026-11-04T16:39:15Z","deadline": "2026-11-22","employmentType": "full-time","contractType": "permanent","numberOfPositions": 1,"occupation": "Grundskollärare","salary": null,"salaryType": "Fast månads- vecko- eller timlön","description": "Har du förståelse för att människor tar till sig kunskap på olika sätt ...","applyUrl": "https://norrkoping.se/jobba-hos-oss/sok-jobb/lediga-jobb?rmpage=job&rmjob=20019","url": "https://arbetsformedlingen.se/platsbanken/annonser/31686710","scrapedAt": "2026-11-04T17:03:47Z"}
| Field | Meaning |
|---|---|
jobId / sourceJobId | Stable ID (source prefix + the source's own ID). Use it to de-duplicate across scheduled runs. |
source / originalSource | NAV Arbeidsplassen, Arbetsförmedlingen Platsbanken or EURES, and where the ad was first published (e.g. NAV, FINN.no, Platsbanken, Työmarkkinatori (Finland), Jobnet (Denmark)). |
country / countryName | ISO country code and name. |
title | Ad headline as the employer wrote it. |
jobTitle | Standardized job title. Norway: the employer's job title field, or NAV's own classification (JANZZ/ESCO) when that field is empty. Sweden: the occupation from the JobTech taxonomy (e.g. Systemutvecklare/Programmerare). Finland/Denmark/Iceland: the ESCO occupation of the ad, in English (e.g. software developer). |
occupation | Broader occupation group. Norway: NAV category (e.g. Utvikling). Sweden: SSYK occupation group. EURES: ISCO group from ESCO (e.g. Software developers). |
company / companyId / companyWebsite | Employer name, organisation number (Norwegian orgnr, Swedish organisationsnummer, Finnish Y-tunnus, Danish CVR) and website, where available. |
location / city / municipality / region / postalCode / address | Workplace. For EURES, region holds NUTS region codes. |
postedAt / updatedAt / expiresAt | ISO 8601 timestamps in UTC. |
deadline | Application deadline as YYYY-MM-DD, or the source's text (e.g. Norwegian Snarest = as soon as possible). |
employmentType | full-time or part-time. |
contractType / contractTypeOriginal | Normalized (permanent, temporary, seasonal, ...) and original wording. |
salary / salaryType | None of the public Nordic job APIs publishes a structured salary amount. salaryType is Sweden's pay type (e.g. Fast månads- vecko- eller timlön = fixed monthly, weekly or hourly pay). salary is filled only when Platsbanken has a salary text, which is rare. NAV and EURES have no salary field; look in description. |
numberOfPositions, startDate, sector, occupationField | Extra details where the source provides them. |
summary, keywords, workLanguage | Norway: NAV's short summary, skill tags and working languages. |
description / descriptionHtml | Full ad text (plain text, plus HTML if enabled). |
applyUrl / url | Where to apply, and the public ad page. |
searchTerm, scrapedAt | The search term that found the job, and when it was scraped. |
Field coverage by source
| Field | Norway (NAV) | Sweden (Platsbanken) | Finland / Denmark / Iceland (EURES) |
|---|---|---|---|
jobTitle | always | always | most ads, about 85% (ESCO, English) |
occupation | always | always | most ads, about 85% (ISCO group) |
salaryType | - | always | - |
salary (amount text) | - | rare (0 of 400 in our tests) | - |
summary, keywords, workLanguage | yes | - | - |
description | only ads not imported from FINN.no (about 30% in our tests) | yes | yes |
A summary per country (jobs, duplicates skipped, filtered-out ads, keyword mismatches, errors, timing, plus the alert state, notification results and contactsRedacted counts) is saved to the key-value store as RUN_SUMMARY. Download the dataset as JSON, CSV, Excel, XML or HTML, or read it through the Apify API.
Job alerts (new jobs only)
Use the Actor as a job alert for Norway, Sweden, Finland, Denmark and Iceland. Save a search, run it on a schedule, and get only the new jobs since the last run, straight to Slack, your inbox or any webhook. It works for any role or city: "new developer jobs in Oslo", "new nursing jobs in Sweden", "new jobs in Helsinki", "Danish engineering jobs this week".
How it works
- Turn on
onlyNewJobsand give the alert a name inalertName(e.g.oslo-developers). - The Actor remembers the IDs of the jobs it returned in a named key-value store in your own Apify account (
nordic-jobs-alert-<alertName>). It keeps the latest ~50,000 job IDs per alert. - On every next run, jobs that the alert has already seen are skipped. They are not saved and not charged. Reposts of the same ad (same title, company and city with a new ID) are skipped too.
- When the run finds at least 1 new job, it sends a notification to the channels you set. When there is nothing new, the run succeeds with the status "No new jobs since the last run" and sends nothing.
The first run is the baseline. An alert with no history returns the current matching jobs (limited by postedWithinDays, maxItemsPerCountry and maxItems) and notifies about them, so you can check the alert works. It also remembers recent matching jobs beyond your limits, without returning or charging them, so the second run does not flood you with old jobs. From the second run on, you only get jobs that are new. Use postedWithinDays: 1 or 2 for the baseline if you don't want a big first batch.
Set up a daily job alert with an Apify Schedule
- Open this Actor in the Apify Console, fill in your search, turn on Only new jobs, set an Alert name and the notification channels, then click Save (or Save as a new task to keep several alerts).
- Go to Schedules → Create new, pick a time (e.g. every day at 07:00, cron
0 7 * * *, and choose your time zone, e.g. Europe/Oslo or Europe/Stockholm). - Under Actors and tasks, add this Actor or your saved task with the same input, and save the schedule.
Example input for a daily "new developer jobs in Norway and Sweden" alert:
{"countries": ["NO", "SE"],"searchTerms": ["developer", "utvikler", "utvecklare"],"postedWithinDays": 2,"maxItemsPerCountry": 200,"onlyNewJobs": true,"alertName": "nordic-developers","slackWebhookUrl": "https://hooks.slack.com/services/T000/B000/XXXX","emailTo": "my-apify-account-email@example.com","notifyTopN": 10}
Use one alertName per search. If you change the search terms or countries a lot, use a new name (or resetAlert: true once) so the alert starts a fresh baseline. Don't run two runs of the same alert at the same time.
Notification channels
- Slack job alerts: create an incoming webhook for your channel and paste it into
slackWebhookUrl. The message shows the number of new jobs, the newestnotifyTopNjobs with title, company, location, posted date, deadline and a link, plus links to the full dataset and the run. - E-mail job alerts: put the e-mail address of your Apify account into
emailTo. The e-mail is sent through Apify's officialapify/send-mailActor, which only delivers to the account owner's own address (to alert a team, use the Slack or webhook channel, or forward the e-mail). It starts a tiny extra run in your account. That run is billed as normal platform usage, typically well under $0.01 per e-mail, and only when there are new jobs. - Webhook (Zapier, Make, n8n, your API): set
webhookUrland receive a POST with JSON like this:
{"event": "nordic-jobs.jobs-found","alertName": "nordic-developers","isBaselineRun": false,"summary": "[nordic-developers] 12 new jobs for \"developer, utvikler, utvecklare\" in Norway, Sweden","jobCount": 12,"countries": { "NO": 7, "SE": 5 },"runId": "...", "runUrl": "https://console.apify.com/...","datasetId": "...", "datasetUrl": "https://console.apify.com/storage/datasets/...","jobsTruncated": false,"jobs": [{ "jobId": "platsbanken-31686710", "country": "SE", "title": "...", "company": "...", "location": "...","postedAt": "2026-11-04T16:39:15Z", "deadline": "2026-11-22", "employmentType": "full-time","contractType": "permanent", "applyUrl": "...", "url": "...", "source": "Arbetsförmedlingen Platsbanken", "searchTerm": "utvecklare" }],"createdAt": "2026-11-05T06:00:41Z"}
The webhook lists up to 500 jobs without descriptions. Read the full data from the dataset datasetId with the Apify API (https://api.apify.com/v2/datasets/<datasetId>/items). Failed notifications (e.g. an invalid Slack URL) are retried, then logged in the run log and in RUN_SUMMARY.notifications. They never fail the run, and your jobs are always in the dataset.
You can also use the notifications without onlyNewJobs. Then every run with results notifies about all jobs it found. Apify's own integrations (Slack, e-mail, Google Sheets, webhooks on the Integrations tab) work too, but they fire on every run, even when nothing is new.
Job alert limits
- After the baseline, each run looks at ads published since the last successful run of that country, minus a 24-hour safety margin. If you pause the schedule for a week, the next run still picks up everything published in between, as long as
postedWithinDays/postedAfterand your item limits allow it. LeavepostedWithinDaysempty for alerts if runs may be skipped. - If the run's maximum cost is reached, the remaining new jobs are not marked as seen. They come in the next run.
- A country added to an existing alert starts with its own baseline.
- An ad that the source edits keeps its ID, so it is not sent again.
Jobs API in Python
from apify_client import ApifyClientclient = ApifyClient("YOUR_APIFY_TOKEN")run = client.actor("tidy-data/nordic-jobs-scraper").call(run_input={"countries": ["NO", "SE", "FI", "DK"],"searchTerms": ["developer", "utvikler", "utvecklare"],"postedWithinDays": 7,"maxItemsPerCountry": 200,})for job in client.dataset(run["defaultDatasetId"]).iterate_items():print(job["country"], job["title"], job["company"], job["url"])
How much does it cost?
You pay $0.90 per 1,000 jobs saved to the dataset (pay per event, see the Pricing tab), plus a tiny per-run start fee. Platform usage is included in the price. Duplicates, ads removed by your filters, jobs a job alert has already seen and failed requests are never charged. A scheduled alert run with no new jobs costs only the start fee. You can cap spending with the run's maximum cost setting, and the Actor stops cleanly when the cap is reached.
Data sources and coverage
| Country | Source | Notes |
|---|---|---|
| 🇳🇴 Norway | NAV Arbeidsplassen (search + NAV's public job feed) | Norway's public job board, tens of thousands of open ads. |
| 🇸🇪 Sweden | Arbetsförmedlingen Platsbanken via the JobTech open-data API | Sweden's public job board. Full description in every ad. |
| 🇫🇮 Finland | EURES | Most ads come from Työmarkkinatori (the public Job Market Finland). |
| 🇩🇰 Denmark | EURES | Ads that Jobnet and Danish employers share with EURES (about 1,000-1,500 open ads). |
| 🇮🇸 Iceland | EURES | Small number of ads. |
Keyword matching
The job sites' own search is loose. EURES, for example, returns any ad whose text contains "develop" when you search for "developer", and NAV and Platsbanken match words anywhere in the ad. With the default keywordMatch: "title", every job is re-checked before it is stored, and jobs that do not match are dropped. You are not charged for dropped jobs.
- Case-insensitive, with plurals and Nordic endings:
nursematches "Nurses" and "Sjuksköterskor", but not "Nursery" or "Nursing home".developermatches "Developers" and "Backend-utvikler", but not "Business Development". - Compounds:
sykepleiermatches "Spesialsykepleier" and "Sykepleiervikar". - Common job words are matched across Nordic languages: developer = utvikler / utvecklare / kehittäjä / udvikler, nurse = sykepleier / sjuksköterska / sairaanhoitaja / sygeplejerske, and the same for engineer, teacher, electrician, driver, accountant, cook/chef, carpenter, cleaner, welder, mechanic, doctor and salesperson. Nynorsk forms are included.
developerdoes not match "business developer" or "property developer" (forretningsutvikler, affärsutvecklare, eiendomsutvikler), unless your term includes that word.- On EURES (Finland, Denmark, Iceland) the ESCO occupation is chosen by the employer. Some employers tag QA, ERP or project roles as "ICT application developer", and those ads match
developer. - Multi-word terms need every word:
java developermatches "Senior Java Developer" and "Java-utvecklare". - Terms with symbols (
C#,.NET,C++) are matched as plain text. fullTextalso checks the description. Ads without a description (FINN.no imports, orincludeDescriptionoff) are kept as the source returned them.- The job title check uses the ad title,
jobTitle,occupationand the source's occupation classification, so "Vil du jobbe med verdensledende droner?" is still found for "developer" when NAV classifies it as Programvareutvikler. - Each search is cut off after checking 10 ×
maxItemsPerCountrysearch results (at least 500), so a rare term cannot become a full crawl.RUN_SUMMARYshowskeywordMismatchper country. - The search itself still runs on each source. Platsbanken's search does not translate (
sykepleierfinds nothing in Sweden), so add the Swedish term (sjuksköterska). EURES does search across languages.
Limits you should know
- Norway, FINN.no ads: many ads on NAV Arbeidsplassen are imported from FINN.no. NAV's open feed does not redistribute their full text, so for these ads you get title, company, location, dates, deadline, NAV's short summary, skill tags and a link to the original ad, but
descriptionis empty. Turn onskipFinnImportedAdsif you only want full ads. - Denmark: coverage is the part of the Danish market that is published on EURES, not all of Jobindex.
- Deep paging: a single search returns up to about 10,000 jobs in Norway, 2,100 in Sweden and 10,000 per country on EURES. For bigger exports, split the run by search term or location.
- Location in Finland: Finnish EURES ads often have no structured city. The location is then matched in the ad text, including inflected forms such as "Tampereella".
Tips
- Daily job alert: turn on
onlyNewJobs, set analertNameand a Slack, e-mail or webhook channel, and schedule the Actor. See Job alerts. - Search in local languages: add the Norwegian, Swedish, Finnish and Danish job titles. Duplicates are removed automatically.
- Faster runs: turn off
includeDescriptionwhen you only need titles, companies and links. - Use it from AI agents: this Actor works with the Apify MCP server, so Claude, ChatGPT or Cursor agents can call it directly.
FAQ
Is there a NAV job API or an Arbetsförmedlingen API?
Yes, both are public, and this Actor uses them: NAV's job search and public job feed (pam-stilling-feed) for Norway, and the JobTech JobSearch API behind Platsbanken for Sweden. The Actor saves you from handling three different formats, paging limits and rate limits, and it adds keyword matching, de-duplication and job alerts.
Does it cover FINN.no, LinkedIn or Jobindex?
Not directly. Norwegian ads that FINN.no shares with NAV are included, without the full description. LinkedIn, Jobindex and other private job boards are not covered.
Does the output contain personal data?
The Actor never extracts contact persons into separate fields: there is no contact name, e-mail or phone field. The description field, however, is the full ad text written by the employer, and in a test sample of 415 ads about half of the ad texts contained a contact person's e-mail address or phone number.
By default (redactContacts: true) the Actor masks these before saving:
- Masked: e-mail addresses (also written as
name (at) firm.no) and phone numbers in Nordic and international formats (+47 412 34 567,0708-123456,040 123 4567,22 33 44 55,00 45 …) indescription,descriptionHtml,summary,title,salary,startDate,workplaceandkeywords. They become[email removed]and[phone removed]. IndescriptionHtml,mailto:andtel:links are emptied. - Kept:
applyUrl,url,originalAdUrl,companyWebsiteand every web address in the text, plus dates, times, salaries, years, postal codes, reference numbers and organisation numbers (companyId, CVR, org.nr., Y-tunnus). - Not masked: names. The ad text may still say who the contact person is, so treat the data as possibly containing personal data under the GDPR.
RUN_SUMMARY.contactsRedacted shows how many e-mails and phone numbers were masked. Masking is pattern-based. In our tests on 415 real ads, no e-mail address was left and no date, salary or ID number was masked, but an unusual format can slip through either way. Turn redactContacts off only if you need the contact details and have a lawful basis to process them. You can also drop the description: for Norway turn off includeDescription. Sweden, Finland, Denmark and Iceland return the description in the search results, so those ads always include it.
Is it legal to scrape job listings?
This Actor only collects public job ads through official, openly available APIs (NAV, JobTech/Arbetsförmedlingen and EURES), without logging in. Make sure your use complies with the GDPR, the sources' terms of use and other applicable laws. If you are unsure, consult a lawyer.
Support
Found a bug or need another country, source or field? Open an issue on the Issues tab. We monitor this Actor and fix breakages quickly.
More scrapers from Tidy Data
- Software Advice Reviews Scraper (Capterra Network): B2B software reviews with pros, cons, company size and vendor replies.
- App Store & Google Play Reviews Scraper: iOS and Android app reviews, multi-country, with developer replies.