Nationale Vacaturebank Scraper
Pricing
from $1.50 / 1,000 results
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
Maintained by CommunityActor stats
1
Bookmarked
23
Total users
9
Monthly active users
12 hours ago
Last modified
Categories
Share

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:
| Category | Fields |
|---|---|
| Identity | id, referenceId, url, originalUrl |
| Job basics | title, functionTitle, categories, industries |
| Employer | company, companyType (direct_employer / intermediary) |
| Location | city, municipality, zipCode, province, latitude, longitude |
| Salary | salary (display text), salaryMin, salaryMax, salaryType |
| Hours | hours (display text), hoursMin, hoursMax |
| Contract | contractType, educationLevel, careerLevel |
| Description | description (HTML), descriptionText, descriptionMarkdown |
| Dates | publishDate, expiryDate, originalPublishDate, scrapedAt |
| Signals | isRepost, 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
| Parameter | Type | Default | Description |
|---|---|---|---|
searchQuery | string | — | Job title or keyword, e.g. developer, marketing manager |
city | string | — | City to search in, e.g. Amsterdam, Rotterdam, Utrecht |
radius | select | 40 | Search radius around city in km: 5, 10, 20, 30, 40, 50, 75, 100 |
contractType | select | all | fulltime, parttime, freelance, tijdelijk, stage, bijbaan |
educationLevel | select | all | vmbo, mbo, hbo, wo |
careerLevel | select | all | starter, junior, medior, senior, manager, directie |
industry | string | — | Free-text industry filter, e.g. IT, Zorg, Logistiek |
maxResults | integer | 5 | Max listings to return (1–5000). Controls cost. |
maxPagesInput | integer | auto | Override auto-calculated page count (~12 results/page). |
fetchDetails | boolean | false | Visit each listing page for the full description and precise publish date. Slower but richer. |
debugMode | boolean | false | Save screenshots and raw HTML to Key-Value Store for debugging. |
Filter Value Reference
contractType
| Value | Label |
|---|---|
fulltime | Fulltime |
parttime | Parttime |
freelance | Freelance / ZZP |
tijdelijk | Tijdelijk |
stage | Stage |
bijbaan | Bijbaan |
educationLevel
| Value | Label |
|---|---|
vmbo | VMBO |
mbo | MBO |
hbo | HBO |
wo | WO / Universiteit |
careerLevel
| Value | Label |
|---|---|
starter | Starter |
junior | Junior |
medior | Medior |
senior | Senior |
manager | Manager |
directie | Directie |
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
| Volume | Duration | Compute Units | Est. 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.
| Item | Price |
|---|---|
| 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 CETconst 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 ApifyClientclient = 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.