# Nationale Vacaturebank Scraper (`santamaria-automations/nationale-vacaturebank-nl-scraper`) Actor

Extract job listings from Nationale Vacaturebank (nationalevacaturebank.nl). Returns title, employer, location, province, salary, hours, education, contract type, contact person with email, full description and apply link. Pay per event: $0.003 per job.

- **URL**: https://apify.com/santamaria-automations/nationale-vacaturebank-nl-scraper.md
- **Developed by:** [NanoScrape](https://apify.com/santamaria-automations) (community)
- **Categories:** Jobs, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 serp results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Nationale Vacaturebank Scraper - Dutch Jobs, Contact Person, Salary

Pull live Dutch vacancies from [Nationale Vacaturebank](https://www.nationalevacaturebank.nl), the Netherlands' largest private job board. Each record includes job title, employer, city and province with coordinates, contract type, weekly hours, education level, salary range in EUR, the full description (text, HTML and Markdown), the expiry date and the apply link. When the employer lists one, you also get the contact person (name and email), the employer website and the contact address. No login, no API key, no cookies to manage.

**Contact person:** many vacancies name a recruiter or hiring manager. You get first name, last name and email in dedicated fields, ready for outreach.

### What you get

| Field | Description |
|-------|-------------|
| `id` | Vacancy identifier (UUID) |
| `title` | Job title |
| `job_url` | Vacancy page on nationalevacaturebank.nl |
| `apply_url` | Where to apply (employer page, or `job_url` when the platform hosts the application) |
| `apply_method` / `external_apply_url` | Apply option as printed and the employer or ATS URL when the application leaves the platform |
| `company_name` | Employer or recruiter name |
| `company_type` | `direct_employer` or `human_resource_manager` (recruitment agency) |
| `company_website` | Employer website (when listed) |
| `company_address` | Street, postcode and city of the contact block (when listed) |
| `company_logo_url` | Employer logo (when uploaded) |
| `location` / `city` | City of the workplace |
| `region` | Dutch province |
| `street_address` / `postal_code` | Workplace address |
| `latitude` / `longitude` | Workplace coordinates |
| `posted_at` | Exact publication timestamp (ISO 8601, UTC) |
| `expires_at` | Vacancy expiry timestamp |
| `employment_type` | permanent, temporary, internship, freelance, temp\_agency, on\_call |
| `contract_types` | All contract types as printed (Dutch) |
| `workplace_type` / `remote_option` | hybrid, remote or on-site, when stated |
| `min_hours` / `max_hours` / `working_hours` | Weekly hours range and a readable text |
| `study_level` / `education_required` | Required education level, normalised and as printed |
| `position_level` | Career level (Starter, Ervaren, ...) |
| `category` / `categories` / `industries` | Platform category and industry labels |
| `occupation` / `isco_code` | Standardised occupation title and ISCO code |
| `salary_min` / `salary_max` | EUR amounts (null when not stated) |
| `salary_currency` / `salary_period` / `salary_text` | Currency, period (month, year, hour) and a readable range |
| `cao` | Collective labour agreement mentioned in the text, for example `CAO VVT` (often null) |
| `description_snippet` / `description_full` / `description_html` / `description_md` | Description in four formats |
| `contact_name` / `contact_firstname` / `contact_lastname` | Contact person |
| `contact_email` / `contact_phone` | Contact person email and phone (scalar) |
| `contact_emails` / `contact_phones` / `contact_urls` | Arrays: contact email plus emails found in the text, phones, contact website |
| `origin` | Feed that supplied the vacancy |
| `applicants_count` | Applications counted by the platform (null when 0) |
| `search_query` | The query that found this row |
| `source_platform` / `scraped_at` | Source and scrape timestamp |

Fields the vacancy does not show are `null` (or an empty array for the `contact_*` arrays).

### Sample output

```json
{
  "_type": "job",
  "id": "7b3124b5-2c58-4846-aed9-6dcdfc50836c",
  "title": "Jeugdverpleegkundige 0-12 jaar",
  "job_url": "https://www.nationalevacaturebank.nl/vacature/7b3124b5-2c58-4846-aed9-6dcdfc50836c/verpleegkundige",
  "apply_url": "https://example-employer.nl/vacatures/jeugdverpleegkundige",
  "apply_method": "external",
  "external_apply_url": "https://example-employer.nl/vacatures/jeugdverpleegkundige",
  "company_name": "GGD Voorbeeldregio",
  "company_type": "direct_employer",
  "company_website": "https://www.example-employer.nl/",
  "location": "Nijmegen",
  "country": "NL",
  "region": "Gelderland",
  "postal_code": "6531AB",
  "latitude": 51.82,
  "longitude": 5.79,
  "posted_at": "2026-09-28T22:00:00Z",
  "expires_at": "2026-11-27T23:00:00Z",
  "employment_type": "temporary",
  "workplace_type": "hybrid",
  "min_hours": 24,
  "max_hours": 32,
  "working_hours": "24-32 uur per week",
  "study_level": "HBO/bachelor",
  "position_level": "Ervaren",
  "category": "Medisch/Zorg",
  "salary_min": 3568,
  "salary_max": 5095,
  "salary_currency": "EUR",
  "salary_period": "month",
  "salary_text": "EUR 3568 - 5095 per month",
  "cao": "CAO VVT",
  "description_snippet": "Jij kijkt verder dan de hulpvraag. Als jeugdverpleegkundige herken je wat kinderen nodig hebben...",
  "contact_name": "Anna de Vries",
  "contact_firstname": "Anna",
  "contact_lastname": "de Vries",
  "contact_email": "info@example-employer.nl",
  "contact_emails": ["info@example-employer.nl"],
  "contact_phones": [],
  "origin": "jobdigger",
  "search_query": "verpleegkundige",
  "source_platform": "nationalevacaturebank.nl",
  "scraped_at": "2026-09-29T08:00:00Z"
}
```

The sample is shortened. Real rows also carry `description_full`, `description_html`, `description_md`, `city`, `street_address`, `contract_types`, `categories`, `industries`, `occupation`, `isco_code` and the other fields from the table above.

### Input

```json
{
  "searchQueries": ["verpleegkundige", "software engineer"],
  "location": "Amsterdam",
  "maxResults": 100,
  "maxResultsPerQuery": 50,
  "sortBy": "newest",
  "postedWithinDays": 7
}
```

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `searchQueries` | string\[] | - | Keywords in Dutch or English. Each runs as a separate search. Leave empty (with no `searchUrls`) to get the newest vacancies overall. |
| `location` | string | - | City filter (Amsterdam, Rotterdam, Utrecht, ...) |
| `searchUrls` | string\[] | - | nationalevacaturebank.nl search URLs (the `query` and `location` parameters are used) |
| `maxResults` | integer | 100 (20 when no keywords or URLs) | Total cap across all queries |
| `maxResultsPerQuery` | integer | 100 | Cap per keyword or URL. Set it below `maxResults` so every query gets rows. |
| `sortBy` | string | `newest` | `newest` (most recent first, right for scheduled scrapes) or `distance` (nearest to `location`) |
| `postedWithinDays` | number | - | Only jobs posted in the last N days. With `newest` the search stops at the first older job. |
| `titleFilter` | string | - | Comma-separated title terms (OR-match, case-insensitive). Rows that do not match are dropped before they are returned or charged. |

Running with an empty input `{}` returns the 20 newest vacancies.

Jobs found by more than one keyword are returned once and attributed to the first keyword that found them.

#### Precision title filter

```json
{
  "searchQueries": ["developer"],
  "titleFilter": "developer, engineer",
  "maxResults": 50
}
```

Only jobs with "developer" or "engineer" in the title are returned.

### Netherlands employment types

Nationale Vacaturebank uses Dutch contract terms, mapped to English in `employment_type`:

| Dutch | English |
|-------|---------|
| Vast | permanent |
| Tijdelijk | temporary |
| Stage | internship |
| Freelance / ZZP | freelance |
| Uitzendkracht | temp\_agency |
| Oproepkracht | on\_call |

The original Dutch values stay available in `contract_types`.

### Speed and scale

A run of 100 jobs takes about a minute. A search returns up to 20 jobs per page and the platform lists thousands of vacancies per popular keyword, so use `maxResults`, `maxResultsPerQuery` and `postedWithinDays` to bound a run. For a daily scheduled run use `sortBy: newest` with `postedWithinDays: 1`.

### Pricing

This actor uses Pay Per Event (PPE) billing:

| Event | Price | Description |
|-------|-------|-------------|
| `actor-start` | $0.001 | Charged once per run |
| `job-serp-result` | $0.003 | Charged once per job returned |

Every row includes the full description, contact person and company data.

**Example cost:** 1,000 jobs cost about $3.00 ($0.003 per job) plus $0.001 per run start.

### Deprecation notes

- `description` is the same value as `description_snippet`. Both are emitted; `description` stays for backward compatibility.
- `posted_at_datetime` is the same value as `posted_at` (canonical name since 2026-09-29). Both are emitted.
- `workplace_type` is the same source as `remote_option`. Both are emitted.

Changes in version 1.5 (2026-09-29): every row includes the full description, contact person and company data, and every job is billed at a flat $0.003. The old inputs `includeJobDetails`, `includeCompanyDetails` and `maxConcurrency` are still accepted and ignored.

Changes in version 1.4 (2026-09-29): `posted_at`/`posted_at_datetime` now carry the exact publication timestamp instead of the date at 00:00:00Z. `job_url` and `source_url` now use the vacancy page link supplied by the platform (`/vacature/{id}/{slug}`), replacing the earlier `/vacature/detail/{id}` form. `region` now comes from the platform (previously a partial city lookup), and `company_logo_url`, `workplace_type`, `salary_period` and `salary_text` are filled where they were empty before.

### Use with AI Agents (MCP)

Connect this actor to any MCP-compatible AI client: Claude Desktop, Claude.ai, Cursor, VS Code, LangChain, LlamaIndex, or custom agents.

Configure the MCP server with Nationale Vacaturebank Scraper preconfigured at `mcp.apify.com?tools=santamaria-automations/nationale-vacaturebank-nl-scraper`. You can connect to the Apify MCP Server using clients like Tester MCP Client, or any other MCP client of your choice.

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=santamaria-automations/nationale-vacaturebank-nl-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}
```

For per-tool schemas and copy-paste snippets for MCP clients, see the [MCP tab](https://console.apify.com/actors/570p4VgnMzjssEKqY/info/api/mcp?build=latest).

See the [auto-generated API tab](https://console.apify.com/actors/570p4VgnMzjssEKqY/info/api) for language-specific examples (cURL, JS, Python, .NET, Ruby, PHP).

### Private vs government

Nationale Vacaturebank covers private-sector employers and agencies posting directly. For government and UWV vacancies use the [werk-nl-scraper](https://apify.com/santamaria-automations/werk-nl-scraper). Together they cover the Dutch labour market.

### Related actors

Feed the `company_website` field from this actor's output into one of the two below to enrich rows with contact data.

- [Website Email & Phone Scraper](https://apify.com/santamaria-automations/website-email-scraper): fast regex-based email and phone extraction from a website.
- [Website Contact Extractor](https://apify.com/santamaria-automations/website-contact-extractor): LLM-based, higher precision on names, roles and department emails.
- [Website Job Extractor](https://apify.com/santamaria-automations/website-job-extractor): jobs from any company career page.
- [Indeed Scraper](https://apify.com/santamaria-automations/indeed-http-scraper): Indeed job listings, including the Netherlands.
- [Glassdoor Scraper](https://apify.com/santamaria-automations/glassdoor-scraper): Glassdoor jobs with company ratings.
- [Werk.nl Scraper](https://apify.com/santamaria-automations/werk-nl-scraper): Dutch UWV government vacancies.
- [VDAB Scraper](https://apify.com/santamaria-automations/vdab-be-scraper): Flanders (Belgium) jobs.
- [Forem Scraper](https://apify.com/santamaria-automations/forem-be-scraper): Wallonia (Belgium) jobs.

### Support

- **Questions or issues?** Email contact@nanoscrape.com, we typically reply within 6 hours. You can also open a ticket in the [Issues tab](https://console.apify.com/actors/570p4VgnMzjssEKqY/info/issues) on the actor page.
- **Feature request for this actor?** Open a ticket in the [Issues tab](https://console.apify.com/actors/570p4VgnMzjssEKqY/info/issues) or email contact@nanoscrape.com with the platform field you need and (if possible) a URL that shows the data live.
- **Need a scraper for a job board we don't cover yet?** Email contact@nanoscrape.com with the target site + your rough usage volume. We ship one-off boards regularly.

# Actor input Schema

## `searchQueries` (type: `array`):

One or more keyword queries in Dutch or English (for example 'software engineer', 'verpleegkundige', 'chauffeur', 'accountant'). Each runs as a separate search and every row carries the query that found it in search\_query. Jobs found by more than one query are returned once. Leave empty (with no Search URLs) to get the newest vacancies overall.

## `location` (type: `string`):

Dutch city to filter by (for example 'Amsterdam', 'Rotterdam', 'Utrecht', 'Eindhoven', 'Den Haag'). Applied to all keyword searches.

## `searchUrls` (type: `array`):

Paste one or more Nationale Vacaturebank search URLs. Go to nationalevacaturebank.nl, run a search, and copy the URL. The query and location parameters are used.

## `maxResults` (type: `integer`):

Total cap across all queries and URLs. Leave empty for the default: 100 with keywords or URLs, 20 (the newest vacancies) with neither.

## `maxResultsPerQuery` (type: `integer`):

Maximum results per keyword or search URL. Set it below Max Total Results so that every query gets its share (for example 2 keywords, 25 each, total 50).

## `sortBy` (type: `string`):

How to order search results. 'newest' returns the most recently posted jobs first (recommended for scheduled scrapes). 'distance' orders by proximity to the Location filter.

## `postedWithinDays` (type: `number`):

Only return jobs posted in the last N days (for example 1 for a daily scheduled run). With sortBy 'newest' the search stops at the first older job. Leave empty for no age limit.

## `titleFilter` (type: `string`):

Comma-separated list of terms to match against job titles (case-insensitive OR-match). Only jobs whose title contains one of the terms are emitted. Non-matching rows are dropped before they are returned, so you don't pay for filtered-out jobs. Leave empty to disable.

## Actor input object example

```json
{
  "location": "Amsterdam",
  "maxResultsPerQuery": 100,
  "sortBy": "newest",
  "titleFilter": ""
}
```

# Actor output Schema

## `jobListings` (type: `string`):

Dataset of Dutch job listings from nationalevacaturebank.nl. Each row has: id, title, job\_url, source\_url, apply\_url, apply\_method, external\_apply\_url, company\_name, company\_website, company\_logo\_url, company\_type, company\_slug, company\_address, location, city, country, region, street\_address, postal\_code, latitude, longitude, posted\_at, posted\_at\_text, posted\_at\_datetime, expires\_at, employment\_type, contract\_types, workplace\_type, remote\_option, min\_hours, max\_hours, working\_hours, study\_level, education\_required, position\_level, category, categories, industries, occupation, isco\_code, salary\_min, salary\_max, salary\_currency, salary\_period, salary\_text, cao, description, description\_snippet, description\_full, description\_html, description\_md, contact\_name, contact\_firstname, contact\_lastname, contact\_email, contact\_phone, contact\_emails, contact\_phones, contact\_urls, origin, applicants\_count, search\_query, source\_platform, scraped\_at.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "maxResultsPerQuery": 100,
    "sortBy": "newest"
};

// Run the Actor and wait for it to finish
const run = await client.actor("santamaria-automations/nationale-vacaturebank-nl-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "maxResultsPerQuery": 100,
    "sortBy": "newest",
}

# Run the Actor and wait for it to finish
run = client.actor("santamaria-automations/nationale-vacaturebank-nl-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "maxResultsPerQuery": 100,
  "sortBy": "newest"
}' |
apify call santamaria-automations/nationale-vacaturebank-nl-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,santamaria-automations/nationale-vacaturebank-nl-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/570p4VgnMzjssEKqY/builds/cMo2RvmE0cXMuAvG0/openapi.json
