# DUO open onderwijsdata

Alle scholen en opleidingen met adres, en per schoolvestiging het aantal leerlingen, schooladviezen, doorstroomtoetsscores, examencijfers en prognoses. Van basisschool tot universiteit. DUO publiceert het als downloads en als API (56 datasets met 274 tabellen in de datastore op 16 oktober 2026).

- Uitgever: Dienst Uitvoering Onderwijs
- Gebied: Nederland · Laagste detail: schoolvestiging
- Periode: 2010 – heden · Ververst: dagelijks
- Toegang: Open · Licentie: CC BY (volgens de catalogus van DUO)
- Koppelsleutels: instellingscode (BRIN), vestigingscode, gemeentenummer, postcode
- Status: ok (2026-10-16) · 56 datasets · nieuwste wijziging: RIO nfo, po, vo, vavo, mbo en ho
- URL: https://duo.nl/open_onderwijsdata/

## Wat kun je ermee?
- **Welk advies krijgen kinderen op jouw basisschool?.** Tel per vestiging de schooladviezen per jaar (sinds 2010) en vergelijk de school met andere scholen in de gemeente.
- **Krimp en groei per school.** Leerlingen per vestiging staan er van 2010 tot en met 2025. Zoek scholen die in tien jaar de helft van hun leerlingen kwijtraakten.
- **Schooladvies naast de buurt.** Koppel vestigingen via postcode of gemeentenummer aan inkomen en opleiding uit de CBS-kerncijfers. Krijgen kinderen in armere buurten lagere adviezen?
- **Waar komen de leerlingen vandaan?.** Het bestand naar postcode4 laat per vestiging zien uit welke postcodegebieden de leerlingen komen. Zo meet je hoe ver ouders reizen voor een school.

## Zo verwerk je het
1. **Zoek de dataset in de catalogus.** De catalogus is een CKAN-portaal. Zoek op een woord en kijk bij elke dataset welke bestanden (resources) erbij horen.
   `https://onderwijsdata.duo.nl/api/3/action/package_search?q=advies&rows=5`
2. **Vraag rijen op via de datastore.** Elk CSV-bestand staat ook in de datastore. Met resource_id, filters en sort haal je alleen wat je nodig hebt. Dit voorbeeld: schooladviezen van één school in 2024.
   `https://onderwijsdata.duo.nl/api/3/action/datastore_search?resource_id=454c5dd4-6815-4b52-ae2f-b9eebc6afa6d&filters=%7B%22INSTELLINGSCODE%22%3A%2200AP%22%2C%22PEILJAAR%22%3A2024%7D`
3. **Of download het hele bestand.** Voor een volledige analyse is de CSV handiger. Sommige downloadlinks in de catalogus wijzen naar een interne server (beheer-ggm-ckan-prd…); vervang de host door onderwijsdata.duo.nl.
   `https://onderwijsdata.duo.nl/dataset/d6903313-8c64-4b12-b4ac-07e5655ef9f4/resource/454c5dd4-6815-4b52-ae2f-b9eebc6afa6d/download/brin6_advies.csv`
4. **Koppel aan adressen.** Leerlingbestanden hebben alleen instellingscode en vestigingscode. Naam, adres, postcode en gemeentenummer staan in de adressenbestanden (bijvoorbeeld alle vestigingen in het basisonderwijs).
   `https://onderwijsdata.duo.nl/api/3/action/datastore_search?resource_id=dcc9c9a5-6d01-410b-967f-810557588ba4&limit=5`
5. **Haal de kleine aantallen eruit.** Een -1 betekent 1 tot 4 leerlingen (afgeschermd). Tel die niet mee als getal; reken met een onder- en bovengrens of laat ze weg.
6. **Erkende opleidingen in het hoger onderwijs.** Het Overzicht Erkenningen ho (CC BY) geeft per instelling, vestiging en opleiding de erkenning, accreditatiedata, studielast, graad en status, actueel en historisch: 74.173 rijen op 16 oktober 2026. Deze dataset staat alleen in de catalogus van DUO, niet op data.overheid.nl.
   `https://onderwijsdata.duo.nl/api/3/action/datastore_search?resource_id=28a4d89b-c223-4dbc-8deb-9d02a533f215&limit=5`

## Interessante koppelingen
- Hangt het schooladvies samen met het inkomen in de gemeente? → [cbs-kwb](https://www.opendataindex.nl/bron/cbs-kwb.md) via gemeentenummer (GM). Zet GM voor het gemeentenummer uit het adressenbestand (1699 wordt GM1699) en koppel aan de kerncijfers van hetzelfde jaar.
- In wat voor gebouwen zitten de scholen? → [pdok-bag](https://www.opendataindex.nl/bron/pdok-bag.md) via postcode + huisnummer. Zoek het adres van elke vestiging op in de BAG voor bouwjaar en oppervlakte.

## Vergelijkbare bronnen
- [cbs-statline](https://www.opendataindex.nl/bron/cbs-statline.md): CBS heeft onderwijscijfers per gemeente en landelijk, niet per school.
- [Scholen op de kaart](https://scholenopdekaart.nl/): Schoolprofielen voor ouders, op basis van onder meer DUO-gegevens. Een website, geen dataset.

## Waar je op moet letten
- **Aantallen onder de 5 zijn afgeschermd.** In de API staat dan -1, in sommige bestanden '<5'. Bij kleine scholen is dat een groot deel van de cellen.
- **Niet elke dataset is actueel.** De registratie van scholen en opleidingen (RIO) wordt elke dag ververst, leerlingtellingen eens per jaar (peildatum 1 oktober). Examencijfers per vestiging in de API lopen tot schooljaar 2017 (stand 15 oktober 2026).
- **Codes zonder uitleg in de API.** Het veld ADVIES is een getal (bijvoorbeeld 5, 7 of 11), geen tekst. Zoek de betekenis op bij DUO voor je telt.
- **Geen SQL op de datastore.** datastore_search_sql geeft 'Geen toegang'. Groeperen en tellen doe je zelf, na het ophalen.
- **Niet alles staat ook op data.overheid.nl.** Een paar datasets staan alleen in de DUO-catalogus, zoals het Overzicht Erkenningen ho en Sectorale Ontwikkelpaden (welke opleidingen bij een ontwikkelpad horen en of er SLIM-subsidie mogelijk is). Bij Sectorale Ontwikkelpaden staat geen licentie in de catalogus (16 oktober 2026): licentie niet vastgesteld.

## API (CKAN (Action API v3 + datastore))

- Basis: https://onderwijsdata.duo.nl/api/3/action
- Toegang: Geen sleutel of account nodig (getest)
- Formaten: json, csv
- Omvang: 274 tabellen in de datastore (van 290 bestanden in 56 datasets) (getest)
- Filteren: Geen querytaal: gelijk-aan-filters als JSON in filters (waarde of lijst van waarden), plus vrij zoeken met q. Geen groter-dan of kleiner-dan; datastore_search_sql is uitgeschakeld.; = (filters), IN (lijst in filters), q (vrij zoeken)

### Endpoints
- `GET /package_list`: Namen van alle 56 datasets (bv. adressen_bo, 03_voex-v1, historische-leerlingenaantallen-po).
- `GET /package_search?q=…&fq=…&rows=…`: Zoeken in de catalogus; met rows=0 alleen het aantal. Geeft per dataset ook alle resources (bestanden) met id, formaat en datastore_active.
- `GET /package_show?id={naam}`: Eén dataset: beschrijving, licentie, metadata_modified en de resources met hun resource_id en download-URL.
- `GET /resource_show?id={resource_id}`: Eén bestand: naam, formaat, last_modified, download-URL.
- `GET /group_list`: De acht onderwerpgroepen (basisonderwijs, voorgezet-onderwijs, hoger-onderwijs, inburgering …).
- `GET /group_show?id={groep}`: Eén groep met titel en beschrijving.
- `GET /datastore_search?resource_id={id}`: De rijen van één tabel, met filters, vrij zoeken, sorteren, kolomkeuze en paginering. Het antwoord noemt ook de kolommen met type.
- `GET /dataset/{dataset-id}/resource/{resource_id}/download/{bestand}.csv`: Het hele bestand als CSV (pad zonder /api/3/action, op https://onderwijsdata.duo.nl).

### Parameters
- `resource_id`: Verplicht bij datastore_search: de id van het bestand (uit package_show). (getest)
- `filters`: Gelijk-aan-filter per kolom als JSON, ook met een lijst: {"PEILJAAR":[2023,2024]}. Kolomnamen exact zoals in fields (soms met spaties: "BEVOEGD GEZAG NUMMER"). (getest)
- `q`: Vrij zoeken in alle kolommen, of per kolom: {"PLAATSNAAM":"utrecht"} (woordovereenkomst, niet hoofdlettergevoelig). (getest)
- `fields`: Alleen deze kolommen, kommagescheiden. (getest)
- `sort`: Sorteren, bv. PEILJAAR desc. (getest)
- `limit`: Aantal rijen; standaard 100 (CKAN). 40.000 werd gewoon geleverd; limit=0 geeft alleen total en kolommen. (getest)
- `offset`: Paginering; het antwoord heeft _links.next met de volgende pagina. (getest)
- `records_format`: objects (standaard), lists of csv (rijen als één CSV-tekst, zonder kop). (getest)
- `include_total`: false slaat het tellen over (sneller bij grote tabellen). (getest)
- `q / fq / rows / start / sort (package_search)`: Solr-zoeken in de catalogus: fq=groups:basisonderwijs (24 datasets), sort=metadata_modified desc. (getest)

### Velden in de datastore (selectie: schooladviezen en adressen basisonderwijs) (8)
`INSTELLINGSCODE` text, `VESTIGINGSCODE` text, `PEILJAAR` numeric, `ADVIES` numeric, `AANTAL_LEERLINGEN` numeric, `GEMEENTENUMMER` text, `POSTCODE` text, `_id` int

### Limieten en valkuilen
- Geen sleutel en geen gedocumenteerde rate limit. Standaard 100 rijen per aanroep; een limit van 40.000 werd geleverd. Pagineer met offset of _links.next. (getest)
- Alleen een deel van de CKAN-acties staat open (package_list, package_search, package_show, resource_show, group_list, group_show, datastore_search). (getest)
- Andere CKAN-acties (status_show, organization_list, tag_list, datastore_info, help_show) geven HTTP 200 met de HTML van de website, geen JSON-fout. Controleer altijd of het antwoord JSON is. datastore_search_sql geeft 400 "Action name not known". (getest)
- distinct=true telt goed (total 15 peiljaren in de schooladviezen) maar gaf maar één rij terug. Gebruik voor unieke waarden liever een kleine kolomselectie met een hoge limit. (getest)
- AVG: aantallen van 1 tot 4 staan als -1 in de API (in sommige bestanden als <5). Niet optellen als getal. (getest)
- Negen download-URL's in de catalogus wijzen naar een interne host (beheer-ggm-ckan-prd.apps.prd.duo.rijksapps.nl) die buiten DUO niet bestaat; vervang de host door onderwijsdata.duo.nl. (getest)
- Leerlingbestanden hebben alleen BRIN en vestigingscode; naam, adres en gemeente koppel je via de adressenbestanden (adressen_bo, adressen_vo …). Gemeentenummer zonder GM: plak er GM en voorloopnullen voor om met CBS te koppelen. (ervaring)
- Resource-id's veranderen niet bij een nieuwe levering; metadata_modified van de dataset en last_modified van de resource geven de versheid (adressen worden dagelijks ververst). (ervaring)

### Voorbeeld
```
https://onderwijsdata.duo.nl/api/3/action/datastore_search?resource_id=454c5dd4-6815-4b52-ae2f-b9eebc6afa6d&filters=%7B%22PEILJAAR%22%3A2024%7D&sort=AANTAL_LEERLINGEN%20desc&limit=3
```

## Zo haal je het op

### curl
```bash
curl -G "https://onderwijsdata.duo.nl/api/3/action/datastore_search" --data-urlencode "resource_id=454c5dd4-6815-4b52-ae2f-b9eebc6afa6d" --data-urlencode "filters={\"PEILJAAR\":2024}" --data-urlencode "limit=5"
```

### python
```python
import requests

r = requests.get("https://onderwijsdata.duo.nl/api/3/action/datastore_search", params={
    "resource_id": "454c5dd4-6815-4b52-ae2f-b9eebc6afa6d",  # schooladviezen per vestiging
    "sort": "PEILJAAR desc", "limit": 5})
for rij in r.json()["result"]["records"]:
    print(rij["INSTELLINGSCODE"], rij["VESTIGINGSCODE"], rij["PEILJAAR"], rij["ADVIES"], rij["AANTAL_LEERLINGEN"])
```

## Wat je ermee kunt bouwen
- [Schoolkeuzehulp: basisscholen rond je adres, met leerlingen en schooladviezen](https://www.opendataindex.nl/bouwen/schoolkeuzehulp.md): Typ een postcode en huisnummer en zie alle basisscholen binnen een straal, op afstand gesorteerd, met hun leerlingenaantal door de jaren en welk deel van de kinderen een havo- of vwo-advies kreeg. Alleen open data van DUO en de BAG.


## Wat er allemaal in zit: 348 datasets en tabellen

Alle datasets in de catalogus van DUO, per onderwerp zoals DUO ze indeelt, met elk bestand erbij, elke nacht opgehaald. Elke tabel heeft een eigen pagina met het aantal rijen, de kolommen en de API-aanroep.

- Soorten: tabel 276, dataset 56, bestand 16
- Laatst gewijzigd: 2026-10-30 (154 in de afgelopen 30 dagen)
- Met een API-aanroep op de datasetpagina: 348
- Zoeken: https://www.opendataindex.nl/api/catalogus/duo?q=… of de MCP-functie zoek_datasets met herkomst=duo
- Elke rij heeft een eigen pagina: https://www.opendataindex.nl/dataset/duo/<sleutel>

### Mappen
- Arbeidsovereenkomst en cao (5): Functiemix (5)
- Basisonderwijs (74): Adressen van hoofdvestigingen, vestigingen en besturen in het basisonderwijs (4), Adressen van instellingen, vestigingen en besturen in het speciaal onderwijs (4), Gemiddelde eindscores per vestiging bo en sbo (2), Heroverwegingen en bijgestelde adviezen bo en sbo (2), Historische leerlingenaantallen PO (3), Kwaliteitsoordelen bevoegde gezagen, po, so en vo (3), Leerlingen bo en sbo per vestiging naar advies (2), Leerlingen bo en sbo per vestiging naar leerjaar (2) …
- Hoger onderwijs (38): Adressen in het hoger onderwijs (3), Eerstejaars ingeschrevenen hoger onderwijs in het domein hoger onderwijs (7), Gediplomeerden in het hoger onderwijs in het domein soort diploma soort hoger onderwijs (7), HO Opleidingsoverzicht (3), Ingeschrevenen hoger onderwijs in het domein hoger onderwijs (7), Inschrijvingen in het hoger onderwijs (7), Overzicht Erkenningen ho (4)
- Inburgering (3): WI 2021 Instroom, Uitstroom en Leerroute (3)
- Middelbaar beroepsonderwijs (43): Adressen mbo (3), MBO Opleidingsaanbod (4), Studentprognoses mbo per instelling (36)
- Speciaal onderwijs en leerproblemen (55): Aantal leerlingen per cluster per schoolvestiging (2), Adressen van instellingen, vestigingen en besturen in het speciaal onderwijs (4), Gemiddelde eindscores per vestiging bo en sbo (2), Heroverwegingen en bijgestelde adviezen bo en sbo (2), Historische leerlingenaantallen PO (3), Kwaliteitsoordelen bevoegde gezagen, po, so en vo (3), Leerlingen bo en sbo per vestiging naar advies (2), Leerlingen bo en sbo per vestiging naar leerjaar (2) …
- Voortgezet onderwijs (33): Aantal afgenomen examens en gemiddelde examencijfers per vak per vestiging (2), Aantal leerlingen per cluster per schoolvestiging (2), Adressen van instellingen, vestigingen en besturen in het voortgezet onderwijs (4), Kwaliteitsoordelen bevoegde gezagen, po, so en vo (3), Leerlingen po per gemeente (5), Leerlingen po per samenwerkingsverband (5), Leerlingen SO en VSO (4), Prognoses vo per instelling (2) …
- Zonder groep (165): Changelog van HO Opleidingsoverzicht (2), Changelog van MBO Opleidingsaanbod (2), Changelog van Overzicht Erkenningen HO (2), Changelog van RIO nfo po vo vavo mbo ho (11), Changelog van Sectorale Ontwikkelspaden (2), Gediplomeerde mbo-studenten (2), Het toegestane voortgezet onderwijs per schoolvestiging en leerjaar. (2), Instromende mbo-studenten (11) …

## Voorbeelden met echte cijfers (2)

Per voorbeeld de bevinding, de peildatum en de aanroep die precies deze cijfers ophaalt.

- **Leerlingen in het basisonderwijs: 1,36 miljoen in 2025/26, 10% minder dan in 1996/97** (2025/26). Tabel 947ecf4a-3744-4f59-ad98-6ce4107dafa2. [Voorbeeld](https://www.opendataindex.nl/voorbeeld/duo-leerlingen-basisonderwijs)
  - `https://onderwijsdata.duo.nl/api/3/action/datastore_search?resource_id=947ecf4a-3744-4f59-ad98-6ce4107dafa2&filters=%7B%22SOORT_VESTIGING%22%3A%22BO%22%7D&fields=SCHOOLJAAR%2CAANTAL_LEERLINGEN&limit=32000`
- **Mbo-studenten per opleidingsrichting: het meest Zorg en welzijn (141.737 studenten), dan Economie en administratie en Techniek en procesindustrie** (oktober 2025). Tabel da6669b9-5894-4ba6-9ba4-bfd42f8d3387. [Voorbeeld](https://www.opendataindex.nl/voorbeeld/duo-mbo-studenten-hoofdgroep)
  - `https://onderwijsdata.duo.nl/api/3/action/datastore_search?resource_id=da6669b9-5894-4ba6-9ba4-bfd42f8d3387&limit=10000`
