303.525 datasets geïndexeerd1.419 uitgevers
Open Data IndexDe index van open data over Nederland
Open Data Index›Bouwen›Woningmarktdashboard voor je gemeente
DashboardGevorderdWonen en ruimte

Woningmarktdashboard voor je gemeente

Eén pagina per gemeente met verkoopprijzen, WOZ-waarde, woningvoorraad, bouwjaren, woninggrootte en leefbaarheid, naast het landelijk gemiddelde. Alles uit open API's zonder sleutel.

Je AI-assistentOpen Data Index MCP aan
De MCP-server van Open Data Index staat aan in je chat. Zo leest de assistent dit project en de bronnen zelf.
Jij plakt de prompt van dit project
De assistent haalt op bij Open Data Index
  • geef_project("woningmarkt-dashboard")
  • geef_bron("cbs-statline")
  • geef_bron("pdok-bag")
  • geef_bron("leefbaarometer")
De assistent

Ik heb het project, de geteste aanroepen en de valkuilen. Ik bouw een dashboard met CBS StatLine, Basisregistratie Adressen en Gebouwen (BAG) en Leefbaarometer. Zo kan het eruitzien:

Dit bouw je zelf. Kopieer de prompt naar Claude, ChatGPT of Cursor, met de MCP-server aan, of volg de stappen hieronder.

Volg de stappen
WoonpeilGM0503Delft
Verkoopprijs 2025€ 453.866▲ 10,7% op 2024
WOZ-waarde 1 jan 2026€ 393.000▲ 11,6% voorlopig
Woningen 1 jan 202654.777+3.282 sinds 2021
Leefbaarometer 20246 / 9plek 318 van 342

Gemiddelde verkoopprijs

DelftNederland
0100k200k300k400k500k19952005201520252015: € 211.971

Delft is ruim twee keer zo duur als in 2015.

Bouwjaar van de woningen

BAG · okt 2026 · 54.862
  • vóór 194521,4%
  • 1945–7431,0%
  • 1975–9425,0%
  • 1995–1412,4%
  • 2015+10,3%
Blaricum€ 1,1 mlnduurst
Nederland€ 480kgemiddeld
Delft€ 454kplek 205
Kerkrade€ 270kgoedkoopst
Mockup

Dit is een mockup, geen werkende versie, met de cijfers voor Delft uit onze proefdraai van 16 oktober 2026 en de CBS-prijsreeks 1995–2025, opgehaald op 17 oktober 2026. De MCP-server zet je aan met het adres op Voor AI.

Voor wie

Raadsleden en wethouders die het woningdebat willen onderbouwen, lokale journalisten, makelaars en kopers die gemeenten willen vergelijken, en studenten die een eerste dashboard met echte overheidsdata willen bouwen.

Wat je krijgt

Een dashboard dat voor één gemeente in een oogopslag laat zien hoe de woningmarkt ervoor staat. Proefdraai voor Delft (GM0503) op 16 oktober 2026: - Gemiddelde verkoopprijs van een bestaande koopwoning in 2025: 453.866 euro, tegen 479.527 euro in heel Nederland. In 2015 was dat in Delft 211.971 euro, dus ruim twee keer zo weinig. Delft staat op plek 205 van de 342 gemeenten; Blaricum is het duurst (1.105.604 euro), Kerkrade het goedkoopst (270.119 euro). - Gemiddelde WOZ-waarde op 1 januari 2026: 393.000 euro (voorlopig), een jaar eerder 352.000 euro. Landelijk 439.000 euro. In 2025: koopwoningen 488.000, corporatiewoningen 249.000, overige huur 311.000 euro. - Woningvoorraad op 1 januari 2026: 54.777 woningen, 3.282 meer dan op 1 januari 2021 (51.495). Gemiddelde oppervlakte 88 m², landelijk 120 m². - BAG, oktober 2026: 54.862 woningen in gebruik in de woonplaats Delft. 52,4% is gebouwd vóór 1975 (21,4% vóór 1945), 10,3% in 2015 of later. 43,9% is kleiner dan 75 m². - Leefbaarometer 2024: score 4,052, klasse 6 van 9, plek 318 van 342 gemeenten. De deelscore woningvoorraad (-0,049) trekt het meest omlaag. Het script haalt dit alles in ongeveer 17 seconden op; de BAG-tellingen kosten de meeste tijd.

Gemiddelde verkoopprijs van een bestaande koopwoning: 505 duizend euro in september 2026, 5,7 keer zo veel als in januari 1995

Gemiddelde verkoopprijs van een bestaande koopwoning, januari 1995 – september 2026, in duizend euro. Dat is het hoogste punt in de reeks.

Bron: CBS, tabel 85773NED (Bestaande koopwoningen; verkoopprijzen prijsindex 2020=100) · opgehaald 25 oktober 2026Open de tabel Los blok

Zo zou je kunnen starten7 stappen

  1. 1

    Zoek de juiste CBS-tabellen in de catalogus

    De CBS-catalogus noemt elke tabel met titel, periode en wijzigingsdatum. Filter op een woord in de titel en sluit stopgezette tabellen uit: er staan tientallen oude woningtabellen in (prijsindex 2010=100, 2015=100) die niet meer worden bijgewerkt. Voor dit dashboard heb je drie tabellen per gemeente nodig: 83625NED (gemiddelde verkoopprijzen, 1995 tot en met 2025), 85036NED (gemiddelde WOZ-waarde naar eigendom, vanaf 2019) en 85035NED (woningvoorraad en gemiddelde oppervlakte op 1 januari, vanaf 2021). Let op: de prijsindex per regio (85792NED) heeft alleen de vier grote steden als gemeente.

    https://opendata.cbs.nl/ODataCatalog/Tables?$format=json&$filter=substringof('koopwoningen',Title) and Frequency ne 'Stopgezet'&$select=Identifier,Title,Modified,Period
    {"odata.metadata":"https://opendata.cbs.nl/ODataCatalog/$metadata#Tables&$select=Identifier,Title,Modified,Period","value":[
    {"Identifier":"85773NED","Title":"Bestaande koopwoningen; verkoopprijzen prijsindex 2020=100","Modified":"2026-09-22T06:30:00","Period":"januari 1995 - augustus 2026"},
    {"Identifier":"85792NED","Title":"Bestaande koopwoningen; verkoopprijzen, prijsindex 2020=100, regio","Modified":"2026-07-22T06:30:00","Period":"1e kwartaal 1995 - 2e kwartaal 2026"},
    ...
    {"Identifier":"83625NED","Title":"Bestaande koopwoningen; gemiddelde verkoopprijzen, regio","Modified":"2026-02-17T02:00:00","Period":"1995 t/m 2025"}]}
  2. 2

    Haal de gemiddelde verkoopprijs op, gemeente en Nederland

    We gebruiken de nieuwere OData-v4-API van het CBS (datasets.cbs.nl). Daar hebben sleutels geen opvulspaties en heten de maten codes (M001534 = gemiddelde verkoopprijs, in euro; zie /MeasureCodes). Nederland heet NL01. De gemiddelde verkoopprijs is geen prijsindex: verkopen in een jaar veel grote huizen, dan stijgt het gemiddelde ook zonder dat huizen duurder worden. Het CBS zegt dat zelf in de tabeltoelichting. Toon hem daarom als 'wat er gemiddeld betaald is'.

    https://datasets.cbs.nl/odata/v1/CBS/83625NED/Observations?$filter=RegioS eq 'GM0503' or RegioS eq 'NL01'&$orderby=Perioden desc&$top=4&$select=RegioS,Perioden,Value
    {"@odata.context":"https://datasets.cbs.nl/odata/v1/CBS/83625NED/$metadata#Observations(RegioS,Perioden,Value)","value":[
    {"Value":479527.0,"RegioS":"NL01","Perioden":"2025JJ00"},
    {"Value":453866.0,"RegioS":"GM0503","Perioden":"2025JJ00"},
    {"Value":450985.0,"RegioS":"NL01","Perioden":"2024JJ00"},
    {"Value":409999.0,"RegioS":"GM0503","Perioden":"2024JJ00"}]}
  3. 3

    Voeg de WOZ-waarde toe, met de status van het jaar

    Tabel 85036NED geeft de gemiddelde WOZ-waarde per 1 januari in duizenden euro's (393.0 = 393.000 euro). Eigendom T001132 is het totaal, 1014800 koopwoningen, A047047 corporatiewoningen, A047048 overige verhuurders. Het nieuwste jaar is voorlopig: haal de status uit /PeriodenCodes en zet hem in beeld. Volgens de tabeltoelichting komen de definitieve cijfers over 2026 begin november 2026. Bij de voorlopige cijfers van Delft stond alleen het totaal, nog niet de uitsplitsing naar eigendom.

    https://datasets.cbs.nl/odata/v1/CBS/85036NED/Observations?$filter=RegioS eq 'GM0503' and Eigendom eq 'T001132'&$orderby=Perioden desc&$top=2&$select=Measure,Eigendom,RegioS,Perioden,Value
    {"@odata.context":"https://datasets.cbs.nl/odata/v1/CBS/85036NED/$metadata#Observations(Measure,Eigendom,RegioS,Perioden,Value)","value":[
    {"Measure":"M003039","Value":393.0,"Eigendom":"T001132","RegioS":"GM0503","Perioden":"2026JJ00"},
    {"Measure":"M003039","Value":352.0,"Eigendom":"T001132","RegioS":"GM0503","Perioden":"2025JJ00"}]}
  4. 4

    Tel de woningvoorraad en de gemiddelde oppervlakte

    Tabel 85035NED geeft per 1 januari twee maten in één antwoord: D002936 (beginstand woningvoorraad, aantal) en M002978 (gemiddelde oppervlakte, m²). Kies Woningtype T001100 en Woningkenmerk T001727 voor het totaal; A053381 geeft alleen nieuwbouw, ZW10290 en ZW10340 splitsen eengezins- en meergezinswoningen. De reeks begint pas in 2021. Filter in je code op Measure, want de twee maten staan door elkaar.

    https://datasets.cbs.nl/odata/v1/CBS/85035NED/Observations?$filter=RegioS eq 'GM0503' and Woningtype eq 'T001100' and Woningkenmerk eq 'T001727'&$orderby=Perioden desc&$top=2&$select=Measure,RegioS,Perioden,Value
    {"@odata.context":"https://datasets.cbs.nl/odata/v1/CBS/85035NED/$metadata#Observations(Measure,RegioS,Perioden,Value)","value":[
    {"Measure":"D002936","Value":54777.0,"RegioS":"GM0503","Perioden":"2026JJ00"},
    {"Measure":"M002978","Value":88.0,"RegioS":"GM0503","Perioden":"2026JJ00"}]}
  5. 5

    Tel woningen per bouwjaar en oppervlakte in de BAG

    De BAG-WFS van PDOK kan tellen zonder data te sturen: resultType=hits geeft alleen numberMatched. Een woning is een verblijfsobject met 'woonfunctie' in gebruiksdoel (een kommalijst, dus PropertyIsLike) en status 'Verblijfsobject in gebruik'. Voeg per klasse een PropertyIsBetween op bouwjaar of oppervlakte toe. Met filter duurt een telling 2 tot 4 seconden, zonder filter rond 30 seconden. De BAG kent geen gemeentecode, alleen woonplaatsen: Delft is één woonplaats, maar veel gemeenten hebben er meerdere. De vijf bouwjaarklassen en de vijf oppervlakteklassen telden elk precies op tot 54.862.

  6. 6

    Haal de leefbaarheidsscore van alle gemeenten op

    De Leefbaarometer-WFS heeft per meting een gemeentelaag (gemeentescore24 = 2024). Vraag alleen de velden die je nodig hebt en laat geom weg, dan is het antwoord klein. Het veld id is de CBS-gemeentecode, dus je koppelt direct aan de CBS-tabellen. lbm is de score, kscore de klasse (1 tot 9, hoger is beter), afw de afwijking van het landelijk gemiddelde, won en onv zijn deelscores. Haal alle 342 gemeenten op als je een plek in de ranglijst wilt tonen. Gebruik JSON, geen CSV: 'Nuenen, Gerwen en Nederwetten' heeft een komma in de naam.

    https://geo.leefbaarometer.nl/lbm3/ows?service=WFS&version=2.0.0&request=GetFeature&typeNames=lbm3:gemeentescore24&outputFormat=application/json&propertyName=id,name,lbm,afw,won,onv,kscore&cql_filter=id='GM0503'
    {"type":"FeatureCollection","features":[{"type":"Feature","id":"gemeentescore24.fid-6ce20098_1a146a7d447_-7c93","geometry":null,
    "properties":{"id":"GM0503","name":"Delft","lbm":4.05173106759454,"afw":-0.0505337835491484,"onv":-0.0255306299775484,
    "won":-0.0491488887163183,"kscore":6},"bbox":[81743,442446.208,87703.775,449847.9507]}],
    "totalFeatures":1,"numberMatched":1,"numberReturned":1,"timeStamp":"2026-10-16T21:39:44.924Z","crs":null}
  7. 7

    Zet de gemeente naast de rest van Nederland

    Een getal zegt pas iets naast een ander getal. Haal voor de ranglijst de verkoopprijs van alle gemeenten in één keer op. De regiodimensie bevat alle 728 gemeentecodes die ooit bestonden; in 2025 hebben er 342 een waarde, de rest is null. Filteren op Value kan niet (de API geeft een fout), dus gooi de lege waarden in je eigen code weg. Gemeentenamen haal je uit /RegioSCodes.

    https://datasets.cbs.nl/odata/v1/CBS/83625NED/RegioSCodes?$filter=startswith(Identifier,'GM')&$select=Identifier,Title&$top=3
    {"@odata.context":"https://datasets.cbs.nl/odata/v1/CBS/83625NED/$metadata#RegioSCodes(Identifier,Title)","value":[
    {"Identifier":"GM1680","Title":"Aa en Hunze"},
    {"Identifier":"GM0738","Title":"Aalburg"},
    {"Identifier":"GM0358","Title":"Aalsmeer"}]}

Hoe de bronnen samenkomen

  • CBS StatLineLeefbaarometervia gemeentecode (GM0503); in de Leefbaarometer het veld id

    De Leefbaarometer gebruikt dezelfde CBS-codes, dus prijs, WOZ en voorraad komen zonder vertaaltabel naast de leefbaarheidsscore. Beide gebruiken de gemeentelijke indeling van hun eigen jaar: na een herindeling verschijnen nieuwe codes.

  • CBS StatLineBasisregistratie Adressen en Gebouwen (BAG)via woonplaatsnaam (de BAG-WFS heeft geen gemeentecode)

    CBS telt de voorraad uit de BAG, dus de twee horen bijna gelijk te zijn: Delft had volgens CBS 54.777 woningen op 1 januari 2026 en volgens de BAG-WFS 54.862 woningen in gebruik in oktober 2026. Een groot verschil betekent dat je de verkeerde woonplaatsen telt. CBS telt ook woningen die buiten gebruik of in verbouwing zijn.

  • Basisregistratie Adressen en Gebouwen (BAG)Leefbaarometervia ligging (RD-coördinaten, EPSG:28992)

    Wil je dieper dan de gemeente, dan liggen BAG-objecten en Leefbaarometer-buurten en -rastercellen in hetzelfde coördinatenstelsel. Zo zet je bouwjaren naast de score per buurt.

Laat AI het bouwen

Plak deze prompt in Claude, ChatGPT, Cursor of Lovable. Hij noemt de echte endpoints, de koppelsleutels en de valkuilen, zodat de assistent meteen werkende code schrijft. Controleer de uitkomst altijd met de bron zelf.

Bouw een woningmarktdashboard (Next.js of één HTML-bestand met JavaScript) waarin ik een gemeente kies en zie: gemiddelde verkoopprijs door de jaren heen, gemiddelde WOZ-waarde, woningvoorraad en gemiddelde oppervlakte, woningen naar bouwjaar en oppervlakte, en de leefbaarheidsscore. Elk cijfer naast het landelijk gemiddelde en met de plek van de gemeente in de ranglijst van 342.

Bronnen (alle drie open, geen sleutel, eerlijke User-Agent meesturen):
1. CBS OData v4, https://datasets.cbs.nl/odata/v1/CBS/<tabel>/Observations?$filter=...
   - 83625NED: gemiddelde verkoopprijs bestaande koopwoningen per jaar (1995 tot en met 2025), maat M001534, euro.
   - 85036NED: gemiddelde WOZ-waarde per 1 januari, maat M003039, in 1.000 euro (393.0 = 393.000 euro). Eigendom: T001132 totaal, 1014800 koop, A047047 corporatie, A047048 overige verhuur.
   - 85035NED: woningvoorraad per 1 januari (D002936, aantal) en gemiddelde oppervlakte (M002978, m²). Woningtype T001100 + Woningkenmerk T001727 = totaal. Reeks vanaf 2021.
   - Nederland heet NL01, gemeenten GM + 4 cijfers. Namen: /<tabel>/RegioSCodes. Status per jaar (Definitief/Voorlopig): /<tabel>/PeriodenCodes. Eenheden: /<tabel>/MeasureCodes.
   - Voorbeeld: https://datasets.cbs.nl/odata/v1/CBS/83625NED/Observations?$filter=RegioS eq 'GM0503' or RegioS eq 'NL01'
2. BAG via PDOK WFS: https://service.pdok.nl/lv/bag/wfs/v2_0, laag bag:verblijfsobject, met resultType=hits en een FES-filter in de parameter FILTER (XML, URL-gecodeerd). Velden: woonplaats, status, gebruiksdoel, bouwjaar, oppervlakte.
3. Leefbaarometer WFS: https://geo.leefbaarometer.nl/lbm3/ows?service=WFS&version=2.0.0&request=GetFeature&typeNames=lbm3:gemeentescore24&outputFormat=application/json&propertyName=id,name,lbm,afw,won,onv,kscore

Valkuilen die je moet afvangen:
- De gemiddelde verkoopprijs is geen prijsindex (andere huizen verkocht = ander gemiddelde). Noem het 'gemiddeld betaald'. De prijsindex per regio (85792NED) heeft alleen Amsterdam, Den Haag, Rotterdam en Utrecht als gemeente.
- De regiodimensie heeft 728 gemeentecodes, ook opgeheven gemeenten. Neem alleen gemeenten met een waarde in het nieuwste jaar (342 in 2025). Filteren op Value geeft een fout: doe dat in je eigen code.
- Het nieuwste WOZ-jaar is voorlopig (2026, definitief begin november 2026) en had bij Delft nog geen uitsplitsing naar eigendom. Toon de status en vang ontbrekende categorieën af.
- In 85035NED staan twee maten door elkaar in dezelfde lijst: filter op Measure.
- Gebruik je de oude OData v3 (opendata.cbs.nl/ODataApi/OData/<tabel>/TypedDataSet), dan zijn sleutels aangevuld met spaties tot de langste code in die dimensie: 'NL01  ' (twee spaties) maar 'GM0503' zonder. Zonder de juiste spaties krijg je een lege lijst zonder fout. Velden heten daar GemiddeldeVerkoopprijs_1, GemiddeldeWOZWaardeVanWoningen_1, BeginstandWoningvoorraad_1, GemiddeldeOppervlakte_2. Op 16 oktober 2026 gaf v3 's avonds een tijd lang HTTP 503 terwijl v4 werkte: bouw een nette foutmelding of een terugval.
- BAG: een woning is een verblijfsobject met 'woonfunctie' in gebruiksdoel. Dat veld is een kommalijst (bijvoorbeeld 'woonfunctie,winkelfunctie'), dus PropertyIsLike met *woonfunctie*, geen PropertyIsEqualTo. Neem status 'Verblijfsobject in gebruik'.
- BAG heeft geen gemeentecode, alleen woonplaatsen. Een gemeente heeft vaak meerdere woonplaatsen; tel die bij elkaar. Woonplaatsnamen zijn niet altijd de gewone naam: 'Bergen (NH)', 'Bergen L', 'Hengelo (Gld)'. Maak een lijst per gemeente of kies de woonplaatsen met de hand.
- BAG-telling zonder filter duurt ongeveer 30 seconden, met filter 2 tot 4 seconden. Doe maximaal drie verzoeken tegelijk en cache de uitkomst een dag.
- GetFeature zonder resultType=hits stuurt altijd de geometrie mee en maximaal 1.000 objecten per pagina: tel, haal niet alles op.
- Leefbaarometer: id is de CBS-gemeentecode. Gebruik JSON, niet CSV (een gemeentenaam bevat een komma). De score is een modelschatting over 2024, gepubliceerd in juli 2026, elke twee jaar.
- Vergelijk CBS-voorraad (1 januari) met de BAG-telling (vandaag) als controle: ze moeten binnen een paar procent liggen.

Gewenste uitkomst: een gemeentekiezer, vijf kaarten met het cijfer, het landelijke cijfer en de plek in de ranglijst, een lijngrafiek van de verkoopprijs sinds 1995 (gemeente en Nederland), staafgrafieken voor bouwjaar en oppervlakte, en onder elk blok de bron, tabelcode en peildatum. Laat bij voorlopige cijfers een label 'voorlopig' zien.

Probeer het zelf

De kern van het project in een klein script. Nodig: Node 20+ (ingebouwde fetch), opslaan als woningmarkt.mjs en draaien met node woningmarkt.mjs. Getest op 2026-10-16; hieronder de echte uitvoer van die proefdraai.

// Woningmarkt van één gemeente: verkoopprijs, WOZ-waarde, voorraad (CBS), bouwjaar en oppervlakte (BAG), leefbaarheid.
// Draait met Node 20+ (ingebouwde fetch). Geen sleutels nodig.  node woningmarkt.mjs
const UA = { "User-Agent": "mijn-woningdashboard/1.0 (+jij@voorbeeld.nl)" };
const GM = "GM0503";          // Delft; CBS-gemeentecode
const WOONPLAATS = "Delft";   // BAG kent woonplaatsen, geen gemeenten: kies de woonplaats(en) van jouw gemeente

const CBS = "https://datasets.cbs.nl/odata/v1/CBS";
async function cbs(tabel, filter) {               // OData v4: sleutels zonder opvulspaties
  const url = `${CBS}/${tabel}/Observations?$filter=${encodeURIComponent(filter)}`;
  const r = await fetch(url, { headers: UA });
  if (!r.ok) throw new Error(`${tabel}: HTTP ${r.status}`);
  return (await r.json()).value;
}
async function status(tabel) {                   // per periode: Definitief, Voorlopig of null
  const r = await (await fetch(`${CBS}/${tabel}/PeriodenCodes`, { headers: UA })).json();
  return Object.fromEntries(r.value.map((p) => [p.Identifier.slice(0, 4), p.Status]));
}
const perJaar = (rijen) => Object.fromEntries(rijen.map((r) => [r.Perioden.slice(0, 4), r.Value]));

// 1. Gemiddelde verkoopprijs bestaande koopwoningen (83625NED), gemeente en Nederland
const prijs = perJaar(await cbs("83625NED", `RegioS eq '${GM}'`));
const prijsNL = perJaar(await cbs("83625NED", "RegioS eq 'NL01'"));
// 2. Gemiddelde WOZ-waarde, alle woningen (85036NED, Eigendom T001132 = totaal), in 1.000 euro
const woz = perJaar(await cbs("85036NED", `RegioS eq '${GM}' and Eigendom eq 'T001132'`));
// 3. Woningvoorraad op 1 januari (85035NED): D002936 = aantal, M002978 = gemiddelde oppervlakte
const vr = await cbs("85035NED", `RegioS eq '${GM}' and Woningtype eq 'T001100' and Woningkenmerk eq 'T001727'`);
const voorraad = perJaar(vr.filter((r) => r.Measure === "D002936"));

const wozStatus = await status("85036NED");
const j = Object.keys(prijs).at(-1), jw = Object.keys(woz).at(-1), jv = Object.keys(voorraad).at(-1);
const f = (n) => Math.round(n).toLocaleString("nl-NL");
console.log(`${GM} ${WOONPLAATS}`);
console.log(`Verkoopprijs ${j}: ${f(prijs[j])} euro (Nederland ${f(prijsNL[j])}), 2015: ${f(prijs["2015"])} euro`);
console.log(`WOZ-waarde ${jw}: ${f(woz[jw] * 1000)} euro (${wozStatus[jw].toLowerCase()}), ${jw - 1}: ${f(woz[jw - 1] * 1000)} euro`);
console.log(`Woningvoorraad 1 januari ${jv}: ${f(voorraad[jv])} woningen, 1 januari 2021: ${f(voorraad["2021"])}`);

// 4. BAG: woningen in gebruik naar bouwjaar en oppervlakte, geteld met resultType=hits (alleen een getal terug)
const BAG = "https://service.pdok.nl/lv/bag/wfs/v2_0";
const is = (v, w) => `<PropertyIsEqualTo><ValueReference>${v}</ValueReference><Literal>${w}</Literal></PropertyIsEqualTo>`;
const tussen = (v, a, b) => `<PropertyIsBetween><ValueReference>${v}</ValueReference><LowerBoundary><Literal>${a}</Literal></LowerBoundary><UpperBoundary><Literal>${b}</Literal></UpperBoundary></PropertyIsBetween>`;
const woning = is("woonplaats", WOONPLAATS) + is("status", "Verblijfsobject in gebruik") +
  `<PropertyIsLike wildCard="*" singleChar="." escapeChar="!"><ValueReference>gebruiksdoel</ValueReference><Literal>*woonfunctie*</Literal></PropertyIsLike>`;
async function tel(extra = "") {
  const p = new URLSearchParams({ service: "WFS", version: "2.0.0", request: "GetFeature", typeNames: "bag:verblijfsobject",
    resultType: "hits", FILTER: `<Filter><And>${woning}${extra}</And></Filter>` });
  const t = await (await fetch(`${BAG}?${p}`, { headers: UA })).text();
  return Number(t.match(/numberMatched="(\d+)"/)[1]);
}
async function rustig(taken) { const uit = []; for (let i = 0; i < taken.length; i += 3) uit.push(...await Promise.all(taken.slice(i, i + 3).map((t) => t()))); return uit; }
const BOUWJAAR = [["voor 1945", 0, 1944], ["1945-1974", 1945, 1974], ["1975-1994", 1975, 1994], ["1995-2014", 1995, 2014], ["2015 en later", 2015, 2100]];
const OPP = [["tot 50 m2", 0, 49], ["50-74 m2", 50, 74], ["75-99 m2", 75, 99], ["100-149 m2", 100, 149], ["150 m2 of meer", 150, 1e6]];
const totaal = await tel();
const bj = await rustig(BOUWJAAR.map(([, a, b]) => () => tel(tussen("bouwjaar", a, b))));
const op = await rustig(OPP.map(([, a, b]) => () => tel(tussen("oppervlakte", a, b))));
const pct = (n) => `${(100 * n / totaal).toFixed(1).replace(".", ",")}%`;
console.log(`\nBAG, woningen in gebruik in woonplaats ${WOONPLAATS}: ${f(totaal)}`);
BOUWJAAR.forEach(([k], i) => console.log(`  gebouwd ${k.padEnd(14)} ${f(bj[i]).padStart(7)}  ${pct(bj[i])}`));
OPP.forEach(([k], i) => console.log(`  ${k.padEnd(22)} ${f(op[i]).padStart(7)}  ${pct(op[i])}`));

// 5. Leefbaarometer 2024, alle 342 gemeenten (JSON, niet CSV: sommige namen bevatten een komma)
const q = new URLSearchParams({ service: "WFS", version: "2.0.0", request: "GetFeature", typeNames: "lbm3:gemeentescore24",
  outputFormat: "application/json", propertyName: "id,name,lbm,afw,won,onv,kscore" });
const gem = (await (await fetch(`https://geo.leefbaarometer.nl/lbm3/ows?${q}`, { headers: UA })).json()).features
  .map((x) => x.properties).sort((a, b) => b.lbm - a.lbm);
const i = gem.findIndex((g) => g.id === GM), g = gem[i];
console.log(`\nLeefbaarometer 2024: score ${g.lbm.toFixed(3)}, klasse ${g.kscore} van 9, plek ${i + 1} van ${gem.length}`);
console.log(`  afwijking van het landelijk gemiddelde ${g.afw.toFixed(3)}; deelscores woningvoorraad ${g.won.toFixed(3)}, overlast en onveiligheid ${g.onv.toFixed(3)}`);
Uitvoer
GM0503 Delft
Verkoopprijs 2025: 453.866 euro (Nederland 479.527), 2015: 211.971 euro
WOZ-waarde 2026: 393.000 euro (voorlopig), 2025: 352.000 euro
Woningvoorraad 1 januari 2026: 54.777 woningen, 1 januari 2021: 51.495

BAG, woningen in gebruik in woonplaats Delft: 54.862
  gebouwd voor 1945       11.731  21,4%
  gebouwd 1945-1974       17.000  31,0%
  gebouwd 1975-1994       13.706  25,0%
  gebouwd 1995-2014        6.785  12,4%
  gebouwd 2015 en later    5.640  10,3%
  tot 50 m2               10.339  18,8%
  50-74 m2                13.753  25,1%
  75-99 m2                14.436  26,3%
  100-149 m2              12.088  22,0%
  150 m2 of meer           4.246  7,7%

Leefbaarometer 2024: score 4.052, klasse 6 van 9, plek 318 van 342
  afwijking van het landelijk gemiddelde -0.051; deelscores woningvoorraad -0.049, overlast en onveiligheid -0.026

Waar het misgaat

  • De gemiddelde verkoopprijs (83625NED) is geen prijsontwikkeling: het is het gemiddelde van wat dat jaar verkocht is. Verkopen er meer grote huizen, dan stijgt het zonder dat iets duurder werd. Voor echte prijsontwikkeling is er de prijsindex (85792NED), maar die heeft alleen de vier grote steden als gemeente.
  • CBS-regiocodes: de dimensie bevat 728 gemeentecodes, ook van opgeheven gemeenten (Aalburg). In 2025 hebben er 342 een waarde. Filteren op Value mag niet in de v4-API (fout 'The property Value cannot be used in the $filter query option'): gooi null-waarden zelf weg.
  • Opvulspaties in de oude OData v3: sleutels worden aangevuld tot de langste code in die dimensie. In 83625NED is het 'NL01 ' (twee spaties) maar 'GM0503' zonder spaties; met spaties erachter krijg je een lege lijst. De v4-API (datasets.cbs.nl) heeft geen opvulspaties.
  • Het nieuwste WOZ-jaar is voorlopig en kan nog categorieën missen: bij Delft stond voor 2026 alleen het totaal, niet koop of huur. Lees de status uit /PeriodenCodes en toon die. De definitieve WOZ-cijfers 2026 komen volgens het CBS begin november 2026.
  • De BAG-WFS kent geen gemeente, alleen woonplaatsen, en de namen zijn niet altijd wat je verwacht: 'Bergen (NH)', 'Bergen L', 'Hengelo (Gld)' naast 'Hengelo'. Een gemeente met meerdere woonplaatsen tel je per woonplaats en dan op. Controleer altijd met de CBS-voorraad (54.777 tegen 54.862 voor Delft).
  • gebruiksdoel in de BAG is een kommalijst: een woning boven een winkel heeft 'woonfunctie,winkelfunctie'. Tel met PropertyIsLike '*woonfunctie*', niet met gelijk-aan, anders mis je die woningen.
  • BAG-WFS: zonder resultType=hits krijg je altijd de geometrie mee en maximaal 1.000 objecten per pagina; GetPropertyValue geeft numberMatched 'unknown'. Tellen met hits en een filter is veel sneller (2 tot 4 seconden) dan alles ophalen. Zonder filter duurt een telling ongeveer 30 seconden.
  • Leefbaarometer als CSV lijkt makkelijk, maar 'Nuenen, Gerwen en Nederwetten' heeft een komma in de naam en de regels eindigen op CRLF. Met een simpele split op komma's schuiven de kolommen en klopt je ranglijst niet meer. Neem outputFormat=application/json.

Verder bouwen

  • Kaart van alle gemeenten: koppel de verkoopprijs 2025 aan de gemeentegrenzen van PDOK (pdok-wijkenbuurten) of aan de Leefbaarometer-laag met geometrie, en kleur naar prijs of naar prijs gedeeld door WOZ-waarde.
  • Per buurt: de Leefbaarometer heeft buurtscore24 met de CBS-buurtcode, en de BAG kun je met een BBOX- of Within-filter per buurt tellen. Zo zie je welke buurten oud en klein gebouwd zijn en hoe ze scoren.
  • Nieuwbouwteller: tel in de BAG panden met status 'Bouw gestart' of 'Bouwvergunning verleend' per woonplaats en zet dat naast de groei van de CBS-voorraad (Woningkenmerk A053381 = nieuwbouw).
  • Maandelijkse markt: de landelijke prijsindex per maand (85773NED, tot en met augustus 2026) als extra lijn, met een melding als de nieuwe maand binnen is.

Meer met deze data

Gemiddelde WOZ-waarde van een woning: het hoogst in Bloemendaal (900 duizend euro), het laagst in Pekela en 1 andere gemeente (199 duizend euro)

Gemiddelde WOZ-waarde van een woning per gemeente, 2024, in duizend euro. Heel Nederland: 378. 342 gemeenten met een cijfer.

Bron: CBS, tabel 85984NED (Kerncijfers wijken en buurten 2024) · opgehaald 18 oktober 2026Open de tabel Los blok

Woningen in Nederland: 8,35 miljoen in 2025, 5,6 keer zo veel als in 1921

Woningen in Nederland, 1921 – 2025, in miljoen. Dat is het hoogste punt in de reeks.

Bron: CBS, tabel 82235NED (Voorraad woningen; standen en mutaties vanaf 1921) · opgehaald 25 oktober 2026Open de tabel Los blok

Panden naar bouwjaar (alleen wat er nu staat): 104.301 panden in 2025, 3% meer dan in 2005

Panden naar bouwjaar (alleen wat er nu staat), 2005 – 2025, in panden. Het hoogste punt was 2021 (184.232). Cijfers met * zijn voorlopig.

Bron: Kadaster, BAG via PDOK (WFS v2_0) · opgehaald 25 oktober 2026 · selectie: zonder status 'Bouwvergunning verleend' en 'Bouw gestart'; alleen panden die er nu nog staanOpen de tabel Los blok

Leefbaarheidsscore (Leefbaarometer): het hoogst in Vlieland (4,47 punten), het laagst in Roosendaal (3,97 punten)

Leefbaarheidsscore (Leefbaarometer) per gemeente, 2024, in punten op de Leefbaarometer-schaal. Heel Nederland: 4,10. 342 gemeenten met een cijfer.

Bron: Leefbaarometer 3.0, WFS-laag gemeentescore24 · opgehaald 25 oktober 2026Open de tabel Los blok

De bronnen3

CBS StatLine

CBSNederland, land tot buurt

De statistiekendatabank van het CBS: bijna 6.000 tabellen over bevolking, economie, werk, wonen, energie, zorg en meer, de meeste met lange reeksen per jaar, kwartaal of maand.

OpenAPIDownloadBevolkingEconomieWerkEnergie
Actueel
bijgewerkt 13 uur geleden

Basisregistratie Adressen en Gebouwen (BAG)

Kadaster, via PDOKNederland, adres en gebouw

Alle adressen en gebouwen van Nederland met bouwjaar, oppervlakte en gebruiksdoel. De ruggengraat voor alles wat op adresniveau gekoppeld moet worden.

OpenKaartlaagAPIDownloadWonen en ruimte
Bereikbaar
dagelijks

Leefbaarometer

Ministerie van Binnenlandse Zaken en KoninkrijksrelatiesNederland, 100 meter

Een schatting van hoe prettig het wonen is, voor elk bewoond vierkant van 100 bij 100 meter in Nederland, en opgeteld per buurt, wijk, postcodegebied en gemeente. Het model gebruikt 45 kenmerken van de woonomgeving (94 onderliggende variabelen), zoals voorzieningen, geluid en onveiligheid. Metingen voor 2002 tot en met 2024, met vijf deelscores.

OpenAPIDownloadKaartlaagWonen en ruimteVeiligheid
Actueel
bijgewerkt in juli 2026

Meer om te bouwen