# TenderNed Netherlands Tenders Scraper (`automation-lab/tenderned-netherlands-tenders-scraper`) Actor

Search and export normalized Dutch procurement notices, awards, buyers, procedures, descriptions, and optional CPV/NUTS details from official TenderNed data.

- **URL**: https://apify.com/automation-lab/tenderned-netherlands-tenders-scraper.md
- **Developed by:** [Stas Persiianenko](https://apify.com/automation-lab) (community)
- **Categories:** Business
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## TenderNed Netherlands Tenders Scraper

Export structured Dutch public-procurement publications from the official, anonymous TenderNed data service.

The Actor searches tender notices, awards, market consultations, and other publication types, then writes one normalized record per publication to the default Apify dataset.

It uses direct HTTP requests to TenderNed's public JSON service. No browser, login, cookies, API key, or proxy is required.

### What can TenderNed Netherlands Tenders Scraper do?

- Search TenderNed titles, descriptions, and contracting authorities.
- Filter by publication date, publication type, procedure, contract type, and national or European scope.
- Keep only a specific buyer or publication status.
- Start at a chosen source page and bound both scanned pages and saved records.
- Export complete descriptions, references, buyer names, procedure labels, sender links, and canonical TenderNed URLs.
- Optionally enrich every result with CPV and NUTS codes, legal framework, scope, reference number, and award status.
- Produce JSON, CSV, Excel, XML, RSS, or another dataset export supported by Apify.

### Who is it for?

**Dutch and EU suppliers** can discover opportunities relevant to their products and services.

**Bid consultants** can build repeatable buyer and sector watchlists instead of checking TenderNed manually.

**Sales-intelligence teams** can enrich CRM pipelines with public procurement activity and award signals.

**Procurement analysts** can collect reproducible notice datasets for market, buyer, procedure, and category analysis.

**Data teams** can schedule daily runs and send new rows to webhooks, cloud storage, spreadsheets, or databases.

### Why use this Actor?

TenderNed publishes useful structured records, but production workflows still need pagination, validation, normalized field names, bounded filtering, retries, and export integrations.

This Actor handles those operational steps while preserving stable source IDs and canonical URLs.

The default mode avoids detail requests because the listing already contains the core publication record. Enable detail enrichment only when CPV, NUTS, legal, or award fields are needed.

### What TenderNed data is extracted?

| Field | Meaning |
| --- | --- |
| `publicationId` | Stable TenderNed publication ID |
| `referenceId` | TenderNed tender/reference ID |
| `referenceNumber` | Buyer reference number when details are enabled |
| `publicationDate` | Official publication date |
| `publicationType` | Publication type code and Dutch label |
| `publicationCode` | Specific notice-form code and label |
| `publicationStatus` | Status code and label, such as published or withdrawn |
| `tenderTitle` | Procurement title |
| `description` | Normalized full description |
| `buyerName` | Contracting authority |
| `procedure` | Procedure code and label |
| `contractType` | Supplies, services, or works code and label |
| `senderName`, `senderUrl` | External sender details when provided |
| `isEuropean`, `isDigital` | EU and digital-submission flags |
| `isEarlyTermination` | Early-termination flag |
| `isEformsAmendment` | eForms amendment flag |
| `legalFramework` | Legal framework with detail enrichment |
| `procurementNature` | Procurement nature with detail enrichment |
| `scope` | National or European scope with detail enrichment |
| `isAwarded` | Award flag with detail enrichment |
| `cpvCodes` | CPV classifications with main-code marker |
| `nutsCodes` | Geographic NUTS codes |
| `canonicalUrl` | Public TenderNed publication URL |
| `scrapedAt` | UTC extraction timestamp |

Fields available only through detail enrichment are `null` or empty arrays when `includeDetails` is disabled.

### How to scrape TenderNed publications

1. Open the Actor in Apify Console.
2. Enter a text query, buyer, or one or more source codes.
3. Add a publication date range for recurring monitoring.
4. Choose a practical `maxItems` value.
5. Enable `includeDetails` only if your workflow needs enrichment fields.
6. Click **Start**.
7. Open the **Dataset** tab to inspect or export results.

A useful first run is:

```json
{
  "query": "duurzaamheid",
  "maxItems": 25
}
```

### Input parameters

| Input | Type | Default | Description |
| --- | --- | ---: | --- |
| `query` | string | — | Text required in title, description, or buyer |
| `buyer` | string | — | Contracting-authority name fragment |
| `publicationTypes` | string\[] | all | TenderNed type codes such as `AAO`, `AGO`, `MAC`, or `VBE` |
| `publicationStatuses` | string\[] | all | Status codes kept after retrieval, such as `PUB` or `INT` |
| `dateFrom` | string | — | Inclusive publication date, `YYYY-MM-DD` |
| `dateTo` | string | — | Inclusive publication date, `YYYY-MM-DD` |
| `procedureCodes` | string\[] | all | Procedure codes such as `OPE` |
| `contractTypes` | string\[] | all | `L` supplies, `D` services, or `W` works |
| `scopeCodes` | string\[] | all | TenderNed national/EU scope codes, for example `EU` |
| `includeDetails` | boolean | `false` | Fetch CPV/NUTS and other enrichment fields |
| `startPage` | integer | `0` | Zero-based TenderNed page |
| `pageSize` | integer | `50` | Source records requested per page, maximum 100 |
| `maxPages` | integer | `20` | Safety limit for source pages scanned |
| `maxItems` | integer | `100` | Maximum matching records saved |

`publicationStatuses`, `buyer`, and exact text matching are verified by the Actor after TenderNed returns candidate rows. Use `maxPages` to control scans for narrow client-side filters.

### Output example

The following abbreviated record reflects the current output shape:

```json
{
  "publicationId": "434758",
  "referenceId": "603932",
  "publicationDate": "2026-07-27",
  "publicationType": {
    "code": "AGO",
    "name": "Aankondiging gegunde opdracht"
  },
  "publicationStatus": {
    "code": "PUB",
    "name": "Gepubliceerd"
  },
  "tenderTitle": "Projectmanager Smart Port Waalwijk",
  "buyerName": "Gemeente Waalwijk",
  "procedure": {
    "code": "OPE",
    "name": "Openbaar"
  },
  "contractType": {
    "code": "W",
    "name": "Werken"
  },
  "isEuropean": true,
  "isDigital": false,
  "canonicalUrl": "https://www.tenderned.nl/aankondigingen/overzicht/434758"
}
```

The complete dataset row also contains the description, sender, publication code, flags, enrichment fields, and extraction timestamp.

### How much does it cost to scrape TenderNed tenders?

The Actor uses pay-per-event pricing:

- **$0.005** once per run.
- On the Free plan, **$0.000041071 per saved publication**.
- Higher Apify plans receive automatic volume-tier discounts, down to **$0.00001 per publication** on the Diamond tier.

Example Free-plan prices:

| Saved publications | Estimated Actor charge |
| ---: | ---: |
| 10 | $0.00541 |
| 100 | $0.00911 |
| 1,000 | $0.04607 |

Rejected, duplicate, malformed, or filtered-out source rows are not charged as items. Detail enrichment has no separate charge event; it is included in the saved-publication event.

Apify displays the applicable plan tier before a run. Storage or other platform charges may be governed by your Apify plan.

### Monitoring and automation workflows

#### Daily opportunity watch

Set `dateFrom` to the latest date required by your process, filter publication types, and schedule the Actor daily. Use the stable `publicationId` to deduplicate downstream alerts.

#### Buyer activity feed

Set `buyer` to a contracting authority and deliver the dataset to a CRM or warehouse. Increase `maxPages` when collecting deep history.

#### Contract award intelligence

Use `publicationTypes: ["AGO"]`, enable `includeDetails`, and retain CPV codes, award status, buyer, and reference fields for sales intelligence.

#### Sector dataset

Combine text, procedure, contract-type, and scope filters. Export the resulting dataset to CSV or query it through the Apify API.

### JavaScript API example

Install the official client:

```bash
npm install apify-client
```

Run the Actor and read its dataset:

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

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation-lab/tenderned-netherlands-tenders-scraper').call({
  publicationTypes: ['AGO'],
  scopeCodes: ['EU'],
  includeDetails: true,
  maxItems: 50,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

### Python API example

Install the client:

```bash
pip install apify-client
```

Then run and retrieve results:

```python
import os
from apify_client import ApifyClient

client = ApifyClient(os.environ['APIFY_TOKEN'])
run = client.actor('automation-lab/tenderned-netherlands-tenders-scraper').call(run_input={
    'buyer': 'Gemeente Waalwijk',
    'maxItems': 25,
})

for item in client.dataset(run['defaultDatasetId']).iterate_items():
    print(item)
```

### cURL API example

Start a synchronous run and receive dataset items:

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/automation-lab~tenderned-netherlands-tenders-scraper/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"query":"duurzaamheid","maxItems":25}'
```

Keep `APIFY_TOKEN` in an environment variable rather than source code.

### Use TenderNed data with Apify MCP

#### Claude Code setup

Add this Actor to Claude Code:

```bash
claude mcp add --transport http apify \
  "https://mcp.apify.com?tools=automation-lab/tenderned-netherlands-tenders-scraper"
```

#### Claude Desktop setup

Claude Desktop can use this JSON configuration:

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com?tools=automation-lab/tenderned-netherlands-tenders-scraper"
    }
  }
}
```

#### Cursor and VS Code setup

In Cursor or VS Code, add the same `mcpServers.apify.url` value through the editor's MCP settings. No local command process is required because the transport is HTTP.

#### MCP example prompts

- “Find 25 TenderNed publications mentioning circular construction.”
- “Collect recent contract awards from Dutch municipalities and include CPV details.”
- “Export TenderNed notices from Gemeente Waalwijk for my supplier pipeline.”

### Limits and reliability

TenderNed controls source availability, fields, code lists, and publication volume.

The Actor retries network timeouts, rate limits, and temporary server errors with bounded backoff. It does not blindly retry invalid requests or unexpected response formats.

Requests are sequential and conservative. The Actor stops at `maxItems`, `maxPages`, an empty page, or TenderNed's last page.

Some historical source descriptions contain replacement characters supplied by TenderNed. The Actor decodes HTML entities and normalizes whitespace but does not invent missing source characters.

No residential proxy or automatic browser fallback is enabled. This keeps cost and behavior predictable for the currently anonymous JSON service.

### Responsible and legal use

TenderNed procurement publications are public government-procurement information. You remain responsible for your collection frequency, retention, redistribution, and downstream decisions.

Respect applicable law, TenderNed terms, intellectual-property rights, privacy obligations, and reasonable request rates.

Do not use public contact or buyer data for unlawful spam, harassment, discrimination, or automated decisions that require human review.

This Actor is an independent data tool and is not affiliated with or endorsed by TenderNed or the Dutch government.

### FAQ

#### Why did my narrow buyer or status search return fewer items than `maxItems`?

The Actor first receives candidates from TenderNed and then verifies buyer, text, and status filters. Increase `maxPages`, broaden the filter, or remove a conflicting date/type constraint.

#### Why are enrichment fields null or empty?

Set `includeDetails` to `true`. Core list mode intentionally skips one extra request per publication.

#### Why did the run fail immediately?

Check that dates use `YYYY-MM-DD`, `dateFrom` is not later than `dateTo`, numeric limits are within the documented bounds, and arrays contain TenderNed codes.

#### Does the Actor need a Netherlands proxy?

No. Current official JSON records are available anonymously and directly. The Actor does not expose an unmeasured proxy fallback.

#### Can I resume at another result page?

Yes. Set zero-based `startPage` and keep the same filters and `pageSize`.

### Related public-procurement Actors

- [Singapore GeBIZ Tender Opportunities Scraper](https://apify.com/automation-lab/singapore-gebiz-tender-opportunities-scraper)
- [CanadaBuys Tender Opportunities Scraper](https://apify.com/automation-lab/canadabuys-tender-opportunities-scraper)
- [UNGM Tender Notices Scraper](https://apify.com/automation-lab/ungm-tender-notices-scraper)
- [AusTender Current Tender Opportunities Scraper](https://apify.com/automation-lab/austender-current-tender-opportunities-scraper)
- [Spain Public Tenders Scraper](https://apify.com/automation-lab/spain-public-tenders-scraper)

Use these Actors when a supplier or analyst needs a multi-country procurement-monitoring portfolio rather than TenderNed alone.

# Actor input Schema

## `query` (type: `string`):

Words to find in the tender title, description, or buyer. TenderNed applies the search first; the Actor verifies the match before saving.

## `buyer` (type: `string`):

Keep publications whose contracting authority contains this name, for example Gemeente Waalwijk.

## `publicationTypes` (type: `array`):

Optional TenderNed publication type codes, such as AAO (contract notice), AGO (contract award), MAC (market consultation), or VBE (early termination).

## `publicationStatuses` (type: `array`):

Optional status codes to keep after retrieval, such as PUB (published) or INT (withdrawn).

## `dateFrom` (type: `string`):

Earliest publication date, inclusive, in YYYY-MM-DD format.

## `dateTo` (type: `string`):

Latest publication date, inclusive, in YYYY-MM-DD format.

## `procedureCodes` (type: `array`):

Optional TenderNed procedure codes, such as OPE for open procedure.

## `contractTypes` (type: `array`):

Optional contract type codes: L (supplies), D (services), or W (works).

## `scopeCodes` (type: `array`):

Optional TenderNed scope codes, for example EU for European notices.

## `includeDetails` (type: `boolean`):

Fetch one extra official API response per result to include CPV/NUTS codes, legal framework, scope, reference number, and award status.

## `startPage` (type: `integer`):

Zero-based TenderNed result page at which to start.

## `pageSize` (type: `integer`):

Publications requested from TenderNed per API page.

## `maxPages` (type: `integer`):

Safety bound for pages scanned, especially when applying buyer or status filters.

## `maxItems` (type: `integer`):

Stop after saving this many matching procurement publications.

## Actor input object example

```json
{
  "query": "duurzaamheid",
  "includeDetails": false,
  "startPage": 0,
  "pageSize": 50,
  "maxPages": 20,
  "maxItems": 20
}
```

# Actor output Schema

## `overview` (type: `string`):

Dataset view containing extracted TenderNed tender and award records.

# 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 = {
    "query": "duurzaamheid",
    "includeDetails": false,
    "maxItems": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation-lab/tenderned-netherlands-tenders-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 = {
    "query": "duurzaamheid",
    "includeDetails": False,
    "maxItems": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("automation-lab/tenderned-netherlands-tenders-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 '{
  "query": "duurzaamheid",
  "includeDetails": false,
  "maxItems": 20
}' |
apify call automation-lab/tenderned-netherlands-tenders-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,automation-lab/tenderned-netherlands-tenders-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/IyPcvDGQ5qW0qfXad/builds/K1B1vPGhQ28LvVUS5/openapi.json
