# NL Sound Load Check (`codeclouds/nl-sound-load-check`) Actor

"Check a Dutch address, postcode, or coordinate against official RIVM noise contours for roads, railways, and Schiphol. Returns Lden/Lnight decibel classes for an indicative environmental screening."

- **URL**: https://apify.com/codeclouds/nl-sound-load-check.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 $6.00 / 1,000 locatie 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?

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

## NL Sound Load Check

Check a Dutch address, postcode, place name, or WGS84 coordinate against the official RIVM Atlas Leefomgeving noise-contour layers. The Actor returns separate daytime (`Lden`) and nighttime (`Lnight`) decibel classes for Dutch national roads, the main railway network, and Schiphol. It is designed as a fast, machine-readable first pass for property and environmental due diligence.

The result is deliberately descriptive: it reports what the selected point intersects in the RIVM contour data, with the dataset year attached. It does not replace a municipal noise map, a field measurement, an acoustic report, or a formal assessment under the Dutch Environmental Planning Act (Omgevingswet).

### When should an AI agent use this?

- "Is this Dutch development address inside a 55 dB or higher road-noise contour?"
- "Which RIVM noise contour classes apply at this postcode for daytime and nighttime?"
- "Screen a shortlist of locations near national roads, railways, or Schiphol before commissioning an acoustic study."
- "Return one consistent JSON record per address so another workflow can filter noise-sensitive sites."
- "Add a factual noise-contour check to a real-estate or project-location due-diligence dossier."
- "Compare the road, rail, and aviation layers at a coordinate without downloading a municipal PDF map."

### What this Actor does

- Resolves a Dutch address, postcode, place name, or `lat,lon` input through the official PDOK Locatieserver.
- Queries six current RIVM WFS contour layers: `Lden` and `Lnight` for `wegverkeer` (national roads), `spoor` (main railway network), and `luchtvaart` (Schiphol).
- Uses a server-side `INTERSECTS` point filter and asks RIVM for only the needed properties. This keeps responses small and avoids downloading entire national contour geometries.
- Returns six fixed source-period records, even when a point does not intersect a layer, so downstream agents can distinguish “no contour match” from a missing field or a failed source.
- Includes machine-readable status fields: `controleStatus`, `foutcode`, `fouten`, geocoding confidence, the number of matches, the highest returned class, and the highest dB lower bound.
- Processes up to 50 locations in one run with configurable concurrency.
- Charges only a complete six-layer check; geocoding misses and partial source failures are returned as records but are not charged as a successful location result.

### Input

| Field | Type | Description | Example |
|---|---|---|---|
| `locaties` | array of strings | 1–50 Dutch addresses, postcodes, place names, or WGS84 coordinates (`lat,lon`) | `["Bathseweg 27, Rilland"]` |
| `concurrency` | integer | Number of locations processed in parallel, from 1 to 10 | `3` |

Direct coordinates use the form `lat,lon`, for example `52.37,4.90`. Address and place-name matching is best-effort, so the returned `weergavenaam`, `geocodingScore`, and `geocodingBetrouwbaarheid` should be retained when the result feeds a formal workflow.

### Output

The following compact example shows the shape for a point that matched the road layers and the railway-night layer in the live probe. Other sources are still present with empty `contouren` arrays.

```json
{
  "invoer": "50.7635,5.7063",
  "gevonden": true,
  "controleStatus": "volledig",
  "fout": null,
  "foutcode": null,
  "fouten": [],
  "weergavenaam": "50.7635,5.7063",
  "type": "coordinaat",
  "postcode": null,
  "gemeente": null,
  "provincie": null,
  "lat": 50.7635,
  "lon": 5.7063,
  "rdX": null,
  "rdY": null,
  "geocodingScore": null,
  "geocodingBetrouwbaarheid": "hoog",
  "geluidsbronnen": [
    {
      "bron": "wegverkeer",
      "periode": "Lden",
      "binnenContour": true,
      "contouren": [{ "dbKlasse": 3, "dbBereik": "60 - 65" }],
      "brondatasetJaar": 2016,
      "fout": null
    },
    {
      "bron": "wegverkeer",
      "periode": "Lnight",
      "binnenContour": true,
      "contouren": [{ "dbKlasse": 2, "dbBereik": "50 - 55" }],
      "brondatasetJaar": 2016,
      "fout": null
    },
    {
      "bron": "spoor",
      "periode": "Lden",
      "binnenContour": false,
      "contouren": [],
      "brondatasetJaar": 2016,
      "fout": null
    },
    {
      "bron": "spoor",
      "periode": "Lnight",
      "binnenContour": true,
      "contouren": [{ "dbKlasse": 3, "dbBereik": "50 - 55" }],
      "brondatasetJaar": 2016,
      "fout": null
    },
    {
      "bron": "luchtvaart",
      "periode": "Lden",
      "binnenContour": false,
      "contouren": [],
      "brondatasetJaar": 2016,
      "fout": null
    },
    {
      "bron": "luchtvaart",
      "periode": "Lnight",
      "binnenContour": false,
      "contouren": [],
      "brondatasetJaar": 2016,
      "fout": null
    }
  ],
  "aantalContouren": 3,
  "maxDbKlasse": 3,
  "maxDbOndergrens": 60,
  "isHoogContour": true,
  "bron": "RIVM Atlas Leefomgeving WFS (data.rivm.nl/geo/alo/wfs) + PDOK Locatieserver"
}
```

`foutcode` is `null` on a complete check, `GEEN_GEOCODING_MATCH` when PDOK finds no usable location, `UPSTREAM_ERROR` when one or more source calls fail after retries, and `ONBEKENDE_FOUT` for an unexpected per-location error. A source can fail without stopping the other five sources; inspect `fouten` and `controleStatus` before using the record.

### Use cases

- Early screening for housing, office, school, or development locations near national-road, railway, or Schiphol contours.
- Automating a consistent first pass over a real-estate portfolio before an acoustic consultant is engaged.
- Enriching a project-management or permitting workflow with a clearly dated, factual spatial data point.
- Producing a compact agent tool that can screen a list of addresses and return a red-flag-oriented boolean without interpreting Dutch law.

This Actor does not calculate noise emissions, building attenuation, façade insulation, railway vibration, or wind-turbine noise. It also does not replace a current municipal noise map. A missing contour match means only that the supplied point did not intersect the queried RIVM layer; it is not a guarantee that a location is quiet.

### Pricing

This Actor uses Apify Pay-Per-Event (PPE) pricing:

- **Actor Start:** `$0.00005` (Apify default).
- **`locatie-resultaat`:** `$0.006` per location that geocodes successfully and completes all six RIVM contour checks. Failed or partial checks are not charged as a successful result.
- **`binnen-geluidscontour-signaal`:** `$0.01` additional event when a returned contour has a lower bound of at least 55 dB. This is a data signal, not a legal or health conclusion.

### Legal

The Actor uses the public RIVM Atlas Leefomgeving WFS and the public PDOK Locatieserver. The live WFS capabilities reported no access fee and no access constraint, and no authentication is used. The contour records are geographic environmental data, not a collection of personal profiles. The Actor does not return names, contact details, or individual measurements.

The output is an indicative screening based on the named RIVM dataset. It is not a formal acoustic report, a municipal determination, a permit decision, or legal advice. The dB contour layers currently used are dated 2016; verify the current municipal and provincial data before relying on a result for a permit, housing decision, or legal deadline. Users remain responsible for checking the source terms, attribution requirements, and the applicability of the data to their own use case.

### FAQ

**Q: Does a `binnenContour: false` result mean the location is silent?**

No. It means the point did not intersect that particular RIVM layer at the supplied coordinate. Local traffic, municipal sources, aircraft routes, building shielding, and newer data are outside this check.

**Q: Which noise sources are included?**

The v1 scope contains national roads, the main railway network, and Schiphol, each for `Lden` and `Lnight`. Industry, wind turbines, heat pumps, neighbours, and the RIVM 2024 area-level nuisance indicators are not included in v1.

**Q: How current is the data?**

The six contour layers identify their source data as 2016. The Actor returns `brondatasetJaar: 2016` in every source record so downstream consumers cannot mistake this for a current measurement.

**Q: What happens when one RIVM layer is unavailable?**

The other source checks continue. The record gets `controleStatus: "gedeeltelijk"` (or `"mislukt"` when no source succeeds), an `UPSTREAM_ERROR` code, and a message in `fouten`. No successful-result event is charged.

**Q: Can I use it for a permit application?**

Use it as a pre-screen only. A permit or Omgevingswet assessment normally requires the applicable current source data, local conditions, measurement or modelling assumptions, and a qualified acoustic professional.

### Related Actors

- **[NL Natura2000 Afstandscheck](https://apify.com/codeclouds/nl-natura2000-afstandscheck)** — combines well with this check for Natura2000 proximity during Dutch site screening.
- **[NL AHN Hoogtedata Lookup](https://apify.com/codeclouds/nl-ahn-hoogtedata-lookup)** — adds elevation and above-ground-height context for the same location.
- **[NL Bodemrisico Check](https://apify.com/codeclouds/nl-bodemrisico-check)** — adds official soil-risk information to a property due-diligence workflow.

### Keywords

netherlands, rivm, geluidsbelasting, geluidhinder, noise map, noise contour, sound level, lden, lnight, road noise, railway noise, schiphol, environmental screening, omgevingsvergunning, pdok, open data

### Changelog

#### 0.3.0

- Fixed the Apify input-schema shape for the `locaties` array so cloud builds accept the actor configuration.
- Initial release.
- Geocodes addresses, postcodes, place names, and coordinates through PDOK Locatieserver.
- Checks the six current RIVM road, railway, and Schiphol `Lden`/`Lnight` contour layers.
- Uses compact server-side point intersection queries and returns six uniform source-period results.
- Adds machine-readable per-location and per-source error fields.

# Actor input Schema

## `locaties` (type: `array`):

One to 50 Dutch addresses, postcodes, place names, or WGS84 coordinates (lat,lon) to check against official RIVM noise contours.

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

Number of locations processed in parallel. Each location uses one geocoding request and six small RIVM contour queries.

## Actor input object example

```json
{
  "locaties": [
    "Bathseweg 27, Rilland"
  ],
  "concurrency": 3
}
```

# Actor output Schema

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

All results are stored in the 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 = {
    "locaties": [
        "Bathseweg 27, Rilland"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("codeclouds/nl-sound-load-check").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 = { "locaties": ["Bathseweg 27, Rilland"] }

# Run the Actor and wait for it to finish
run = client.actor("codeclouds/nl-sound-load-check").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 '{
  "locaties": [
    "Bathseweg 27, Rilland"
  ]
}' |
apify call codeclouds/nl-sound-load-check --silent --output-dataset

```

## MCP server setup

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

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/mxEHPfyPwkBPMaR7a/builds/KykH6ycsTtDczqe0Z/openapi.json
