Arbeidsplassen NAV Job Scraper — Norway Job Leads
Pricing
from $1.20 / 1,000 per job ad returneds
Arbeidsplassen NAV Job Scraper — Norway Job Leads
Scrape Norway's national NAV job board arbeidsplassen.nav.no: title, employer, county, occupation, dates and NAV's own AI summary, plus org number, apply link, ATS vendor and named contact e-mail/phone from the ad page. 12,400+ live ads, ~550 new per day. No login.
Pricing
from $1.20 / 1,000 per job ad returneds
Rating
0.0
(0)
Developer
Scrapers Delight
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
3 days ago
Last modified
Categories
Share
🇳🇴 Arbeidsplassen (NAV) Job Scraper — Norway's national vacancy board
Scrape arbeidsplassen.nav.no, the public job board run by NAV (the Norwegian Labour and Welfare Administration) — the one register where Norwegian vacancies from FINN, from every major applicant-tracking system, and from employers typing straight into NAV all land in the same place.
One row per ad, up to 76 fields: employer, Norwegian organisation number, county and municipality, occupation, employment type, dates — plus, from the ad page, the apply link, the ATS vendor behind it, and the named contact person with their direct e-mail and phone.
What does this actor do?
- 📋 Sweeps the whole live board — 13,475 live ads measured 2026-09-04 08:10 UTC (12,471 six hours earlier the same day — the board moves), and it is a flow, not a stock: 4,385 ads published in the last 7 days (~626/day, ~19,000/month).
- 🏢 Puts an org number on the row — the join key to Brreg, Norway's company register, so every lead can be enriched with revenue, employee count and directors.
- 🔌 Names the ATS — derived from the apply-link hostname:
webcruiter,visma-talent,jobbnorge,teamtailor,recman,easycruit,finn.no… This is the competitive-displacement list, andonlyDirectPostedgives you the opposite: employers hiring with no recruiting software at all. - ☎️ Named contact, not a careers inbox — NAV's ads carry a real person: name, job title, direct phone, direct e-mail.
- 🤖 Free AI enrichment — NAV runs its own model over every ad and publishes the result: a one-paragraph
short_summaryand a skill-tag list. Both come back at ~100% fill, at no extra cost. - 🧭 63 input options, and every filter that NAV's own API silently ignores (municipality, occupation sub-category, summer job, city, postal code) is applied over the rows here instead of pretending to work.
- 🔁 Incremental monitoring — give a run a
stateKeyand it remembers every ad UUID it has delivered, so the next run only returns (and only bills) genuinely new vacancies.
Who buys this data
| Buyer | The row they pay for |
|---|---|
| ATS / recruiting-software vendors (Webcruiter, Visma, Teamtailor, Jobbnorge, ReachMee) | ats_vendor = the competitor's install base, with a named contact and a live hiring need. onlyDirectPosted: true = the greenfield list. |
| Staffing & recruitment agencies | An employer who is hiring right now, filtered to their county and occupation, with the deadline and the person to ring. |
| B2B sellers into growing companies (payroll, onboarding, insurance, workwear, IT, office) | A new vacancy is a growth signal; org_number makes it a CRM-ready account. |
| Labour-market analysts and salary benchmarks | STYRK08 / ESCO / JANZZ occupation codes, county, sector, extent and education requirements on 12,000+ live ads. |
| International recruiters / relocation | workLanguage: ["Engelsk"] — 2,717 live ads where Norwegian is not required. |
Quick start
Every nurse vacancy in Oslo and Viken, with the org number and the contact person:
{"occupationCategories": ["Helse og sosial"],"occupationSubCategories": ["Sykepleier"],"counties": ["OSLO", "AKERSHUS"],"fetchDetails": true,"requireOrgnr": true,"maxItems": 500}
Competitive displacement — everyone in Norway running Webcruiter:
{ "fetchDetails": true, "atsVendorInclude": ["webcruiter"], "maxItems": 1000 }
The greenfield list — employers hiring with no third-party ATS at all:
{ "fetchDetails": true, "onlyDirectPosted": true, "requireContactEmail": true, "maxItems": 500 }
A daily monitor that only ever bills you for new ads:
{ "counties": ["VESTLAND"], "publishedWithin": "now-3d", "stateKey": "vestland-daily", "maxItems": 0 }
Or just paste a search URL out of NAV's own site — including the municipality and occupation filters their API ignores:
{ "startUrls": ["https://arbeidsplassen.nav.no/stillinger?county=VESTLAND&municipal=VESTLAND.BERGEN&q=utvikler"] }
Output
{"uuid": "07823086-c85c-4c8e-b73f-1b0dedbd772a","ad_url": "https://arbeidsplassen.nav.no/stillinger/stilling/07823086-c85c-4c8e-b73f-1b0dedbd772a","title": "Mulighetsrom til å påvirke veksten til Payments.","job_title": "Junior Sales Executive Payments","employer_name": "SVEA FINANS AS","org_number": "980130169","employer_sector": "Privat","employer_homepage": "https://www.svea.com/no/nb/start/","county": "OSLO", "municipal": "OSLO", "city": "OSLO","postal_code": "0663", "address": "Innspurten 15", "country": "NORGE","occupation_level1": "Salg og service","occupation_level2": "Salg, butikk- og varehandel","category_styrk08": "Salgs- og markedssjefer","engagement_type": "Fast", "extent": "Heltid", "position_count": 1,"published": "2026-09-04T07:48:21+02:00","expires": "2026-09-12T00:00:00+02:00","application_due": "2026-09-12", "application_due_asap": false,"apply_url": "https://www.finn.no/job-apply/475024396/apply","apply_host": "finn.no", "ats_vendor": "finn.no", "is_direct_posted": false,"contact_name": "Morten Leknes","contact_title": "Avdelingsleder","contact_email": "morten.leknes@example.no","contact_phone": "(+47) 90920664","short_summary": "Stillingen innebærer løsningsorientert salg, prospektering, og kundekontakt…","ai_tags": "Betalingsløsninger; Forretningsutvikling; Kundeservice; SMB; Salg","ad_text": "…the full ad body, HTML stripped…","detail_fetched": true}
Measured field fill
Validated offline against live bytes on 2026-09-04. These are the numbers from the actual runs, not estimates.
Listing sweep — 1,950 ads, 1,950 unique, no ad-page enrichment:
| Field | Fill |
|---|---|
uuid, ad_url, title, employer_name, business_name | 100% |
status, source, medium, reference, published, expires | 100% |
county, country, locations, locations_count | 100% |
occupation_level1, occupation_level2, occupations | 100% |
short_summary (NAV's AI summary), ai_tags, ai_under18_reason | 100% |
experience, need_drivers_license, under18 | 100% |
categories, category_styrk08, education | 99.9% |
search_tags | 99.8% |
application_due_raw | 98.3% |
municipal | 97.3% |
work_language | 97.2% |
city, postal_code | 93.2% |
job_title | 80.1% |
address | 77.3% |
application_due (a parsed date) | 72.0% |
keywords | 53.7% |
remote (on the listing; the ad page fills it to 100%) | 26.1% |
Of those 1,950 ads, 26% carry no fixed deadline at all — NAV's deadline field says Snarest ("as soon as possible"), which this actor exposes as application_due_asap: true rather than throwing away. Source mix on the same sample: IMPORTAPI (pushed by an ATS) 60%, FINN 24%, Stillingsregistrering (typed straight into NAV by the employer) 16%, AMEDIA 0.4%.
With fetchDetails: true — two independent 150-ad runs, ad page fetched for each, 75 fields on the row.
Column A is the offline validation run; column B is a run on the Apify platform the same day against a
different slice of the board. Both are shown because the ad-page fields genuinely vary with which ads you pull —
quote the lower number when you plan a campaign, not the higher one.
| Field | A (offline) | B (platform) | Note |
|---|---|---|---|
detail_fetched | 100% | 100% | the ad page parsed on 150/150 in both runs |
ad_text, position_count, engagement_type, extent, updated, remote | 100% | 100% | all six are absent from the search API |
ai_is_summer_job, ai_work_experience | 100% | 100% | NAV's own classification |
categories, category_styrk08 | 100% | 99.3% | |
org_number | 100% | 90.0% | the Brreg join key |
employer_sector | 98.7% | 97.3% | |
is_direct_posted | 96.0% | 97.3% | null only when the ad has no apply route at all |
apply_url, apply_host, ats_vendor | 89.3% | 93.3% | the rest apply by e-mail or have no link |
search_tags | 100% | 90.7% | |
job_title | — | 86.0% | |
application_due (a parsed date) | 71.3% | 76.0% | the remainder are "Snarest" → application_due_asap |
employer_homepage | 71.3% | 72.7% | |
contacts_count / contact_name | 65.3% / 63.3% | 67.3% / 64.7% | not every ad names a person |
employer_description | 59.3% | 57.3% | |
contact_phone | 54.0% | 58.0% | |
contact_title | 53.3% | 56.7% | |
contact_email | 34.0% | 25.3% | plan on one ad in four, not one in three |
source_url | 36.0% | 34.0% | link to the original posting off-NAV |
start_date | 26.0% | 26.0% | |
work_hours / work_days | 21.3% / 18.7% | 17.3% / 13.3% | |
has_superrask_soknad | 10.7% | 6.7% | the flag is simply absent on most ads |
apply_email | 6.7% | 4.0% | |
employer_facebook / employer_linkedin | 6.7% / 1.3% | 3.3% / 0.7% | employers rarely fill these in |
employer_twitter, job_percentage | 0% | 0% | the fields exist on NAV's object and are essentially never populated — reported honestly rather than quietly dropped |
Be honest with yourself about the contact fields. About two thirds of NAV's ads name a person, a bit over half publish a direct phone, and a quarter to a third publish an e-mail (34.0% and 25.3% on the two 150-ad samples above). If your workflow needs one on every row, set requireContactEmail: true and pay only for the rows that have it — the actor drops the rest before billing.
Reliability, measured
| Test | Result |
|---|---|
| Transport ladder (all through Apify proxies) | direct 200 · datacenter 200 · residential-NO 200 · residential-US 200 · residential-any 200 — the cheapest rung works, and it is not geo-blocked |
| Sustained search (varied filters and page offsets) | 56 / 57 usable = 98.2% |
| Sustained ad-page fetch | 20 / 20 = 100% |
| Contiguous paging, crawled the way the actor crawls | 20 pages × 100 from from=0 to 1900 → 2,000 fetched, 2,000 unique, 0 duplicates, 0.00% loss |
| Dedupe proof (offline) | the same search fed twice → 714 rows / 714 unique; with deduplicate:false → 1,428 rows / 714 unique |
| Dedupe proof (on Apify, billing checked) | the same NAV search URL passed twice → 9 rows delivered, job-scraped charged 9; the same run with deduplicate:false → 18 delivered, 18 charged. A duplicate ad is never billed twice unless you explicitly ask for it |
| Two different inputs → two different result sets | county=TROMS vs county=ROGALAND: 60 + 60 rows, overlap 0; sykepleier vs elektriker: overlap 0 |
| Ad-page parse over a 150-ad enrichment run | 150 / 150 parsed |
| Live platform runs | 19 runs, 19 SUCCEEDED, 0 failed and 0 timed out (13 on build 0.1.1, 6 on 0.1.2), worst wall-clock 123.9 s against Apify's 300 s limit; chargedEventCounts equals the delivered row count on every single one |
| Offline validation suite | 48 checks, 48 pass — every filter asserted against the rows it returned, plus dedupe, incremental state, the empty-input badge preflight and the zero-match clean exit |
The only residual failure mode is not NAV: the Apify proxy tunnel answers 595 on roughly 2-3% of calls. Every request is wrapped in a retry with a fresh proxy session, which converts it to ~100%.
The three things about NAV's API that break naive scrapers
They are all in the code with the measurement next to them, and they are worth knowing if you are evaluating other actors on this site:
sizeis honoured at 100 and nowhere else. 1, 5, 10, 20, 25, 30, 40, 50, 75, 99, 101 and 200 all silently return 25 rows. A pagination loop written asfrom += sizewithsize=50therefore skips every other page — it loses half the corpus and still finishes green.- The result window is
from + size ≤ 10000.from=9900is fine;from=9901returns HTTP 400 "Pagination depth exceeds maximum allowed window". The board runs ~12,500–13,500 ads (12,471 and 13,475 measured six hours apart on 2026-09-04), so a full sweep is impossible in one query. This actor slices by county (largest slice: OSLO, 2,185) and then by occupation if a slice is still too deep, sweeps the ads located abroad through the country facet (measured today: 35 ads across 16 countries, DANMARK 5 / SVERIGE 6 / ISLAND 6 / SVEITS 4 / …) — they have no Norwegian county and would otherwise vanish — and deduplicates on ad UUID, because NAV counts a multi-county ad once per county (the county slices sum to 13,008 against a 12,460 corpus). - Five filter parameters are accepted and silently ignored.
municipal/municipals/municipality/kommune,occupationLevel2,summerJob,postcodeandcitynever move the hit count, in any value shape. This actor does not pretend otherwise: those are applied over the rows after fetching, including when they appear in astartUrlslink pasted from NAV's own UI.
Server-side vs client-side filters
Applied by NAV (cheap, narrows the fetch): keyword, counties, countries, occupation categories, published-within (only today / 3 days / 7 days exist), sort, employment type, full/part-time, sector, education, experience, working language, remote, driving licence, under-18, quick-apply.
Applied by this actor over the rows: municipalities, occupation sub-categories, cities, postal codes and prefixes, exact published/expiry/deadline date ranges, title include/exclude, ad-text keywords, employer include/exclude, staffing-agency blocklist, ad source, ATS vendor, direct-posted-only, summer jobs, position count, and the lead-quality gates (requireOrgnr, requireContactEmail, requireContactPhone, requireApplyLink).
Filters that can only be decided from the ad page refuse to run without fetchDetails rather than silently doing nothing.
Pricing
Pay-per-event, no subscription, no platform-usage surcharge.
| Event | Price | When it fires |
|---|---|---|
job-scraped | $1.20 / 1,000 ads | once per unique ad delivered — after deduplication and after your filters, so you never pay for a row you did not receive |
job-detail-enriched | $2.50 / 1,000 ads | only with fetchDetails: true, and only for rows that really came back enriched |
A full sweep of the live board with everything on is 13,475 × $0.0037 ≈ $50; keeping it fresh on new ads only (~19,000 ads/month at the measured 4,385-per-week rate) is about $70/month. Listing-only, the whole board is $16.
Rows are charged through Apify's budget-aware push, so if you cap a run's spend you receive exactly the rows you paid for — never more delivered than billed, and never a duplicate billed twice.
Input reference — the options that matter
| Input | What it does |
|---|---|
query | free-text keyword, Norwegian (sykepleier, utvikler, elektriker) |
counties / municipalities | county is server-side and cheap; municipality is client-side because NAV's API ignores it |
occupationCategories / occupationSubCategories | NAV's two-level occupation taxonomy |
startUrls | paste searches straight from NAV's website; municipal= and occupationLevel2= are translated |
adUrls | skip the search, fetch named ads by URL or UUID |
fetchDetails | the second surface: org number, apply link, ATS vendor, contact person, ad text |
requireOrgnr / requireContactEmail / requireContactPhone / requireApplyLink | lead-quality gates — filtered rows are never billed |
atsVendorInclude / atsVendorExclude / onlyDirectPosted | the recruiting-stack angle |
excludeStaffingAgencies | drops bemanning / vikarbyrå / rekruttering employers |
stateKey | incremental monitoring in a named key-value store |
maxItems | the hard cap on rows delivered and billed; 0 = the whole board |
flattenOutput | flat CRM-ready rows (default) vs nested arrays |
includeRawSource | attaches NAV's untouched _source and adData objects |
FAQ
Is this the same as scraping FINN.no?
No. FINN is Norway's commercial classifieds site; arbeidsplassen.nav.no is the state board. A large share of NAV's ads are syndicated from FINN (source: "FINN"), but NAV also carries ads pushed by ATS vendors and ads typed directly into NAV by small employers who never advertise anywhere else. sourceExclude: ["FINN"] gives you the non-FINN half.
Do I need a NAV API token? No. This actor reads the site's own public search endpoint and its public ad pages. NAV also offers a registered, token-gated ad feed for high-volume integrators; if you have one, it is a different product and this actor does not use it.
How fresh is the data?
NAV publishes continuously — 98 ads on the morning this was measured, 2,109 in the previous 3 days. publishedWithin: "now/d" plus a stateKey gives you a same-day feed.
Why does the ad page cost extra?
Because it is a second HTTP request per ad. The search API simply does not contain the org number, the apply link or the contact person — measured 0.0% fill on all of them across 402 listing rows. If you only need the vacancy itself, leave fetchDetails off and pay the listing rate.
Will it return every ad on the board?
Yes, with maxItems: 0 and autoSliceCorpus: true (the default). The run log prints NAV's own reported total next to the delivered-unique count and flags the delta, so you can see the coverage rather than trust it.
What happens if my filters match nothing? The run finishes successfully with zero rows and a log line telling you so. It only fails when it genuinely could not read NAV — a broken run and an empty one must not look the same.
Can I get the raw NAV objects?
includeRawSource: true attaches raw_source (the Elasticsearch _source) and raw_detail (NAV's own adData). includeEmbeddingVector: true adds the 256-float compositeAdVector NAV publishes for semantic matching.
Can it run on a schedule?
Yes — set a stateKey, schedule it, and each run delivers and bills only ads it has never delivered before.
Legal & fair use
https://arbeidsplassen.nav.no/robots.txtisUser-agent: */Disallow:— an explicit allow-all, plus a sitemap. This actor reads only public pages and the site's own unauthenticated search endpoint. No login, no token, no signature, no CAPTCHA, and nothing that circumvents an access control.- Requests are proxied, retried politely and rate-limited by
requestDelayMsandmaxConcurrency. Leave the defaults unless you have a reason. - Personal data.
contact_name,contact_emailandcontact_phoneare real individuals' work contact details, published by their employer in a job ad. Norway is in the EEA, so the GDPR applies: you need a lawful basis to process them, and the obligations around information, retention and erasure are yours, not this actor's. If you do not need them, leavefetchDetailsoff or drop the columns. - Fair use, respect NAV's terms, and check your own compliance position before you build a marketing list on top of this.
Built and measured 2026-09-04 against the live site. Every number on this page came from a run, not from a guess.