Buurtmonitor veiligheid: overlast en misdrijven per buurt
Een dashboard dat voor elke buurt in je gemeente laat zien hoeveel overlast en misdrijven de politie registreert, per 1.000 inwoners en door de jaren heen, met een kaart en een vergelijking met heel Nederland.
geef_project("buurtmonitor-veiligheid")geef_bron("politie-overlast")geef_bron("politie-misdrijven")geef_bron("cbs-kwb")
Ik heb het project, de geteste aanroepen en de valkuilen. Ik bouw een dashboard met Geregistreerde overlast per buurt, Geregistreerde misdrijven per buurt, Kerncijfers wijken en buurten en Wijk- en buurtkaart. 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.
Buurten met de meeste misdrijvenper 1.000aantal
- 1Hoog-Catharijne NS en Jaarbeurs*1.252
- 2Lange Elisabethstraat, Mariaplaats e.o.540
- 3Wijk C516
- 4Domplein, Neude, Janskerkhof369
- 5Nobelstraat en omgeving258
- 6Galgenwaard en omgeving206
mediaan buurt 50,8* veel reizigers, die tellen niet als inwoner
Dit is een mockup, geen werkende versie, met de cijfers uit onze proefdraai van 16 oktober 2026 voor Utrecht (politie via CBS, 2021–2025; buurten met minstens 1.000 inwoners). De MCP-server zet je aan met het adres op Voor AI.
Voor wie
Raadsleden en wijkregisseurs die willen weten waar het schuurt, lokale journalisten, bewonersorganisaties en iedereen die wil nagaan of 'het onveiliger wordt' in de eigen buurt klopt.
Wat je krijgt
Een dashboard met drie delen: een kaart van de buurten in je gemeente, gekleurd naar misdrijven of overlast per 1.000 inwoners; een lijn met de jaren 2021 tot en met 2025 voor de hele gemeente; en een tabel per buurt met inwoners, misdrijven, overlast en woninginbraak per 1.000 woningen.
Proefdraai op 16 oktober 2026 voor Utrecht (GM0344, 111 buurten, 376.770 inwoners en 168.736 woningen volgens de kerncijfers 2025): - In 2025 registreerde de politie in Utrecht 27.512 misdrijven (73,0 per 1.000 inwoners) en 18.181 overlastmeldingen (48,3 per 1.000). In heel Nederland was dat 808.021 misdrijven (44,8 per 1.000 van 18.044.027 inwoners) en 461.940 overlastmeldingen (25,6 per 1.000). - Misdrijven in Utrecht stegen van 21.765 in 2021 naar 27.512 in 2025. Overlast daalde eerst (16.342 in 2022, 15.478 in 2024) en steeg in 2025 weer. - Woninginbraak: 629 in 2025, 3,7 per 1.000 woningen (landelijk 21.624, 2,6 per 1.000 woningen). In 2024 was het in Utrecht 399. - De buurt Hoog-Catharijne NS en Jaarbeurs staat met 1.252 misdrijven per 1.000 inwoners bovenaan, want daar komen dagelijks tienduizenden reizigers en bezoekers die niet als inwoner meetellen. De mediane buurt (met minstens 1.000 inwoners) had 50,8 misdrijven en 35,2 overlastmeldingen per 1.000 inwoners. Hetzelfde script werkt voor elke gemeente: voor Amsterdam (517 buurten) duurde het ook ongeveer een seconde.
Geregistreerde overlast: 462 duizend meldingen per jaar in 2025, 65% meer dan in 2012
Geregistreerde overlast, 2012 – 2025, in duizend meldingen per jaar. Het hoogste punt was 2021 (537).
Zo zou je kunnen starten6 stappen
- 1
Kies je gemeente en haal de buurten op
De politietabellen hebben een eigen lijst met gebieden. Filter op Municipality (zonder opvulspaties) en je krijgt de gemeente, de wijken (WK) en de buurten (BU) met hun naam. Utrecht heeft 10 wijken en 111 buurten. Let op: in de Key staat de gemeentecode aangevuld met spaties tot 10 tekens ('GM0344 '), de wijkcode tot 10 ('WK034401 '). Buurtcodes zijn al precies 10 tekens. In Amsterdam bevatten buurtcodes letters (BU0363AE01). De politie rekent alle jaren om naar de buurtindeling van 2025: gebruik dus ook inwoners en grenzen van 2025.
https://dataderden.cbs.nl/ODataApi/OData/47024NED/WijkenEnBuurten?$filter=Municipality eq 'GM0344'&$format=json
{ "odata.metadata":"https://dataderden.cbs.nl/ODataApi/OData/47024NED/$metadata#Cbs.OData.WebAPI.WijkenEnBuurten","value":[ { "Key":"GM0344 ","Title":"Utrecht","Description":"Gemeente 'Utrecht' (GM0344)","Municipality":"GM0344","DetailRegionCode":"GM0344" },{ "Key":"WK034401 ","Title":"Wijk 01 West","Description":"Wijk 'Wijk 01 West' (WK034401) is een wijk in de gemeente 'Utrecht'.", ... },{ "Key":"BU03440111","Title":"Welgelegen, Den Hommel","Description":"Buurt 'Welgelegen, Den Hommel' (BU03440111) is een buurt in wijk 'Wijk 01 West' in de gemeente 'Utrecht'.", ... - 2
Haal de overlast per buurt op (tabel 47024NED)
Overlast heeft naast maanden ook jaartotalen ('2025JJ00'). Met substringof('BU0344',WijkenEnBuurten) krijg je alle buurten van de gemeente in één aanroep. De soortcode van het totaal is '0.0.0 ' met een spatie aan het eind; zonder die spatie krijg je een lege lijst en geen foutmelding. Andere soorten: 'E33 ' verward persoon, 'E35 ' jeugd, 'E38 ' alcohol of drugs, 'M22 ' geluidshinder. Let op: de buurten samen (17.974 in 2025) zijn iets minder dan de gemeente (18.181). Zo'n 1% van de meldingen heeft geen buurt.
https://dataderden.cbs.nl/ODataApi/OData/47024NED/TypedDataSet?$filter=Overlast eq '0.0.0 ' and substringof('BU0344',WijkenEnBuurten) and Perioden eq '2025JJ00'&$select=WijkenEnBuurten,Perioden,GeregistreerdeOverlast_1&$format=json
{ "odata.metadata":"https://dataderden.cbs.nl/ODataApi/OData/47024NED/$metadata#Cbs.OData.WebAPI.TypedDataSet&$select=WijkenEnBuurten,Perioden,GeregistreerdeOverlast_1","value":[ { "WijkenEnBuurten":"BU03440111","Perioden":"2025JJ00","GeregistreerdeOverlast_1":109 },{ "WijkenEnBuurten":"BU03440112","Perioden":"2025JJ00","GeregistreerdeOverlast_1":135 },{ "WijkenEnBuurten":"BU03440113","Perioden":"2025JJ00","GeregistreerdeOverlast_1":55 },{ ... - 3
Haal de misdrijven per buurt op (tabel 47022NED)
De misdrijventabel heeft 59 soorten maar géén jaartotalen: alleen maanden (2012MM01 tot en met 2026MM09). Tel de twaalf maanden zelf op. Maanden zonder misdrijven staan er wel in, met 0. Woninginbraak is soort '1.1.1 ' (ook met spatie). Belangrijk: een vraag die meer dan 10.000 rijen zou opleveren, geeft HTTP 500 met 'Please redefine your query so that it returns less than 10000 records' en géén odata.nextLink. Voor Amsterdam (517 buurten × 12 maanden × 2 soorten = 12.408 rijen) moet je dus per soort vragen.
https://dataderden.cbs.nl/ODataApi/OData/47022NED/TypedDataSet?$filter=SoortMisdrijf eq '1.1.1 ' and WijkenEnBuurten eq 'BU03440712' and substringof('2025MM',Perioden)&$select=Perioden,GeregistreerdeMisdrijven_1&$format=json
{ "odata.metadata":"https://dataderden.cbs.nl/ODataApi/OData/47022NED/$metadata#Cbs.OData.WebAPI.TypedDataSet&$select=Perioden,GeregistreerdeMisdrijven_1","value":[ { "Perioden":"2025MM01","GeregistreerdeMisdrijven_1":2 },{ "Perioden":"2025MM02","GeregistreerdeMisdrijven_1":1 },{ "Perioden":"2025MM03","GeregistreerdeMisdrijven_1":0 },{ ... - 4
Haal inwoners en woningen per buurt op (kerncijfers 2025)
De noemer komt uit de Kerncijfers wijken en buurten 2025 (tabel 86165NED), dezelfde buurtindeling als de politiecijfers. Aantal inwoners is T001036, de woningvoorraad M000297. Deel woninginbraken door woningen, niet door inwoners. Wij gebruiken de nieuwe CBS-API op datasets.cbs.nl (OData v4): daar hebben codes géén opvulspaties en staat de waarde in Value. Op 16 oktober 2026 rond 23.30 uur gaf de oude API op opendata.cbs.nl een 503 (Service Unavailable), terwijl datasets.cbs.nl gewoon antwoordde. Utrecht: 111 buurten, samen 376.770 inwoners en 168.736 woningen.
https://datasets.cbs.nl/odata/v1/CBS/86165NED/Observations?$filter=startswith(WijkenEnBuurten,'BU0344') and (Measure eq 'T001036' or Measure eq 'M000297')&$select=WijkenEnBuurten,Measure,Value
{"@odata.context":"https://datasets.cbs.nl/odata/v1/CBS/86165NED/$metadata#Observations(WijkenEnBuurten,Measure,Value)","value":[ {"Measure":"T001036","Value":1880.0,"WijkenEnBuurten":"BU03440111"}, {"Measure":"M000297","Value":911.0,"WijkenEnBuurten":"BU03440111"}, {"Measure":"T001036","Value":4105.0,"WijkenEnBuurten":"BU03440112"}, {"Measure":"M000297","Value":1428.0,"WijkenEnBuurten":"BU03440112"}, ... - 5
Haal de buurtgrenzen op voor de kaart (PDOK)
De wijk- en buurtkaart 2025 staat bij PDOK als WFS. Vraag srsName=EPSG:4326 voor een webkaart (Leaflet, MapLibre). Valkuil: deze MapServer-WFS negeert een cql_filter zonder foutmelding en stuurt dan de eerste 1.000 buurten van het land (49 MB, de eerste is 'Buitenland' met -99997 inwoners). Filter daarom met een FES-filter in de parameter filter (XML, URL-gecodeerd). Dan krijg je precies 111 buurten met geometrie, 474 kB. De laag heeft ook aantalInwoners (bij Utrecht dezelfde 376.770), handig als je de kerncijfers wilt overslaan; negatieve waarden zijn codes voor geheim of onbekend.
https://service.pdok.nl/cbs/wijkenbuurten/2025/wfs/v1_0?request=GetFeature&service=WFS&version=2.0.0&typeNames=wijkenbuurten:buurten&outputFormat=application/json&srsName=EPSG:4326&propertyName=buurtcode,buurtnaam,aantalInwoners&filter=<Filter xmlns%3D"http%3A%2F%2Fwww.opengis.net%2Ffes%2F2.0"><PropertyIsEqualTo><ValueReference>gemeentecode<%2FValueReference><Literal>GM0344<%2FLiteral><%2FPropertyIsEqualTo><%2FFilter>
{ "type": "FeatureCollection", "numberMatched": 111, "name": "buurten", "features": [ { "type": "Feature", "properties": { "buurtcode": "BU03440111", "buurtnaam": "Welgelegen, Den Hommel", "aantalInwoners": 1880 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ 5.095490997659927, 52.086681703224 ], ... - 6
Maak de trend voor de gemeente en zet hem naast Nederland
Voor de lijn door de tijd vraag je de gemeente zelf op ('GM0344 ', tien tekens) en voor de vergelijking heel Nederland ('NL00 '). Begin de lijn in 2021 of 2022: in maart 2021 veranderde de politie de registratie van overlast (vooral 'verward persoon' sprong omhoog), dus vergelijk 2020 niet met latere jaren. Deel elk jaar door de inwoners; met de kerncijfers van 2025 voor alle jaren is dat een benadering, want Utrecht groeit. Een gemeentecode zonder opvulspaties ('GM0344') geeft een lege lijst.
https://dataderden.cbs.nl/ODataApi/OData/47022NED/TypedDataSet?$filter=WijkenEnBuurten eq 'GM0344 ' and SoortMisdrijf eq '0.0.0 ' and Perioden eq '2025MM12'&$format=json
{ "odata.metadata":"https://dataderden.cbs.nl/ODataApi/OData/47022NED/$metadata#Cbs.OData.WebAPI.TypedDataSet","value":[ { "ID":2732162,"SoortMisdrijf":"0.0.0 ","WijkenEnBuurten":"GM0344 ","Perioden":"2025MM12","GeregistreerdeMisdrijven_1":2192 } ] }
Hoe de bronnen samenkomen
- Geregistreerde overlast per buurtKerncijfers wijken en buurtenvia
buurtcode (BU03440111), indeling 2025De kerncijfers 2025 (86165NED) leveren het aantal inwoners per buurt. Overlast per 1.000 inwoners is eerlijker dan het kale aantal: grote buurten hebben vanzelf meer meldingen. In de politietabel is de buurtcode 10 tekens zonder spaties, in de kerncijfers (OData v4) ook: ze passen één op één. Bij Utrecht kwamen alle 111 buurten overeen.
- Geregistreerde misdrijven per buurtKerncijfers wijken en buurtenvia
buurtcode, woningvoorraad (M000297)Woninginbraak deel je door het aantal woningen, niet door inwoners: in een buurt met veel eenpersoonshuishoudens zijn er relatief meer woningen. Utrecht 2025: 629 inbraken op 168.736 woningen is 3,7 per 1.000 woningen.
- Geregistreerde overlast per buurtWijk- en buurtkaartvia
buurtcode = buurtcode in de WFS-laag wijkenbuurten:buurten (2025)De grenzen maken van de tabel een kaart. Neem de dienst van hetzelfde jaar als de indeling van de politiecijfers (nu 2025): met de grenzen van 2024 mis je hernoemde en gesplitste buurten.
- Geregistreerde misdrijven per buurtGeregistreerde overlast per buurtvia
zelfde buurtcodes en perioden (2025MM01)Beide tabellen komen van de politie via CBS en gebruiken dezelfde gebieden en maanden. Zo kun je per buurt zien of het vooral om overlast gaat (meldingen, geen strafbaar feit) of om misdrijven. Galgenwaard in Utrecht: 206 misdrijven maar maar 13 overlastmeldingen per 1.000 inwoners (stadion).
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 buurtmonitor voor veiligheid als één webpagina (HTML + JavaScript, met Leaflet of MapLibre voor de kaart en een kleine grafiekbibliotheek). Ik kies een gemeente en zie:
1. een kaart van alle buurten, gekleurd naar misdrijven of overlast per 1.000 inwoners in het laatste volle jaar (keuzeknop);
2. een lijn van 2021 tot het laatste volle jaar voor de gemeente en voor heel Nederland, per 1.000 inwoners;
3. een sorteerbare tabel per buurt: inwoners, misdrijven, overlast, woninginbraak per 1.000 woningen, en de verandering ten opzichte van het jaar ervoor.
Databronnen (alle open, geen sleutel, CORS open):
- Overlast: https://dataderden.cbs.nl/ODataApi/OData/47024NED/TypedDataSet?$filter=Overlast eq '0.0.0 ' and substringof('BU0344',WijkenEnBuurten) and Perioden eq '2025JJ00'&$format=json
Veld GeregistreerdeOverlast_1. Heeft jaartotalen (2025JJ00) én maanden (2025MM01).
- Misdrijven: https://dataderden.cbs.nl/ODataApi/OData/47022NED/TypedDataSet?$filter=SoortMisdrijf eq '0.0.0 ' and substringof('BU0344',WijkenEnBuurten) and substringof('2025MM',Perioden)&$format=json
Veld GeregistreerdeMisdrijven_1. Alleen maanden: tel ze zelf op tot een jaar. Woninginbraak = SoortMisdrijf '1.1.1 '.
- Buurtnamen: https://dataderden.cbs.nl/ODataApi/OData/47024NED/WijkenEnBuurten?$filter=Municipality eq 'GM0344'&$format=json
- Inwoners en woningen per buurt (kerncijfers 2025, OData v4): https://datasets.cbs.nl/odata/v1/CBS/86165NED/Observations?$filter=startswith(WijkenEnBuurten,'BU0344') and (Measure eq 'T001036' or Measure eq 'M000297')&$select=WijkenEnBuurten,Measure,Value
T001036 = inwoners, M000297 = woningvoorraad. Nederland = 'NL00'.
- Grenzen: PDOK WFS https://service.pdok.nl/cbs/wijkenbuurten/2025/wfs/v1_0, typeNames=wijkenbuurten:buurten, outputFormat=application/json, srsName=EPSG:4326, propertyName=buurtcode,buurtnaam, en een FES-filter in de parameter filter:
<Filter xmlns="http://www.opengis.net/fes/2.0"><PropertyIsEqualTo><ValueReference>gemeentecode</ValueReference><Literal>GM0344</Literal></PropertyIsEqualTo></Filter>
Valkuilen die je moet afvangen:
- In de politietabellen (OData v3) zijn sleutels met spaties aangevuld tot een vaste lengte: '0.0.0 ', '1.1.1 ', 'E33 ', 'GM0344 ' (10 tekens), 'NL00 '. Zonder spaties krijg je een lege lijst en geen fout. Buurtcodes zijn al 10 tekens (BU03440111; in Amsterdam met letters: BU0363AE01).
- In de kerncijfers (OData v4 op datasets.cbs.nl) hebben codes géén spaties. Niet door elkaar halen.
- Een vraag die meer dan 10.000 rijen zou geven, faalt met HTTP 500 ('returns less than 10000 records'), zonder odata.nextLink. Splits per soort of per jaar. Volg wel odata.nextLink als die er is.
- Gebruik de buurtindeling van 2025 voor alles (de politie rekent alle jaren om naar 2025): kerncijfers 86165NED en de PDOK-dienst 2025.
- De PDOK-WFS (MapServer) negeert cql_filter en geeft dan 1.000 willekeurige buurten (49 MB). Alleen het FES-filter werkt.
- Trendbreuk in maart 2021 bij overlast: begin de lijn niet vóór 2021 en zet er een opmerking bij.
- Buurten met minder dan 1.000 inwoners: grijs en 'te weinig inwoners om te vergelijken'. Centrumbuurten en stationsbuurten scoren extreem hoog per inwoner door bezoekers; zet daar een uitleg bij (geen ranglijst 'gevaarlijkste buurt').
- Een registratie is geen gebeurtenis: wat niemand meldt, staat er niet in. Oude maanden worden achteraf bijgewerkt: haal altijd de hele reeks opnieuw op.
- Ongeveer 1% van de overlast heeft geen buurt: het gemeentetotaal is iets hoger dan de som van de buurten. Toon het gemeentetotaal uit de gemeenteregel.
- Negatieve waarden in PDOK (-99997) zijn codes voor geheim of onbekend, geen getallen.
Controle: voor Utrecht (GM0344) moet je voor 2025 uitkomen op 27.512 misdrijven, 18.181 overlastmeldingen, 629 woninginbraken, 111 buurten en 376.770 inwoners. Nederland 2025: 808.021 misdrijven en 461.940 overlastmeldingen.
Zet onder het dashboard de bron: 'Politie via CBS (47022NED, 47024NED), CBS Kerncijfers wijken en buurten 2025, PDOK. CC BY 4.0' en de nieuwste maand in de data.
Probeer het zelf
De kern van het project in een klein script. Nodig: Node 20 of nieuwer (ingebouwde fetch), geen pakketten. Opslaan als buurtmonitor.mjs en draaien met: node buurtmonitor.mjs 0344. Getest op 2026-10-16; hieronder de echte uitvoer van die proefdraai.
// Buurtmonitor veiligheid: overlast en misdrijven per buurt, per 1.000 inwoners, door de tijd.
// Bronnen: politie via CBS (47024NED overlast, 47022NED misdrijven), CBS kerncijfers wijken en buurten 2025
// (86165NED: inwoners en woningen) en PDOK wijken en buurten 2025 (grenzen). Geen sleutel nodig.
// Draai met: node buurtmonitor.mjs [gemeentecode zonder GM]
const UA = { "User-Agent": "mijn-buurtmonitor/1.0 (+jij@voorbeeld.nl)" };
const POLITIE = "https://dataderden.cbs.nl/ODataApi/OData";
const KWB = "https://datasets.cbs.nl/odata/v1/CBS/86165NED"; // kerncijfers 2025, zelfde buurtindeling als de politietabellen
const PDOK = "https://service.pdok.nl/cbs/wijkenbuurten/2025/wfs/v1_0";
const GM = process.argv[2] ?? "0344"; // Utrecht
const JAREN = [2021, 2022, 2023, 2024, 2025];
async function json(url) {
const r = await fetch(url, { headers: UA });
if (!r.ok) throw new Error(`${r.status} ${url}`);
return r.json();
}
// Politie (OData v3): volg odata.nextLink als die er is; een vraag die meer dan 10.000 rijen zou geven, faalt met HTTP 500
async function politie(tabel, filter, select) {
let url = `${POLITIE}/${tabel}/TypedDataSet?` + new URLSearchParams({ $filter: filter, $select: select, $format: "json" });
const uit = [];
while (url) { const j = await json(url); uit.push(...j.value); url = j["odata.nextLink"]; }
return uit;
}
const som = (rijen, veld) => rijen.reduce((a, r) => a + (r[veld] ?? 0), 0);
const per1000 = (n, d) => (n / d * 1000).toFixed(1);
// 1. Inwoners (T001036) en woningen (M000297) per buurt. OData v4: codes zonder opvulspaties.
const kwb = await json(`${KWB}/Observations?` + new URLSearchParams({
$filter: `startswith(WijkenEnBuurten,'BU${GM}') and (Measure eq 'T001036' or Measure eq 'M000297')`,
$select: "WijkenEnBuurten,Measure,Value" }));
const buurt = {};
for (const o of kwb.value) {
const b = (buurt[o.WijkenEnBuurten] ??= { overlast: 0, misdrijf: 0, inbraak: 0 });
b[o.Measure === "T001036" ? "inw" : "won"] = o.Value;
}
const inw = Object.values(buurt).reduce((a, b) => a + (b.inw ?? 0), 0);
const won = Object.values(buurt).reduce((a, b) => a + (b.won ?? 0), 0);
// 2. Grenzen en namen uit PDOK. Deze MapServer negeert cql_filter (dan 1.000 buurten, 49 MB): gebruik een FES-filter.
const fes = `<Filter xmlns="http://www.opengis.net/fes/2.0"><PropertyIsEqualTo><ValueReference>gemeentecode</ValueReference><Literal>GM${GM}</Literal></PropertyIsEqualTo></Filter>`;
const geo = await json(`${PDOK}?` + new URLSearchParams({ request: "GetFeature", service: "WFS", version: "2.0.0",
typeNames: "wijkenbuurten:buurten", outputFormat: "application/json", srsName: "EPSG:4326",
propertyName: "buurtcode,buurtnaam,gemeentenaam", filter: fes }));
for (const f of geo.features) if (buurt[f.properties.buurtcode]) buurt[f.properties.buurtcode].naam = f.properties.buurtnaam;
const gekoppeld = geo.features.filter((f) => buurt[f.properties.buurtcode]).length;
console.log(`${geo.features[0].properties.gemeentenaam} (GM${GM}): ${Object.keys(buurt).length} buurten, ${inw.toLocaleString("nl-NL")} inwoners en ${won.toLocaleString("nl-NL")} woningen (kerncijfers 2025), ${gekoppeld} grenzen gekoppeld`);
// 3. Trend voor de hele gemeente. Overlast heeft jaartotalen (JJ00); misdrijven alleen maanden, dus zelf optellen.
const g = `WijkenEnBuurten eq 'GM${GM} '`; // gemeentecode in de politietabellen: aangevuld tot 10 tekens
const ov = await politie("47024NED", `${g} and Overlast eq '0.0.0 ' and substringof('JJ',Perioden)`, "Perioden,GeregistreerdeOverlast_1");
const mi = await politie("47022NED", `${g} and (SoortMisdrijf eq '0.0.0 ' or SoortMisdrijf eq '1.1.1 ')`, "SoortMisdrijf,Perioden,GeregistreerdeMisdrijven_1");
console.log("\nJaar overlast misdrijven woninginbraak | per 1.000 inw: overlast misdr. | inbraak per 1.000 woningen");
for (const j of JAREN) {
const o = som(ov.filter((r) => r.Perioden === `${j}JJ00`), "GeregistreerdeOverlast_1");
const m = som(mi.filter((r) => r.Perioden.startsWith(`${j}MM`) && r.SoortMisdrijf === "0.0.0 "), "GeregistreerdeMisdrijven_1");
const i = som(mi.filter((r) => r.Perioden.startsWith(`${j}MM`) && r.SoortMisdrijf === "1.1.1 "), "GeregistreerdeMisdrijven_1");
console.log(`${j} ${String(o).padStart(9)} ${String(m).padStart(11)} ${String(i).padStart(14)} | ${per1000(o, inw).padStart(19)} ${per1000(m, inw).padStart(6)} | ${per1000(i, won).padStart(5)}`);
}
// 4. Per buurt in 2025. Buurtcodes zijn al 10 tekens, dus daar geen opvulling; soortcodes wel ('0.0.0 ', '1.1.1 ').
const ovB = await politie("47024NED", `Overlast eq '0.0.0 ' and substringof('BU${GM}',WijkenEnBuurten) and Perioden eq '2025JJ00'`, "WijkenEnBuurten,GeregistreerdeOverlast_1");
// Meer dan 10.000 rijen geeft HTTP 500 (geen odata.nextLink): vraag daarom per soort op (Amsterdam: 517 buurten x 12 maanden).
const miB = [];
for (const soort of ["0.0.0 ", "1.1.1 "])
miB.push(...await politie("47022NED", `SoortMisdrijf eq '${soort}' and substringof('BU${GM}',WijkenEnBuurten) and substringof('2025MM',Perioden)`, "WijkenEnBuurten,SoortMisdrijf,GeregistreerdeMisdrijven_1"));
for (const r of ovB) if (buurt[r.WijkenEnBuurten]) buurt[r.WijkenEnBuurten].overlast += r.GeregistreerdeOverlast_1 ?? 0;
for (const r of miB) if (buurt[r.WijkenEnBuurten]) buurt[r.WijkenEnBuurten][r.SoortMisdrijf === "0.0.0 " ? "misdrijf" : "inbraak"] += r.GeregistreerdeMisdrijven_1 ?? 0;
console.log(`\nOverlast 2025: ${som(ovB, "GeregistreerdeOverlast_1")} bij een buurt, ${som(ov.filter((r) => r.Perioden === "2025JJ00"), "GeregistreerdeOverlast_1")} bij de gemeente (rest zonder buurt)`);
const telbaar = Object.entries(buurt).filter(([, b]) => (b.inw ?? 0) >= 1000); // kleine buurten schieten alle kanten op
const rij = ([c, b]) => ` ${c} ${(b.naam ?? "?").slice(0, 27).padEnd(27)} ${String(b.inw).padStart(6)} inw | misdr. ${per1000(b.misdrijf, b.inw).padStart(6)} overlast ${per1000(b.overlast, b.inw).padStart(5)} | inbraak/1.000 won. ${per1000(b.inbraak, b.won).padStart(4)}`;
console.log(`\nMeeste misdrijven per 1.000 inwoners in 2025 (${telbaar.length} buurten met minstens 1.000 inwoners):`);
telbaar.sort((a, b) => b[1].misdrijf / b[1].inw - a[1].misdrijf / a[1].inw).slice(0, 6).forEach((x) => console.log(rij(x)));
console.log("Meeste woninginbraken per 1.000 woningen in 2025:");
telbaar.sort((a, b) => b[1].inbraak / b[1].won - a[1].inbraak / a[1].won).slice(0, 3).forEach((x) => console.log(rij(x)));
const mediaan = (xs) => { const s = [...xs].sort((a, b) => a - b); return s[Math.floor(s.length / 2)]; };
console.log(`Mediaan buurt: ${mediaan(telbaar.map(([, b]) => b.misdrijf / b.inw * 1000)).toFixed(1)} misdrijven en ${mediaan(telbaar.map(([, b]) => b.overlast / b.inw * 1000)).toFixed(1)} overlastmeldingen per 1.000 inwoners`);
Utrecht (GM0344): 111 buurten, 376.770 inwoners en 168.736 woningen (kerncijfers 2025), 111 grenzen gekoppeld Jaar overlast misdrijven woninginbraak | per 1.000 inw: overlast misdr. | inbraak per 1.000 woningen 2021 21096 21765 681 | 56.0 57.8 | 4.0 2022 16342 24093 666 | 43.4 63.9 | 3.9 2023 15602 25437 513 | 41.4 67.5 | 3.0 2024 15478 25124 399 | 41.1 66.7 | 2.4 2025 18181 27512 629 | 48.3 73.0 | 3.7 Overlast 2025: 17974 bij een buurt, 18181 bij de gemeente (rest zonder buurt) Meeste misdrijven per 1.000 inwoners in 2025 (95 buurten met minstens 1.000 inwoners): BU03440613 Hoog-Catharijne NS en Jaarb 2935 inw | misdr. 1252.1 overlast 607.8 | inbraak/1.000 won. 0.8 BU03440612 Lange Elisabethstraat, Mari 1790 inw | misdr. 539.7 overlast 346.9 | inbraak/1.000 won. 4.9 BU03440621 Wijk C 1370 inw | misdr. 516.1 overlast 365.7 | inbraak/1.000 won. 3.5 BU03440611 Domplein, Neude, Janskerkho 2515 inw | misdr. 368.6 overlast 371.8 | inbraak/1.000 won. 3.7 BU03440623 Nobelstraat en omgeving 1000 inw | misdr. 258.0 overlast 160.0 | inbraak/1.000 won. 7.3 BU03440535 Galgenwaard en omgeving 1205 inw | misdr. 205.8 overlast 13.3 | inbraak/1.000 won. 10.5 Meeste woninginbraken per 1.000 woningen in 2025: BU03440113 Halve Maan-Zuid 1485 inw | misdr. 53.9 overlast 37.0 | inbraak/1.000 won. 15.1 BU03440626 Nieuwegracht-Oost 1160 inw | misdr. 169.0 overlast 190.5 | inbraak/1.000 won. 14.4 BU03440535 Galgenwaard en omgeving 1205 inw | misdr. 205.8 overlast 13.3 | inbraak/1.000 won. 10.5 Mediaan buurt: 50.8 misdrijven en 35.2 overlastmeldingen per 1.000 inwoners
Waar het misgaat
- Opvulspaties in de politietabellen: '0.0.0 ', '1.1.1 ', 'GM0344 ' (10 tekens), 'NL00 '. Zonder die spaties krijg je een lege lijst en geen foutmelding. In de kerncijfers op datasets.cbs.nl (OData v4) zijn er juist géén spaties.
- Meer dan 10.000 rijen in één vraag geeft HTTP 500 ('Please redefine your query so that it returns less than 10000 records'), niet een volgende pagina. Bij grote gemeenten per soort of per jaar vragen. Amsterdam met twee soorten en twaalf maanden is al 12.408 rijen.
- Per inwoner misleidt in centrum- en stationsbuurten: Hoog-Catharijne NS en Jaarbeurs heeft 2.935 inwoners maar 3.675 misdrijven in 2025 (1.252 per 1.000). Daar tellen reizigers, winkelend publiek en uitgaanders mee in de teller, niet in de noemer. Laat dat zien in plaats van een ranglijst van 'gevaarlijkste buurten' te maken.
- Kleine aantallen schommelen hard. Halve Maan-Zuid heeft de hoogste inbraakkans van Utrecht (15,1 per 1.000 woningen), maar dat zijn maar 9 inbraken. Toon bij buurten onder de 1.000 inwoners of met minder dan 20 gevallen geen percentage maar 'te klein'.
- Trendbreuk in maart 2021: de politie registreert overlast sindsdien anders, vooral 'verward persoon'. Begin trendlijnen in 2021 of later. De politie werkt ook oude maanden bij, dus laad bij elke verversing de hele reeks opnieuw.
- De PDOK-WFS (MapServer) negeert cql_filter zonder foutmelding en stuurt dan de eerste 1.000 buurten van heel Nederland (49 MB). Gebruik een FES-filter (XML in de parameter filter). En neem de dienst van 2025: alle politiecijfers staan in de buurtindeling van 2025.
- De misdrijventabel heeft geen jaartotalen (alleen maanden), de overlasttabel wel (2025JJ00). En ongeveer 1% van de overlastmeldingen staat wel bij de gemeente maar bij geen enkele buurt: Utrecht 2025 18.181 tegen 17.974.
- Een registratie is geen gebeurtenis. Hoe vaak mensen melden of aangifte doen verschilt per buurt en per soort; bij fietsendiefstal doet een groot deel geen aangifte. Zet dat bij elke grafiek.
Verder bouwen
- Maandelijkse alert: rond de 15e van de maand verschijnt een nieuwe maand. Vergelijk januari tot en met de nieuwste maand met dezelfde maanden vorig jaar en stuur een bericht als een buurt met genoeg meldingen meer dan 30% stijgt.
- Kies een soort: fietsendiefstal (1.2.3), straatroof (1.4.6), verward persoon (E33) of jeugdoverlast (E35) als eigen laag op de kaart, met een seizoenspatroon per maand.
- Leg de buurten naast inkomen en leefbaarheid: gemiddeld inkomen staat ook in de kerncijfers 2025, de Leefbaarometer heeft een score per buurt (laag buurtscore24). Laat de samenhang zien, maar zeg erbij dat samenhang geen oorzaak is.
- Zet het om naar wijken (WK) voor een rustiger beeld: tel buurten op per wijk, of vraag de wijkcodes direct op (WK034401, aangevuld tot 10 tekens).
Meer met deze data
Geregistreerde misdrijven: 45,0 per 1.000 inwoners in 2025, 3,2 keer zo veel als in 1948
Geregistreerde misdrijven, 1948 – 2025, per 1.000 inwoners. Het hoogste punt was 2001 (93,0).
De bronnen4

Geregistreerde overlast per buurtUitgewerkt
Elke maand telt de politie hoeveel meldingen van overlast er binnenkwamen, per buurt en per soort: van verwarde personen en jeugd tot geluidshinder en drugs. CBS publiceert de cijfers als open tabel, met een maand vertraging.

Geregistreerde misdrijven per buurt
Alle misdrijven die de politie registreert, in 59 soorten, per buurt en per maand. Van fietsendiefstal tot woninginbraak.

Kerncijfers wijken en buurten
Ruim honderd cijfers per buurt: inwoners naar leeftijd, huishoudens, WOZ-waarde, inkomen, uitkeringen, auto's en afstand tot voorzieningen. Elk jaar een nieuwe tabel.

Wijk- en buurtkaart
De officiële grenzen van alle gemeenten, wijken en buurten, als kaartlaag (WFS) en als download. De geometrie die je nodig hebt om buurtcijfers op een kaart te zetten.
Meer om te bouwen
Aardbevingentracker: elke beving op de kaart, met gemeente en woningenKaart
Dashboard asielopvang: landelijk en per gemeenteDashboard
Klimaatrisico-check voor een adresTool
Laadpunten per buurt en per elektrische autoKaart
Natuurbrandkaart: risico van vandaag, hittepunten en verbrande natuurKaart
Satelliet voor en na: zie hoe je stad of polder veranderdeTool