# Perceel Dossier XL — Agrarisch Dossier (`codeclouds/nl-perceel-dossier-xxl`) Actor

Vraag een agrarisch perceeldossier op — gewas, bodemrisico en netcongestie in 1 call, per adres of coördinaat. Bespaart 3 losse databronnen (BRP Gewaspercelen, Bodemloket, Capaciteitskaart) + geocoding-koppeling. Vanaf $0,02/dossier, optionele verrijkingen $0,008/stuk, PPE.

- **URL**: https://apify.com/codeclouds/nl-perceel-dossier-xxl.md
- **Developed by:** [Dennis](https://apify.com/codeclouds) (community)
- **Categories:** Real estate
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $20.00 / 1,000 perceel-dossier-resultaats

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?

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

## Perceel Dossier XL — Agrarisch Perceel-Dossier

One request per Dutch address or coordinate → a combined agricultural parcel dossier assembled
from **three official open data sources**: BRP Gewaspercelen (crop registration), Bodemloket (soil
contamination risk), and the national Capaciteitskaart (electricity grid congestion). Every source
is free and public on its own — nobody combines them into one location-level record. That
combination is the product.

Manually looking each of these three sources up per parcel — a different map layer or portal for
each — realistically costs 5-10 minutes per location. This Actor turns that into a single request,
with every value source-attributed and a free risk summary included per result.

### When should an AI agent use this?

- "Build an agricultural parcel dossier for this address: crop, soil risk, and grid capacity."
- "What crop is registered on this agricultural parcel?"
- "Screen this farmland before a purchase or lease: is there a known soil contamination nearby, and is there still grid capacity for a solar/battery installation?"
- "Check a shortlist of agricultural parcels for BRP crop data plus soil and grid risk in one call."
- "Does this location fall inside a Bodemloket-registered contaminated-soil area?"
- "Is there still room on the electricity grid at this location for a new farm connection?"

### What this Actor does

- Geocodes your input (address, postcode, place name, or `"lat,lon"`) via the official **PDOK
  Locatieserver**
- Looks up the nearest **BRP Gewaspercelen** (PDOK/RVO crop parcel registration) — crop, parcel
  category, parcel ID, status, distance to your input point, and computed surface area; returns
  the top-3 nearest parcels (crop-rotation fields are reserved for when the source serves
  multiple years)
- Checks **Bodemloket** (Rijkswaterstaat) for known soil contamination (Wbb) locations near the
  point, with a risk classification and the responsible authority (`bevoegd gezag`)
- Checks the national **Capaciteitskaart** (Netbeheer Nederland) for the current electricity grid
  congestion status (both feed-in and offtake) at the location
- Builds a free `samenvatting` (summary) block per result: a `risiconiveau` (risk level), the
  attention points that drove it, and the crop + surface area of the nearest parcel — no extra
  charge, purely aggregated from data already fetched
- Adds a free `RUN_SUMMARY` key-value record at the end of the run: totals, crop distribution, and
  total surface area processed
- Processes a single query or a bulk list, with configurable concurrency

### Who is this for?

- Agricultural advisors and appraisers
- Land brokers and real-estate agents specializing in farmland
- Banks (business transfer due diligence, subsidy applications)
- Project developers scoping agricultural sites (e.g. for solar/BESS)

### Input

| Field | Type | Description | Example |
|---|---|---|---|
| `query` | string | Single address, postcode, coordinate (`"lat,lon"`), or place name | `"Emmeloord"` |
| `queries` | array of strings | Bulk: one or more addresses/coordinates/place names | `["Emmeloord", "Dronten"]` |
| `concurrency` | integer | How many locations to process in parallel (1-10) | `3` |
| `includeBodemrisico` | boolean | Add the soil-contamination check via Bodemloket | `true` |
| `includeNetcongestie` | boolean | Add the grid-congestion check via the Capaciteitskaart | `true` |
| `includeGewasrotatie` | boolean | Request crop rotation from an older snapshot (currently a no-op: PDOK serves only the latest snapshot, so `vorigGewas` stays `null`) | `false` |
| `bronnenFilter` | array | Optional: filter on specific BRP crop codes (`gewascode`), e.g. `[259, 2659]` | — |

### Output

```json
{
  "invoer": "Emmeloord",
  "gevonden": true,
  "perceelGevonden": true,
  "fout": null,
  "weergavenaam": "Emmeloord, Noordoostpolder",
  "postcode": "8302",
  "gemeente": "Noordoostpolder",
  "provincie": "Flevoland",
  "lat": 52.7108,
  "lon": 5.7473,
  "geocodingScore": 15.2,
  "geocodingBetrouwbaarheid": "hoog",
  "perceel": {
    "id": "NL.IMRO...",
    "gewas": "Tarwe, winter-",
    "gewascode": 259,
    "jaar": 2026,
    "status": "Definitief",
    "afstandTotInvoerpunt": 42,
    "oppervlakteM2": 38400
  },
  "percelen": [ "..." ],
  "aantalPercelen": 3,
  "bodemrisico": {
    "type": "Wbb-locatie",
    "status": "Voldoende onderzocht",
    "risico": "laag",
    "bevoegdGezag": "Provincie Flevoland"
  },
  "netcongestie": {
    "statusAfname": "Voldoende ruimte",
    "statusOpwek": "Beperkte ruimte",
    "netbeheerder": "Liander",
    "wachtrijAfnameMw": 0,
    "wachtrijOpwekMw": 4.2
  },
  "samenvatting": {
    "risiconiveau": "laag",
    "omschrijving": "Geen bijzondere risico's gevonden.",
    "aandachtspunten": [],
    "gewas": "Tarwe, winter-",
    "perceelOppervlakte": 38400
  },
  "bron": "BRP Gewaspercelen (PDOK/RVO, api.pdok.nl/rvo/gewaspercelen)"
}
```

`fout` is a human-readable error message (`null` on success). `perceelGevonden` distinguishes a
successful geocoding match from an actual BRP parcel being found on that location — a location can
geocode fine but have no registered agricultural parcel nearby (e.g. inside a village).

#### Common BRP crop codes (`gewascode`)

| Code | Crop | Category |
|---|---|---|
| 259 | Wheat, winter | Arable |
| 2659 / 2013 | Maize, silage | Arable |
| 236 | Barley, spring | Arable |
| 233 | Barley, winter | Arable |
| 201 | Potatoes | Arable |
| 1010 | Sugar beet | Arable |
| 857 | Flower bulbs, other | Horticulture |
| 2563 | Flower bulbs, tulips | Horticulture |
| 313 | Grassland, permanent | Grassland |

### Sources

| Source | License | Access |
|---|---|---|
| BRP Gewaspercelen (PDOK/RVO) | Public Domain Mark 1.0 | No auth, no cost |
| Bodemloket (Rijkswaterstaat) | Public domain | No auth |
| Capaciteitskaart (Netbeheer Nederland) | Public domain | No auth |

### Pricing

This Actor uses Apify's Pay-Per-Event (PPE) pricing model.

- **Actor Start:** $0.00005 (Apify default)
- **perceel-dossier-resultaat:** $0.02 per address successfully geocoded and assembled into a dossier
- **bodemrisico-verrijking:** $0.008 per result where soil contamination data was actually found (only when enabled)
- **netcongestie-verrijking:** $0.008 per result where grid congestion data was actually found (only when enabled)

### Legal

Uses only official, open, public-domain government data: BRP Gewaspercelen (PDOK/RVO), Bodemloket
(Rijkswaterstaat), and the Capaciteitskaart (Netbeheer Nederland). No personal data is processed —
BRP Gewaspercelen is anonymized parcel-level crop data, not tied to a farm owner's identity.

### Known limitations

- BRP Gewaspercelen is updated annually (reference date 15 May) — not live day-to-day data
- Soil risk is an area-level indication, not an exact per-parcel assessment
- Grid congestion reflects the general network status, not a guaranteed available connection capacity for a specific project
- No historical data: PDOK serves only the most recent BRP snapshot (reference date 15 May), so the crop-rotation fields (`vorigGewas`, `vorigGewascode`, `vorigJaar`) are always `null` for now

### FAQ

**Q: What's the difference between `gevonden` and `perceelGevonden`?**
A: `gevonden` means the input was successfully geocoded to a location. `perceelGevonden` means a
BRP-registered agricultural parcel was actually found near that location — a valid address can
still have no nearby parcel (e.g. an address in a village center).

**Q: Can I filter on a specific crop?**
A: Yes — use `bronnenFilter` with one or more BRP `gewascode` values (see the table above) to only
match specific crops.

**Q: Do I get charged if soil or grid data isn't enabled or found?**
A: No. `bodemrisico-verrijking` and `netcongestie-verrijking` are only charged when the respective
module is enabled **and** data was actually found for that location.

### Related Actors

- **[NL Bodemrisico Check](https://apify.com/codeclouds/nl-bodemrisico-check)** — same Bodemloket source, usable standalone for a pure soil-risk check.
- **[NL Netcongestie Monitor](https://apify.com/codeclouds/nl-netcongestie-monitor)** — same Capaciteitskaart source, usable standalone for a pure grid-congestion check.
- **[Vastgoed XXL](https://apify.com/codeclouds/vastgoed-xxl)** — the equivalent combined-dossier concept for urban real estate instead of farmland.

***

*Zoekwoorden: agrarisch perceeldossier, BRP gewaspercelen, bodemrisico landbouwgrond, netcongestie
agrarisch, perceelscheck, landbouwgrond due diligence, gewasrotatie, Wbb-locatie, Capaciteitskaart
landbouw.*

### Keywords

agriculture, farmland, netherlands, brp, crop-data, soil-contamination, grid-congestion,
due-diligence, parcel, geocoding

### Changelog

#### 0.1.0

- Initial release: BRP Gewaspercelen + soil risk + grid congestion
- Distance to parcel in meters
- Free summary block per dossier (risk level + attention points)
- `perceelGevonden` field distinguishes geocoding from an actual parcel match

# Actor input Schema

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

Eén adres, postcode, 'lat,lon'-coördinaat of plaatsnaam voor een enkel agrarisch dossier.

## `queries` (type: `array`):

Een of meer adressen, postcodes, plaatsnamen of coordinaten ("lat,lon") om te controleren op BRP-gewaspercelen, bodemrisico en netcongestie.

## `concurrency` (type: `integer`):

Hoeveel locaties tegelijk verwerkt worden (geocoding + BRP-lookup + risico-checks per locatie).

## `includeBodemrisico` (type: `boolean`):

Voeg bodemrisico-check toe via Bodemloket (Rijkswaterstaat ArcGIS). Detecteert Wbb-locaties (verontreinigde grond) in de buurt.

## `includeNetcongestie` (type: `boolean`):

Voeg netcongestie-check toe via de landelijke Capaciteitskaart (Netbeheer Nederland ArcGIS). Toont status van het elektriciteitsnet op deze locatie.

## `includeGewasrotatie` (type: `boolean`):

Vraag gewasrotatie uit een oudere jaargang aan. Let op: de BRP-bron serveert momenteel alleen de laatste snapshot (peildatum 15 mei), dus vorigGewas blijft voorlopig null.

## `bronnenFilter` (type: `array`):

Optioneel: filter op specifieke BRP-gewascodes (bijv. \['259' = tarwe, '2659' = mais). Zonder filter worden alle gewassen getoond.

## Actor input object example

```json
{
  "query": "Emmeloord",
  "queries": [
    "Emmeloord",
    "Dronten"
  ],
  "concurrency": 3,
  "includeBodemrisico": true,
  "includeNetcongestie": true,
  "includeGewasrotatie": false
}
```

# Actor output Schema

## `results` (type: `string`):

Alle perceeldossiers in het default dataset.

# 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": "Emmeloord",
    "queries": [
        "Emmeloord",
        "Dronten"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("codeclouds/nl-perceel-dossier-xxl").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": "Emmeloord",
    "queries": [
        "Emmeloord",
        "Dronten",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("codeclouds/nl-perceel-dossier-xxl").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": "Emmeloord",
  "queries": [
    "Emmeloord",
    "Dronten"
  ]
}' |
apify call codeclouds/nl-perceel-dossier-xxl --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,codeclouds/nl-perceel-dossier-xxl"
        }
    }
}

```

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/zvXI8wY3Blg7gbFRB/builds/XdHvO0JoQgWoRZfEM/openapi.json
