Nationale Vacaturebank Jobs Scraper
Pricing
Pay per event
Nationale Vacaturebank Jobs Scraper
Scrape Nationale Vacaturebank (nationalevacaturebank.nl) job listings by keyword: title, employer, city and province, contract type, salary range, working hours, education level, dates, full text and vacancy URL. Deduplicated rows.
Pricing
Pay per event
Rating
0.0
(0)
Developer
DevilScrapes
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
5 days ago
Last modified
Categories
Share
Nationale Vacaturebank Jobs Scraper
💰 $3.00 / 1 000 vacancies · plus a $0.20 start fee per run · pay per vacancy delivered
The devil's in the data. 😈
Pull job listings from Nationale Vacaturebank (nationalevacaturebank.nl), one of the biggest Dutch job boards, as clean, deduplicated rows: title, employer, city and province, contract type, salary range, working hours, education and career level, dates, the full vacancy text and the public vacancy URL. Search by one keyword or many, and let us page through the results for you.
🎯 What this scrapes
Nationale Vacaturebank lists tens of thousands of Dutch vacancies and offers no
anonymous export. This Actor runs a keyword search (for example python or
verpleegkundige), walks the result pages 100 vacancies at a time, and returns one
row per vacancy: the vacancy id and URL, title and normalised function title,
employer (name, slug, type), work location (city, municipality, province, postal
code, coordinates), contract type, salary minimum, maximum and period when the
advert states one, working hours per week, education level, career level,
categories, industries, start, end and expiry dates, the apply link, the source
feed and the full vacancy text as HTML and as plain text. Each row also records the
keyword that found it and the total number of vacancies the site reports for it.
🔥 Features
- 🛡️ We rotate browser fingerprints (curl-cffi Chrome, Firefox and Safari profiles) when a request is refused, so the retry looks like a different browser.
- 🔁 We retry with exponential backoff on rate limits and server errors,
honouring
Retry-After. Up to 5 attempts per page. - 🌐 We rotate Apify Proxy sessions on every retry, with a fresh exit each time.
- 🧊 Run-wide deduplication. The same vacancy id never appears twice in your dataset, across pages or across keywords in one run.
- 🧱 Fault isolation. A page that cannot be read after its retries is skipped and the walk continues; one keyword that fails doesn't end the others. The status message tells you what was skipped.
- 💶 Structured salary. Minimum, maximum and period are separate numeric
fields, and stay
nullwhen the advert does not state a salary. - 📝 Full text on tap. Switch
includeDescriptionoff for a lighter dataset.
💡 Use cases
- Recruiters and staffing agencies: watch who is hiring for a role, and where, across the Netherlands.
- Labour-market analysts: measure vacancy volume, contract mix, salary bands and required education per keyword and province.
- Job aggregators: feed fresh Dutch vacancies into your own board.
- HR-tech and salary teams: track demand for a skill over time with a scheduled run.
⚙️ How to use it
- Add one or more search terms to
keywords, for examplepythonandverpleegkundige. - Set
maxPages(100 vacancies per page) andmaxItemsto bound how much you pull. - Run it, then export to JSON, CSV, or Excel, or pull the dataset straight from the Apify API.
📥 Input
| Field | Type | Required | Default | Notes |
|---|---|---|---|---|
keywords | array<string> | yes | none | Job titles, skills or employers. Blanks and duplicates are dropped. |
maxPages | integer | no | 3 | Result pages per keyword, 100 vacancies each (1-100). |
maxItems | integer | no | 100 | Hard cap on total rows across the run (1-10000). |
includeDescription | boolean | no | true | Include the full vacancy text (HTML and plain text). |
proxyConfiguration | object | yes | Apify Proxy | Datacenter by default; see Limitations. |
Example input
{"keywords": ["python", "verpleegkundige"],"maxPages": 2,"maxItems": 150,"includeDescription": true,"proxyConfiguration": { "useApifyProxy": true }}
📤 Output
One row per deduplicated vacancy.
| Field | Type | Notes |
|---|---|---|
jobId | string | Vacancy UUID, dedupe key. |
url | string | null | Public vacancy URL on nationalevacaturebank.nl. |
title / functionTitle | string | Vacancy title and normalised function title. |
company / companySlug / companyType / companyWebsite | string | null | Employer or recruiter. |
city / municipality / province / postalCode / street / country | string | null | Work location. |
latitude / longitude | number | null | Work location coordinates. |
contractType / contractTypes | string | null / array | e.g. Vast, Tijdelijk, Stage. |
salaryMin / salaryMax / salaryType | number | null / string | null | Null when the advert states no salary. |
workingHoursMin / workingHoursMax | number | null | Hours per week. |
educationLevel / educationLevels / careerLevel | string | null / array | e.g. WO, HBO, Ervaren. |
categories / industries | array<string> | Site categories and industries. |
startDate / endDate / expirationDate | string | null | ISO 8601 UTC. |
applyUrl / applyOption | string | null | Where and how to apply. |
origin / referenceId / recruiterId | string | null | Source feed identifiers. |
numberOfApplies | integer | null | Applications counted by the site. |
description / descriptionText | string | null | Vacancy text as HTML and as plain text. |
searchKeyword | string | Keyword that found the vacancy. |
totalResults | integer | null | Vacancies the site reports for that keyword. |
pageNumber / position | integer | 1-based page and position within the page. |
source | string | nationalevacaturebank. |
scrapedAt | string | UTC ISO-8601 run timestamp. |
Example output record
{"jobId": "4eedbe40-20f4-4c43-8b74-8b8ac205d627","url": "https://www.nationalevacaturebank.nl/vacature/4eedbe40-20f4-4c43-8b74-8b8ac205d627/data-scientist","title": "Data Scientist","company": "Stedin","companyType": "direct_employer","city": "Rotterdam","province": "Zuid-Holland","country": "Nederland","contractType": "Vast","salaryMin": 5085.0,"salaryMax": 5085.0,"salaryType": "monthly","workingHoursMin": 40.0,"workingHoursMax": 40.0,"educationLevel": "WO","careerLevel": "Ervaren","startDate": "2026-10-12T22:00:00Z","endDate": "2026-12-11T23:00:00Z","origin": "jobdigger","searchKeyword": "python","totalResults": 813,"pageNumber": 1,"position": 1,"source": "nationalevacaturebank","scrapedAt": "2026-10-13T08:00:00Z"}
💰 Pricing
Pay-Per-Event: you pay only when these events fire.
| Event | USD | What it is |
|---|---|---|
actor-start | $0.20 | One-off start charge per run |
result-emitted | $0.003 | Per deduplicated vacancy written to the dataset |
Example: 1 000 rows = $3.20 per run ($0.20 start + 1000 x $0.003). The start charge applies to every run, including one that matches nothing. No subscription, no minimum.
🚧 Limitations
- Keyword search only. Location, category and salary filters are not offered yet.
- Overlapping keywords overlap. A vacancy matching two keywords is returned once, under the first keyword that found it.
- Live ordering moves. Results are sorted newest first, so a new vacancy landing mid-run can shift the list; we dedupe by id, so a page may bring fewer new rows.
- Salary is advert-dependent. Many vacancies state none; those rows carry
null. - Datacenter proxy by default. If the site starts refusing it, switch
proxyConfigurationto a residential group with a Dutch exit. - A keyword with no vacancies is a success. It finishes with zero rows and a status message naming what was searched.
❓ FAQ
Do I need a Nationale Vacaturebank account or API key? No. This reads the public vacancy search.
How many vacancies can I pull per keyword?
As many as maxPages x 100, up to what the site lists for the keyword. The
totalResults column tells you the keyword's full size.
Why did my run return fewer rows than maxItems?
Either the keyword has fewer vacancies than your cap, maxPages stopped the run
first, or another keyword already returned the same vacancies. The status message
says which.
What happens if a page is blocked? We retry up to 5 times with a fresh browser fingerprint and proxy session each time. If a page still can't be read it is skipped and counted in the status message. The run ends as failed only when a keyword was blocked and nothing at all could be collected.
Can I run this on a schedule? Yes. Use Apify Schedules to re-run your keywords daily and catch newly posted vacancies.
💬 Your feedback
Found a bug, or need a field we don't return yet? Open an issue on the Actor's Issues tab. We read every one.