# Netherlands Childcare Register - Nursery & Daycare Leads (`scrapersdelight/lrk-childcare-nl-scraper`) Actor

From $1.20 per 1,000 locations, no start fee. The official Dutch LRK register: 18,399 registered nurseries, out-of-school care sites and childminder agencies with email (97.5% filled), phone, website, named contact, licensed child places, operator KvK number and coordinates.

- **URL**: https://apify.com/scrapersdelight/lrk-childcare-nl-scraper.md
- **Developed by:** [Scrapers Delight](https://apify.com/scrapersdelight) (community)
- **Categories:** Lead generation, Business, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$1.20 / 1,000 per childcare location returneds

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

## Netherlands Childcare Register (LRK) scraper

Exports the Netherlands' official **Landelijk Register Kinderopvang** — the register every Dutch
childcare location must be listed in before it is allowed to open — as a clean B2B lead table.

**Price: $0.0012 per location delivered ($1.20 per 1,000), no run-start fee.** Rows your filters
exclude are never delivered and never charged.

***

### The numbers, all counted on 2026-09-16

Not estimates. The national totals come from sweeping **all 342 gemeente codes** and fetching the
**last page of each** so rows are counted rather than inferred from page totals. The field-fill
numbers come from **1,493 deduped real records** captured across 118 pages — 60 randomly-drawn
municipalities, each contributing its page 1 plus one randomly-drawn deeper page.

| | measured |
|---|---|
| Registered childcare locations (KDV + BSO + GOB) | **18,399** across 1,389 pages |
| Whole register, any status and type | 78,452 across 5,386 pages |
| Gemeenten resolved in the sweep | 342 of 342, 0 unresolved |
| Locations per operating company | 3.72 (401 distinct operators across 1,493 rows) |

#### Field fill on the registered KDV/BSO/GOB slice (n = 1,493)

Counting rule: a literal `"N/A"`, `"-"`, `"Onbekend"` or an empty string is **not** filled.

| field | filled | % |
|---|---|---|
| `locationId`, `lrkNumber`, `name`, `type`, `registrationStatus`, `registeredSince` | 1,493 | **100.0%** |
| `street`, `houseNumber`, `postalCode`, `city`, `fullAddress`, `municipality` | 1,493 | **100.0%** |
| `childPlaces` (licensed capacity) | 1,493 | **100.0%** |
| `operatorId` | 1,493 | **100.0%** |
| `latitude` / `longitude` | 1,489 | **99.7%** |
| `correspondenceAddress` | 1,477 | **98.9%** |
| `email` | 1,456 | **97.5%** |
| `contactPerson` (a named human) | 1,434 | **96.0%** |
| `phone` | 1,406 | **94.2%** |
| `website` | 1,341 | **89.8%** |
| `establishmentNumber` (KvK vestigingsnummer) | 1,125 | **75.4%** |
| email **and** phone | 1,384 | **92.7%** |
| email **or** phone | 1,478 | **99.0%** |

#### Operator columns (`includeOperatorDetails`, on by default)

Measured row-level over the 536 sample rows whose operator was actually looked up, and
holder-level over 182 distinct operators:

| field | filled | % |
|---|---|---|
| `operatorKvkNumber` | 536 / 536 | **100.0%** |
| `operatorName` | 536 / 536 | **100.0%** |
| `operatorDisputesCommitteeSince` | 535 / 536 | 99.8% |
| `operatorLegalForm` | 428 / 536 | **79.9%** |

(The live 393-row Utrecht run came out at `operatorKvkNumber` 100.0%, `operatorName` 100.0%,
`operatorLegalForm` 96.4% — Utrecht is corporate-heavy. The table above is the national sample,
which is the conservative number and the one to plan against.)

`operatorLegalForm` is the one that is *not* near-total, and it fails in two distinct ways: the
register records a legal form only for a legal entity (present on 120 of 120 corporate holders,
**0 of 62** sole-trader holders), and 7 of those 120 say `"Onbekend"` — its own filler — which is
emitted as `null`, not as a legal form. `operatorAddress` follows the same corporate-only pattern.

See trap 3 below for why the 100% KvK figure is only reachable one particular way.

***

### The single most important thing about this register

**That 97.5% email fill exists only behind the filter.** Measured on a 300-record sample taken
with **no** status or type filter, from the same 20 municipalities:

| slice | n | email | phone |
|---|---|---|---|
| everything, unfiltered | 300 | **15.7%** | 14.3% |
| `UITGESCHREVEN` (deregistered) | 205 | **0.0%** | 0.0% |
| `VGO` (home-based childminders) | 235 | **1.3%** | 0.4% |
| `KDV` (day nurseries) | 22 | 86.4% | 77.3% |
| `BSO` (out-of-school care) | 43 | 58.1% | 58.1% |

The register **strips contact details on deregistration** — all 205 deregistered rows, zero
exceptions — and **privacy-suppresses home-based childminders**, who are private households rather
than businesses. A scraper that walks the register naively ships an email column that is ~84%
empty and looks broken.

So this actor defaults to `includeTypes: ["KDV","BSO","GOB"]` and
`registrationStatus: "INGESCHREVEN"`. Both filters are applied **server-side**, which also cuts the
national walk from 5,386 pages to 1,389 — a 3.9x cost reduction on top of the quality gain.

***

### What you get per row

`locationId` · `lrkNumber` · `name` · `type` + `typeLabel` · `registrationStatus` ·
`registeredSince` · `childPlaces` · `preschoolEducation` · `parentRunCreche` ·
`contactPerson` · `email` · `phone` · `website` ·
`street` · `houseNumber` · `postalCode` · `city` · `fullAddress` · `municipality` ·
`correspondenceAddress` · `correspondencePoBox` · `correspondencePostalCode` · `correspondenceCity` ·
`latitude` · `longitude` · `rdX` · `rdY` ·
`establishmentNumber` ·
`operatorId` · `operatorName` · `operatorKvkNumber` · `operatorLegalForm` · `operatorLegalFormRaw` ·
`operatorDisputesCommitteeSince` · `operatorAddress` ·
`inspectionId` · `apiUrl` · `scrapedAt`

Why `childPlaces` is the interesting column: it is the **licensed capacity**, i.e. a firmographic
size signal a Dutch childcare SaaS can price against. Measured means: KDV 34.0 places, BSO 41.5,
both with a minimum of 5. GOB agencies license 0 by definition (all 28 zero-capacity rows in the
sample were GOB, none were KDV or BSO) — that 0 is real and is not nulled.

***

### Fields that were CUT, and why

These are in the source and are **not** shipped, because they are not populated:

- **`historischeNamen` (former names)** — an empty array on **1,493 of 1,493** rows. Cut entirely.
- **A human-facing register link.** The LRK public site is a Vue SPA and the server does **not**
  rewrite deep paths to the app shell: `/pp/inzien/oko/gegevens/<uuid>`,
  `/pp/inzien/houder/<uuid>/<kvk>` and `/pp/inspectierapport/<uuid>/<id>` — the app's own routes,
  read out of its JS bundle — each redirect a cold load to `/storing/index.html`, a maintenance
  page, **with HTTP 200**. A `registerUrl` column would have been 100% broken links, so the actor
  emits `apiUrl` instead, which was verified: HTTP 200, 1,193 bytes, the same record.
- **`houderDatumAanvang`** — the only field the per-location detail endpoint adds. It costs one
  extra request per location and the detail response actually **drops** `inspectie`, which the list
  already carries. Strictly worse per request, so no N+1 detail call is made.

And one field that ships but is deliberately **not** advertised: `parentRunCreche` (`opc`,
parent-run crèche) was `false` on **1,493 of 1,493** rows. It is present and unambiguous, so it is
emitted — but a column that never varies is not a selling point and is not claimed as one.

***

### The traps this build had to get right

Each one was verified against live bytes; the captured responses are in `fixtures/` and
`offline_validate.mjs` asserts against them.

1. **The documented query string is dead.** `?plaats=&soort=` returns **HTTP 400**, body verbatim:
   `[PARAMETER]\r[voorzieningenRead.arg7]\r[size must be between 2 and 2147483647]\r[]`. An
   *empty* search parameter is rejected outright — at least one non-empty one is mandatory.
2. **The `Accept` header trap runs the opposite way from the obvious.** `Accept: application/json`
   → **HTTP 500** `{"title":"COMMON","status":500,"code":"9999"}`, and `Accept: text/html` → the
   same 500. `application/hal+json` → 200. (No `Accept` header at all also → 200, so the rule is
   "never send a non-HAL `Accept`".)
3. **The KvK rollup is behind a link that looks wrong.** A row carries **two different** holder
   uuids: the `houder` **field** and `_links.houder.href`. They differ on **97 of 1,493** rows and
   both return HTTP 200. Measured across 244 holder requests:
   `/houders/<houder FIELD>` → `kvkNummer` on **182 of 182 (100.0%)**;
   `/houders/<HAL link uuid>` → `kvkNummer` on **0 of 62 (0.0%)**, silently absent.
   Following the HAL link is the obvious move and loses the field entirely.
4. **`status=INGESCHREVEN` leaks.** 1 of 1,493 returned rows carried `AANGEMELD`. Worse,
   `status=AANGEMELD` is itself rejected with HTTP 400 — the register *publishes* a status it
   *refuses* as a filter. The actor re-asserts status and type client-side and counts what it drops
   in `RUN_SUMMARY`; dropped rows are never delivered and never charged.
5. **`vestigingsNummer` is not unique.** 1,125 filled values held only **837 distinct** — a KDV and
   a BSO at the same site share one KvK establishment number. Deduplication uses `identificatie`
   (1,493 unique of 1,493); `lrkNumber` is equally unique.
6. **Coordinates are Rijksdriehoek, not lon/lat.** `locatie.coordinates` ranged x 68,953–274,916
   and y 308,121–591,813. Published as "longitude, latitude" every Dutch nursery would land off the
   coast of Somalia. They are converted with the Schreutelkamp / Strang van Hees polynomial (0.0 m
   error at the Amersfoort origin, 0.9 m at the Groningen Martinitoren) and the raw RD pair is kept
   as `rdX`/`rdY`. 0 of 1,489 converted rows fell outside the Netherlands.
7. **House numbers are split across three keys.** 198 of 1,493 addresses use `huisnummer` + `letter`
   (192) + `toevoeging` (7). Joining only `huisnummer` emits a wrong address silently.
8. **The correspondence address has two mutually exclusive shapes.** Of the 1,477 rows that carry
   one, 494 use `postbusnummer` (a PO box) and 983 use street+number — 494 + 983 = 1,477 exactly.
   A naive street join drops a third of them to null.
9. **A 200 can carry a block page.** Deep paths on this site answer HTTP 200 with a Dutch
   maintenance page ("Onderhoudswerkzaamheden … niet bereikbaar"). The walk classifies the *body*,
   not the status code, and treats that as a transport failure — not as end-of-data.
10. **Out-of-range pages return HTTP 200 with an empty array, never 404.** Page 60 of a 59-page
    result is a normal, empty envelope. A loop that terminates on a status code never terminates.
11. **`rechtsvorm` is spelled three ways.** Across 120 holders: "Besloten Vennootschap" 59, "BV" 8,
    "BeslotenVennootschap" 6; "Vennootschap Onder Firma" 7, "VOF" 5, "VennootschapOnderFirma" 5.
    Both a folded `operatorLegalForm` and the untouched `operatorLegalFormRaw` are shipped.

***

### Speed, proxies and the concurrency inversion

The origin **resets connections above ~2 requests in flight from a single IP**. Measured cleanly,
24 requests each, nothing else running:

| source | conc 1 | conc 3 | conc 6 | conc 8 | conc 12 |
|---|---|---|---|---|---|
| one IP (no proxy) | 24/24 | 18/24 | 12/24 | — | — |
| Apify Proxy, datacenter, fresh session per request | — | — | — | **48/48** | 47/48 |
| Apify Proxy, residential NL, fresh session per request | — | — | — | 22/24 | — |

The failures on a single IP are TCP connection resets, never HTTP statuses — so a scraper that
only checks status codes reads them as nothing at all.

Two consequences, both baked in:

- **The default proxy is Apify datacenter, not residential.** Residential was measurably *worse*
  here (22/24 vs 48/48) and buys nothing: this register has no CAPTCHA, no Cloudflare, no JS
  challenge, no cookie gate and no auth. Page bodies are ~17.8 KB decompressed / ~2.5 KB on the
  wire, far below the size where a datacenter-proxy body truncates mid-stream, so the integrity
  guard here is the page-count reconciliation rather than a byte-length check.
- **With no proxy the actor forces concurrency to 1** and says so in the log, rather than running
  at 8 and quietly shedding a third of the register.

Measured throughput at concurrency 8 through Apify datacenter proxy: **3.77 req/s** in isolation,
**3.2 req/s** on a real end-to-end run including operator lookups.

Real runs against the live register through Apify Proxy, on the real Apify SDK:

| input | wall | rows | result |
|---|---|---|---|
| **All of gemeente Utrecht, no cap, operator details on** | **36 s** | **393** | `complete: true`, 27 of 27 pages, 393 distinct ids, 100% email, 99.5% phone, **100% operator KvK**, 0 unreachable |
| Utrecht, cap 50 — the daily health-test input | 12–25 s | 50 | 100% email, phone and operator KvK |
| Utrecht, `requireEmail`, cap 30 | 7 s | **exactly 30** | the cap counts delivered rows, not fetched ones |
| Utrecht, `minChildPlaces: 60`, cap 20 | 6 s | **exactly 20** | ditto, on a filter that rejects most rows |
| 3 small municipalities, no cap | 21 s | 51 | `complete: true`, 6 of 6 pages, 100% operator KvK |
| One municipality, **proxy off** | 3 s | 20 | concurrency auto-dropped to 1, warned in the log |
| A name that matches nothing | 4 s | 0 | 0 delivered, **0 charged**, reported as a real empty result |

The 393-row run is also the coverage proof: 393 is exactly the number the independent 342-gemeente
corpus sweep counted for Utrecht. Two of those runs hit a transient proxy error mid-walk
(`ECONNRESET`, and a TLS socket disconnect); both were retried on a fresh proxy session and both
runs finished with **zero unreachable pages**.

Extrapolating the 393-row run (115 requests in 36 s), a **complete national export** — 1,389 pages
plus roughly 5,000 operator lookups — lands around **30–45 minutes**. Turning
`includeOperatorDetails` off cuts that to about 8 minutes. The actor's default run timeout is 2
hours, so either fits.

***

### Cost

At 512 MB the full national run is ~0.2 compute units and ~5 MB of proxy traffic — around **$0.05
of platform usage for 18,399 rows**, about $0.0000027 per row. The $0.0012 price is a lane
decision, not a cost floor.

***

### Honest limits

- **Not a Chamber of Commerce extract.** `operatorKvkNumber` is the operator's KvK number as the
  childcare register holds it; it is not validated against the KvK's own register, and no turnover,
  employee count or director data is available here.
- **`establishmentNumber` is 75.4% filled and not unique** (see trap 5). Treat it as an enrichment
  key, not a primary key.
- **`operatorLegalForm` is 79.9%, not near-total.** Sole-trader operators have no legal form in the
  register at all, and 7 of 120 corporate holders record it as `"Onbekend"`. See the operator table
  above.
- **Coordinates are derived, not published as lat/lon.** The conversion is accurate to roughly a
  metre, which is fine for mapping and radius work and is not a survey-grade position.
- **`GOB` rows are agencies, not sites.** They carry contact data (they are businesses) but license
  0 child places. Set `minChildPlaces: 1` to exclude them.
- **`VGO` rows are households.** They are available (`includeTypes`) but 98.7% of them publish no
  email. They are off by default for that reason.
- **One country, one register.** Only the Netherlands; there is no equivalent call for BE/DE here.
- **The register is rebuilt continuously.** A page fetched mid-walk can shift by a row or two; the
  actor warns on a short non-final page rather than truncating, and reconciles pages read against
  the page count the register itself reported.
- **Not verified under sustained multi-hour load, and never run inside an Apify container.** The
  runs in the table above are real, on the real SDK, through Apify Proxy — but from a local
  machine, not from a platform run. The longest continuous exercises were a full 342-gemeente sweep
  (672 requests, 147 s) and a 1,327-request corpus count, both with zero unresolved municipalities.
  A ~20-minute national run with operator enrichment has not been run end to end.

### robots.txt

`https://www.landelijkregisterkinderopvang.nl/robots.txt` returns, verbatim:

```
User-agent: *
Disallow: /
```

The data itself is the Dutch government's public childcare register, published under the Wet
kinderopvang so that parents and businesses can look it up, and the `/pp-api/v1/` endpoints this
actor uses are the same public API the register's own website calls from the browser. No
authentication, no rate-limit headers, no terms gate. Flagging the robots line here because it is
what the file says; the decision to publish is the operator's.

***

### Files

- `src/query.js` — URL building, the gemeente lookup, and every 400/500 trap encoded as a comment
  with the response that produced it.
- `src/walk.js` — pagination, the maintenance-page classifier, concurrency via `pool.js`.
- `src/transform.js` — the record shape, the RD→WGS84 conversion, and every counted data defect.
- `src/main.js` — scope resolution, billing, floor assertions, `RUN_SUMMARY`.
- `fixtures/` — the real bytes all of the above was written against, captured 2026-09-16.
- `offline_validate.mjs` — `node offline_validate.mjs`. No network, no platform, no `node_modules`.

# Actor input Schema

## `municipalities` (type: `array`):

Municipality names as the register spells them ('s-Gravenhage, not Den Haag), or their 1-4 digit CBS codes (363 = Amsterdam). Names are matched case- and accent-insensitively against the register's own /v1/gemeenten table, and an unknown name stops the run with the closest matches listed - because an unknown code returns HTTP 200 with zero rows, which looks exactly like 'no childcare here'. Leave empty together with the other scope fields to cover the whole country.

## `cities` (type: `array`):

Town/city names to search instead of, or alongside, municipalities. Narrower than a municipality: gemeente Amsterdam holds 2,323 records against plaats=Amsterdam's 1,569, because a municipality contains several towns.

## `postalCodes` (type: `array`):

Full Dutch postcodes, for example 1019TZ. Spaces are removed and letters upper-cased for you. Use this for tight catchment-area lists.

## `nameContains` (type: `string`):

Search location names, for example a chain name like Partou or Zazoe. Runs as one extra search on top of any geographic scope.

## `includeTypes` (type: `array`):

KDV = day nursery (ages 0-4). BSO = out-of-school care (ages 4-12). GOB = childminder agency. VGO = an individual registered childminder working from a private home - these are consumer households, not businesses, and the register privacy-suppresses their contact details (measured: 1.3% have an email against 97.5% for the rest), so VGO is OFF by default. The server rejects any other value and rejects lowercase.

## `registrationStatus` (type: `string`):

INGESCHREVEN = currently registered and operating. UITGESCHREVEN = deregistered; the register STRIPS the email and phone from these (measured 0.0% of 205 deregistered rows carried either), so they are useful for churn analysis and useless as leads. ALL returns both. Note AANGEMELD: the register publishes that status but refuses it as a filter, so a few AANGEMELD rows leak through the INGESCHREVEN filter and this actor drops them client-side.

## `requireEmail` (type: `boolean`):

Drop rows with no email address BEFORE they are delivered, so you never pay for them. On the registered KDV/BSO/GOB slice 97.5% of rows carry one, so this removes very little.

## `requireContact` (type: `boolean`):

Looser than the email filter: keeps a row if it has either. Measured 99.0% of registered KDV/BSO/GOB rows qualify.

## `minChildPlaces` (type: `integer`):

Firmographic size filter. Licensed capacity (kindplaatsen) averaged 34.0 for KDV and 41.5 for BSO on 1,493 measured rows; set 50 or 75 to isolate the larger sites. GOB agencies license 0 places by definition and are excluded by any value above 0.

## `preschoolEducationOnly` (type: `boolean`):

Keep only locations offering voorschoolse educatie - municipally funded early-years education. Measured 326 of 1,493 rows (21.8%).

## `includeOperatorDetails` (type: `boolean`):

One extra request per DISTINCT operator - the register averages 3.7 locations per operator, so it adds roughly a quarter to the run time - and returns the operator's legal name, Chamber of Commerce (KvK) number, legal form and disputes-committee registration date. Measured 100% KvK fill across 182 holders. Turn off for the fastest possible run.

## `maxLocations` (type: `integer`):

Hard cap on delivered - and therefore charged - rows. 0 means no cap: the whole scope is read and every row is charged. The complete registered KDV/BSO/GOB register was 18,399 rows on 2026-09-16.

## `maxConcurrency` (type: `integer`):

Measured against the live register: through Apify Proxy with a fresh session per request, 48 of 48 requests succeeded at 8 in flight and 47 of 48 at 12. From a SINGLE IP the origin resets connections above ~2 (24/24 at 1, 18/24 at 3, 12/24 at 6), so if you turn Apify Proxy off this is forced down to 1 and the run gets slower rather than lossy.

## `proxyConfiguration` (type: `object`):

Apify Proxy datacenter (the default) is what was measured fastest and cleanest here: 48/48 requests OK at concurrency 8, against 21-22/24 on residential. Residential is not needed - the register has no CAPTCHA, no Cloudflare and no JS challenge - and its exit nodes were measurably flakier.

## Actor input object example

```json
{
  "municipalities": [
    "Utrecht"
  ],
  "includeTypes": [
    "KDV",
    "BSO",
    "GOB"
  ],
  "registrationStatus": "INGESCHREVEN",
  "requireEmail": false,
  "requireContact": false,
  "preschoolEducationOnly": false,
  "includeOperatorDetails": true,
  "maxLocations": 50,
  "maxConcurrency": 8,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `items` (type: `string`):

One row per registered childcare location: LRK number, name, type, licensed child places, email, phone, website, named contact person, full address, WGS84 coordinates, KvK establishment number, and the operating company with its KvK number and legal form.

## `runSummary` (type: `string`):

RUN\_SUMMARY: pages the register said existed vs pages actually read, rows delivered and charged, counted field fill for this run, what was excluded before delivery and why, and every page that could not be reached - so a partial read is never mistaken for a small register.

# 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 = {
    "municipalities": [
        "Utrecht"
    ],
    "maxLocations": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapersdelight/lrk-childcare-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 = {
    "municipalities": ["Utrecht"],
    "maxLocations": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("scrapersdelight/lrk-childcare-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 '{
  "municipalities": [
    "Utrecht"
  ],
  "maxLocations": 50
}' |
apify call scrapersdelight/lrk-childcare-nl-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,scrapersdelight/lrk-childcare-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/3BR5UZITri4Gb6CRh/builds/nbimbrVWUDejlYodi/openapi.json
