Nordic Jobs Scraper & Alerts: Norway, Sweden, Finland, Denmark avatar

Nordic Jobs Scraper & Alerts: Norway, Sweden, Finland, Denmark

Pricing

from $0.90 / 1,000 jobs

Go to Apify Store
Nordic Jobs Scraper & Alerts: Norway, Sweden, Finland, Denmark

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

Tidy Data

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Categories

Security

Limited permissions

Share

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

FieldDescription
countriesAny of NO, SE, FI, DK, IS. Default: Norway, Sweden, Finland and Denmark.
searchTermsKeywords, 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.
keywordMatchHow 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.
locationOptional city, municipality or region, e.g. Oslo, Bergen, Göteborg, Tampere, Aarhus. Select the matching country for best results.
postedWithinDaysOnly jobs published in the last N days, e.g. 1 for a daily schedule.
postedAfterOptional YYYY-MM-DD. Only jobs published on or after this date.
maxItemsPerCountryStop after this many jobs per country. Default 100. 0 = all available.
maxItemsOptional cap for the whole run. 0 = no cap.
includeDescriptionFetch 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).
includeDescriptionHtmlAlso return the original HTML description. Default off.
dedupeByTitleAndCompanyRemove reposted ads with the same title, company and city. Default on.
skipFinnImportedAdsNorway only: skip ads that NAV imports from FINN.no, which come without a full description (see Limits). Default off.
redactContactsReplace e-mail addresses and phone numbers in the ad texts with [email removed] / [phone removed] (see Personal data). Default on.
onlyNewJobsJob alert mode: return only jobs that previous runs of the same alert have not returned yet. See Job alerts. Default off.
alertNameName of the alert, e.g. oslo-developers. Each name keeps its own memory of seen jobs. Use one name per search.
resetAlertForget the jobs this alert has seen and start a new baseline. Default off.
webhookUrlPOST a JSON summary plus the job list to this URL when the run finds at least 1 job (Zapier, Make, n8n, your own API).
slackWebhookUrlSlack incoming webhook URL. Posts a message with the newest jobs and links when the run finds at least 1 job.
emailToSend 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.
notifyTopNHow many jobs to list in the Slack message and e-mail. Default 10, max 40.
proxyConfigurationApify 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"
}
FieldMeaning
jobId / sourceJobIdStable ID (source prefix + the source's own ID). Use it to de-duplicate across scheduled runs.
source / originalSourceNAV 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 / countryNameISO country code and name.
titleAd headline as the employer wrote it.
jobTitleStandardized 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).
occupationBroader occupation group. Norway: NAV category (e.g. Utvikling). Sweden: SSYK occupation group. EURES: ISCO group from ESCO (e.g. Software developers).
company / companyId / companyWebsiteEmployer name, organisation number (Norwegian orgnr, Swedish organisationsnummer, Finnish Y-tunnus, Danish CVR) and website, where available.
location / city / municipality / region / postalCode / addressWorkplace. For EURES, region holds NUTS region codes.
postedAt / updatedAt / expiresAtISO 8601 timestamps in UTC.
deadlineApplication deadline as YYYY-MM-DD, or the source's text (e.g. Norwegian Snarest = as soon as possible).
employmentTypefull-time or part-time.
contractType / contractTypeOriginalNormalized (permanent, temporary, seasonal, ...) and original wording.
salary / salaryTypeNone 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, occupationFieldExtra details where the source provides them.
summary, keywords, workLanguageNorway: NAV's short summary, skill tags and working languages.
description / descriptionHtmlFull ad text (plain text, plus HTML if enabled).
applyUrl / urlWhere to apply, and the public ad page.
searchTerm, scrapedAtThe search term that found the job, and when it was scraped.

Field coverage by source

FieldNorway (NAV)Sweden (Platsbanken)Finland / Denmark / Iceland (EURES)
jobTitlealwaysalwaysmost ads, about 85% (ESCO, English)
occupationalwaysalwaysmost ads, about 85% (ISCO group)
salaryType-always-
salary (amount text)-rare (0 of 400 in our tests)-
summary, keywords, workLanguageyes--
descriptiononly ads not imported from FINN.no (about 30% in our tests)yesyes

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

  1. Turn on onlyNewJobs and give the alert a name in alertName (e.g. oslo-developers).
  2. 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.
  3. 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.
  4. 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

  1. 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).
  2. 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).
  3. 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 newest notifyTopN jobs 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 official apify/send-mail Actor, 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 webhookUrl and 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 / postedAfter and your item limits allow it. Leave postedWithinDays empty 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 ApifyClient
client = 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

CountrySourceNotes
🇳🇴 NorwayNAV Arbeidsplassen (search + NAV's public job feed)Norway's public job board, tens of thousands of open ads.
🇸🇪 SwedenArbetsförmedlingen Platsbanken via the JobTech open-data APISweden's public job board. Full description in every ad.
🇫🇮 FinlandEURESMost ads come from Työmarkkinatori (the public Job Market Finland).
🇩🇰 DenmarkEURESAds that Jobnet and Danish employers share with EURES (about 1,000-1,500 open ads).
🇮🇸 IcelandEURESSmall 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: nurse matches "Nurses" and "Sjuksköterskor", but not "Nursery" or "Nursing home". developer matches "Developers" and "Backend-utvikler", but not "Business Development".
  • Compounds: sykepleier matches "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.
  • developer does 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 developer matches "Senior Java Developer" and "Java-utvecklare".
  • Terms with symbols (C#, .NET, C++) are matched as plain text.
  • fullText also checks the description. Ads without a description (FINN.no imports, or includeDescription off) are kept as the source returned them.
  • The job title check uses the ad title, jobTitle, occupation and 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 × maxItemsPerCountry search results (at least 500), so a rare term cannot become a full crawl. RUN_SUMMARY shows keywordMismatch per country.
  • The search itself still runs on each source. Platsbanken's search does not translate (sykepleier finds 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 description is empty. Turn on skipFinnImportedAds if 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 an alertName and 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 includeDescription when 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 …) in description, descriptionHtml, summary, title, salary, startDate, workplace and keywords. They become [email removed] and [phone removed]. In descriptionHtml, mailto: and tel: links are emptied.
  • Kept: applyUrl, url, originalAdUrl, companyWebsite and 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.

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