Nationale Vacaturebank Scraper avatar

Nationale Vacaturebank Scraper

Pricing

from $1.50 / 1,000 results

Go to Apify Store
Nationale Vacaturebank Scraper

Nationale Vacaturebank Scraper

Scrape 105,000+ listings from Nationale Vacaturebank — the #1 Dutch job board. Structured output: title, company, salary, contract type & full descriptions (HTML, text, Markdown). Deduplication, repost detection & daysOld filtering. No API key required.

Pricing

from $1.50 / 1,000 results

Rating

0.0

(0)

Developer

Unfenced Group

Unfenced Group

Maintained by Community

Actor stats

1

Bookmarked

23

Total users

9

Monthly active users

12 hours ago

Last modified

Share

Nationale Vacaturebank Scraper

Extract structured job listings from Nationale Vacaturebank — the largest Dutch job board with 100,000+ active vacancies. Filter by keyword, city, radius, contract type, education level, career level, and industry. Every result includes a full job description in HTML, plain text, and Markdown.

No API key required. No login. Runs entirely in the cloud.


What You Get

Every scraped record contains 28 structured fields:

CategoryFields
Identityid, referenceId, url, originalUrl
Job basicstitle, functionTitle, categories, industries
Employercompany, companyType (direct_employer / intermediary)
Locationcity, municipality, zipCode, province, latitude, longitude
Salarysalary (display text), salaryMin, salaryMax, salaryType
Hourshours (display text), hoursMin, hoursMax
ContractcontractType, educationLevel, careerLevel
Descriptiondescription (HTML), descriptionText, descriptionMarkdown
DatespublishDate, expiryDate, originalPublishDate, scrapedAt
SignalsisRepost, numberOfApplies, changeStatus, contentHash

Sample Output

{
"id": "16c66447-14f9-442c-ba7b-87469b45764e",
"title": "Assistent Teamleider Logistiek",
"url": "https://www.nationalevacaturebank.nl/vacature/16c66447-.../assistent-teamleider-logistiek",
"company": "Active Ants",
"companyType": "direct_employer",
"city": "Roosendaal",
"municipality": "ROOSENDAAL",
"zipCode": "4701AA",
"province": "Noord-Brabant",
"latitude": 51.532954,
"longitude": 4.458893,
"salary": "vanaf €3.054",
"salaryMin": 3054,
"salaryMax": 3054,
"salaryType": "monthly",
"hours": "40 - 40 uur",
"hoursMin": 40,
"hoursMax": 40,
"contractType": "Tijdelijk",
"educationLevel": "MBO",
"careerLevel": "Ervaren",
"functionTitle": "Assistent Teamleider Logistiek",
"categories": ["Inkoop/Logistiek/Transport"],
"industries": ["Industrie"],
"publishDate": "2026-02-27",
"expiryDate": "2026-04-28",
"isRepost": true,
"originalPublishDate": "2026-02-27",
"numberOfApplies": 2,
"description": "<p>Ben jij de gedreven Assistent Teamleider...</p>",
"descriptionText": "Ben jij de gedreven Assistent Teamleider...",
"descriptionMarkdown": "Ben jij de gedreven Assistent Teamleider...",
"scrapedAt": "2026-05-19T09:00:00.000Z",
"contentHash": null,
"changeStatus": null
}

Input Parameters

ParameterTypeDefaultDescription
searchQuerystringJob title or keyword, e.g. developer, marketing manager
citystringCity to search in, e.g. Amsterdam, Rotterdam, Utrecht
radiusselect40Search radius around city in km: 5, 10, 20, 30, 40, 50, 75, 100
contractTypeselectallfulltime, parttime, freelance, tijdelijk, stage, bijbaan
educationLevelselectallvmbo, mbo, hbo, wo
careerLevelselectallstarter, junior, medior, senior, manager, directie
industrystringFree-text industry filter, e.g. IT, Zorg, Logistiek
maxResultsinteger5Max listings to return (1–5000). Controls cost.
maxPagesInputintegerautoOverride auto-calculated page count (~12 results/page).
fetchDetailsbooleanfalseVisit each listing page for the full description and precise publish date. Slower but richer.
debugModebooleanfalseSave screenshots and raw HTML to Key-Value Store for debugging.

Filter Value Reference

contractType

ValueLabel
fulltimeFulltime
parttimeParttime
freelanceFreelance / ZZP
tijdelijkTijdelijk
stageStage
bijbaanBijbaan

educationLevel

ValueLabel
vmboVMBO
mboMBO
hboHBO
woWO / Universiteit

careerLevel

ValueLabel
starterStarter
juniorJunior
mediorMedior
seniorSenior
managerManager
directieDirectie

Use Cases

Labour market research Pull vacancies across all regions and sectors. The structured salaryMin/salaryMax, educationLevel, and careerLevel fields enable quantitative salary analysis and supply/demand mapping per province or city.

Recruitment pipeline intelligence Track competitor job postings, monitor how long roles stay live (publishDate vs expiryDate), detect reposts (isRepost), and measure candidate interest (numberOfApplies).

Job alert and aggregation services Schedule the actor daily or hourly via Apify's scheduler. Feed new listings into your own database, Slack, or email notification system using the Apify API or webhooks.

HR and workforce analytics Combine latitude/longitude with your own workforce data for commute analysis, territory planning, or regional hiring benchmarks.

ATS and job board integrations The three description formats (description, descriptionText, descriptionMarkdown) make it straightforward to ingest into any ATS, CMS, or data warehouse without transformation.


Performance & Cost

VolumeDurationCompute UnitsEst. Cost
100 results~11 sec~0.012 CU~$0.15
500 results~53 sec~0.060 CU~$0.75
1,000 results~105 sec~0.120 CU~$1.50
5,000 results~9 min~0.600 CU~$7.50

Benchmarks measured at 256 MB RAM. The actor uses a pure HTTP architecture (no browser) — it is fast and cost-efficient by design.


Pricing

Pay-per-result — you only pay for data you actually receive.

ItemPrice
Per result$0.0015
Per 1,000 results$1.50
Actor start$0.00005 (one-time, per run)

No subscription. No minimum. Runs cost nothing if no results are returned.


API Integration

Run the actor programmatically and retrieve results with the Apify API:

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_API_TOKEN' });
const run = await client.actor('unfenced-group/nationale-vacaturebank-scraper').call({
searchQuery: 'developer',
city: 'Amsterdam',
radius: '20',
contractType: 'fulltime',
educationLevel: 'hbo',
careerLevel: 'medior',
maxResults: 500,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(`Scraped ${items.length} jobs`);

Scheduled Daily Export

// Create a schedule via Apify API — runs every morning at 07:00 CET
const schedule = await client.schedules().create({
name: 'nationale-vacaturebank-daily',
cronExpression: '0 6 * * *',
isEnabled: true,
actions: [{
type: 'RUN_ACTOR',
actorId: 'unfenced-group/nationale-vacaturebank-scraper',
runInput: {
searchQuery: 'software engineer',
city: 'Utrecht',
maxResults: 200,
},
}],
});

Python Example

from apify_client import ApifyClient
client = ApifyClient(token="YOUR_API_TOKEN")
run = client.actor("unfenced-group/nationale-vacaturebank-scraper").call(run_input={
"searchQuery": "data analyst",
"city": "Rotterdam",
"educationLevel": "hbo",
"maxResults": 100,
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
print(item["title"], "|", item["company"], "|", item.get("salaryMin"))

Tips for Large-Scale Scraping

Segment by city to maximise coverage Nationale Vacaturebank returns up to ~5,000 results per search. For national coverage without limits, run parallel searches across the major cities: Amsterdam, Rotterdam, Utrecht, Den Haag, Eindhoven, Groningen, Tilburg, Almere, Breda, Nijmegen.

Use maxResults to control cost Set maxResults conservatively during testing. Increase once your pipeline is validated.

Enable fetchDetails only when you need it The default list view already includes full job descriptions parsed from the search response. Enable fetchDetails: true only if you need the precise publication timestamp to the minute or want to guarantee you capture description fields not always present in the search response.

Deduplication via id or contentHash Use the id field (UUID) as your primary key. The contentHash field (populated when fetchDetails is enabled) lets you detect whether a relisted vacancy has changed its content.

Detect reposts with isRepost + originalPublishDate Vacancies relisted by the same employer carry isRepost: true. Compare publishDate with originalPublishDate to determine how many times a role has been recycled and for how long.


Technical Notes

  • Architecture: Pure HTTP with Cheerio — no browser, no Playwright. Fast and lightweight.
  • Memory: Default 256 MB. No adjustment needed for standard use.
  • Proxy: Datacenter proxies. The site does not require residential proxies or session management.
  • Rate limits: The actor respects the site's natural pagination rate. No artificial delays.
  • Robots.txt: Scrapes publicly accessible search results pages only.

FAQ

Does this require a Nationale Vacaturebank account? No. The actor scrapes publicly accessible listings without authentication.

How fresh is the data? The data reflects what is live on the site at the moment of the run. Schedule the actor to keep your dataset current.

Can I filter by multiple cities or contract types at once? The actor supports one filter combination per run. For multi-city or multi-filter collection, run multiple parallel instances via the Apify API.

Why does descriptionText look shorter than description? The HTML description is the full source. descriptionText strips all tags and normalises whitespace. descriptionMarkdown converts lists and headings. All three contain the same underlying content.

The salary field is sometimes null — why? Salary disclosure is optional on Nationale Vacaturebank. When an employer does not publish a salary, all salary fields (salary, salaryMin, salaryMax, salaryType) will be null.