
CBS StatLine
The statistics database of Statistics Netherlands: almost 6,000 tables on population, economy, work, housing, energy, care and more, most with long annual, quarterly or monthly series.

CBS StatLine5,961
All StatLine tables, in CBS's own theme tree, fetched every night. Every table has its own page with the OData call.
CBS, tabellen van derden830
Tables CBS publishes on behalf of others (police, RIVM, ministries), by organisation, fetched every night.
Young people under a child protection order (CBS figure, also in Waarstaatjegemeente): highest in Heerlen (2.4%), lowest in Bloemendaal (0.2%)
Young people under a child protection order (CBS figure, also in Waarstaatjegemeente) per municipality, 2025, in percent of under-18s. Netherlands as a whole: 1.0. 330 municipalities with a figure.
Population by marital status: never married is the largest part, 50% in 2026
Breakdown in 2026: never married 50%, married 37%, divorced 7.7%, widowed 4.8%. Total: 18,130,208 residents.
Population by country of origin: the Netherlands is the largest part, 71% in 2026
Breakdown in 2026: the Netherlands 71%, outside Europe 19%, elsewhere in Europe 9.6%. Total: 18,130,208 residents.
Households by composition: living alone is the largest part, 40% in 2026
Breakdown in 2026: living alone 40%, married couple 38%, unmarried couple 13%, single parent 7.5%, other 0.6%. Total: 8,474,674 households.
Population by age: 40 to 65 is the largest part, 32% in 2026
Breakdown in 2026: 40 to 65 32%, 20 to 40 26%, under 20 20%, 65 to 80 16%, 80 or older 5.3%. Total: 18,130,208 residents.
People aged 80 or over in the Netherlands: 957 thousand in 2026, 9.6 times as much as in 1950
People aged 80 or over in the Netherlands, 1950 – 2026, in thousand. That is the highest point in the series.
People living alone: 3.41 million in 2026, 38 times as much as in 1899
People living alone, 1899 – 2026, in million. That is the highest point in the series.
Asylum applications and family reunification: 42.4 thousand per year in 2025, 109 times as much as in 1975
Asylum applications and family reunification, 1975 – 2025, in thousand per year. The highest point was 2015 (58.9).
What you can build with it3
AnalysisHow fast is your municipality going electric?A page showing per municipality what share of passenger cars is fully electric, where it ranks among the 342, and how fast it is going nationally, from the daily RDW count per postcode and the CBS annual series.2 sourcesGetting started
DashboardMonitor for inflation, mortgage rates and savings ratesOne dashboard that shows every month how fast prices rise, what a new mortgage costs and what savings earn, in the Netherlands and the euro area.3 sourcesGetting started
DashboardHousing market dashboard for your municipalityOne page per municipality with sale prices, WOZ value, housing stock, construction years, dwelling size and liveability, next to the national average. All from open APIs without a key.3 sourcesAdvancedWhat can you do with it?2 ideas
One long series, one story
Pick a table with annual figures since 1950 and show what changed. The blocks below are made exactly like that.
From country to neighbourhood
Many tables have a region dimension. The same figures per municipality or neighbourhood become a map.
Interesting combinations
Similar sources
EurostatEuropean figures, often with the Netherlands next to other EU countries.
What to watch out for
- Keys padded with spaces
Dimension keys are padded with spaces ('NL01 '). Without the spaces you get an empty list, not an error.
- Provisional figures
Periods marked * are provisional and get revised. Always reload complete series.
APIOData v3 + OData v4 (CBS) · read 16 Oct 2026
No key or account needed tested
tables in the catalogue (4,914 Dutch, 1,073 English; 1,301 with status Regulier, the rest discontinued) tested
jsonatom/xmlcsv
Base URL
https://opendata.cbs.nl
Endpoints 17
- GET
/ODataCatalog/Tables?$format=jsonAll tables in one response (18 MB): Identifier, Title, ShortDescription, Modified, Frequency, Period, OutputStatus, RecordCount, ColumnCount, ApiUrl, FeedUrl. $filter, $select, $orderby and $top work here. - GET
/ODataCatalog/Themes?$format=jsonStatLine's theme tree: 1,293 themes with ID, ParentID, Number and Title. - GET
/ODataCatalog/Tables_Themes?$format=jsonLink between table and theme (8,162 lines; a table can sit in several themes). - GET
/ODataCatalog/Featured?$format=jsonThe 12 featured topics; Table_Featured links them to tables. - GET
/ODataApi/OData/{tabel}Service document of one table: TableInfos, UntypedDataSet, TypedDataSet, DataProperties, CategoryGroups and one endpoint per dimension. - GET
/ODataApi/OData/{tabel}/TableInfosTitle, summary, period, frequency, status and modification date (Modified). - GET
/ODataApi/OData/{tabel}/DataPropertiesAll columns: dimensions (Dimension, TimeDimension, GeoDetail), topics (Topic, with Unit and Decimals) and groups (TopicGroup). - GET
/ODataApi/OData/{tabel}/{Dimensie}Codes (Key), names and descriptions of one dimension, e.g. /RegioS or /Perioden. - GET
/ODataApi/OData/{tabel}/TypedDataSetThe figures as numbers, one column per topic. At most 10,000 rows per response. - GET
/ODataApi/OData/{tabel}/UntypedDataSetThe same figures as text (sometimes with leading spaces: " 13199"), including symbols for missing values. - GET
/ODataApi/OData/{tabel}/TypedDataSet/$countNumber of rows in the table (37230ned: 196,160). - GET
/ODataApi/OData/{tabel}/$metadataFull data model (XML, EDMX). - GET
/ODataFeed/OData/{tabel}/TypedDataSetSame data as Atom XML in pages of 10,000 with <link rel="next"> ($skip). For the whole table; mind the filter pitfall below. - GET
https://datasets.cbs.nl/odata/v1/CBS/DatasetsNew API (OData v4): all 4,894 Dutch datasets with Identifier, Title, Modified, Status, ObservationCount and Distributions (CSV download). $filter (including contains()), $orderby and $select work. - GET
https://datasets.cbs.nl/odata/v1/CBS/{tabel}One dataset in v4: Properties (description, version, status), Dimensions, MeasureCodes, MeasureGroups, {Dimension}Codes, {Dimension}Groups and Observations. - GET
https://datasets.cbs.nl/odata/v1/CBS/{tabel}/ObservationsLong format: one row per figure (Id, Measure, ValueAttribute, Value, StringValue, dimensions). 100,000 per page with @odata.nextLink; $count with a filter works. - GET
https://datasets.cbs.nl/csv/CBS/nl/{tabel}The whole dataset as a ZIP of CSVs (37230ned: 16.7 MB, file name with version: 37230ned-202609300000.zip).
The APIs of this source 2 · from the provider's documentation from the description
OData v4 (CBS Cijfer Bank)
The new API: long format (one row per figure), stable topic codes, 100,000 cells per page, CSV download per dataset. Dutch CBS tables only.
https://datasets.cbs.nl/odata/v1- GET
/CBS/Datasets?$filter=contains(Title,'wijken')Zoeken in alle datasets - GET
/CBS/{tabel}/Observations?$filter=RegioS eq 'GM0363'Cijfers, sleutels zonder spaties - GET
/CBS/{tabel}/MeasureCodesOnderwerpen met titel, eenheid en beschrijving - GET
https://datasets.cbs.nl/csv/CBS/nl/{tabel}Hele dataset als ZIP met CSV
Tabellen van derden
The same OData v3 API for tables CBS publishes on behalf of others: 829 tables from e.g. the police, RIVM, Iv3 (municipal finances).
https://dataderden.cbs.nl- GET
/ODataCatalog/Tables?$format=json&$filter=Catalog eq 'Politie'Tabellen per eigenaar - GET
/ODataApi/OData/{tabel}/TypedDataSetCijfers, zelfde regels als opendata.cbs.nl
Filtering tested
OData expressions in $filter. Keys in single quotes; padded with spaces to a fixed length in v3, unpadded in v4. Only dimensions can be filtered.
Parameters 6
$filter | Select rows on dimensions: RegioS eq 'GM0363', startswith(Perioden,'2026'), substringof('wijken',Title) in the catalogue. In v4 also in (…), ge/le on Perioden and contains(). | tested |
$select | Only these columns; an unknown column gives HTTP 500 (v3) or 400 (v4) with "Could not find a property named …". | tested |
$top / $skip | Paging. v3: more than 10,000 rows gives an error; v4: $top up to 100,000. | tested |
$orderby | Works in the catalogue and in v4, but is ignored by the v3 table endpoints. | tested |
$format | json or atom. Without $format=json the catalogue returns Atom XML. | tested |
$count | After a path: count only. In v3, /{Dimension}/$count ignores $filter; on the catalogue it works. | tested |
Fields in the catalogue (ODataCatalog/Tables) 9
| Name | Type | Meaning |
|---|---|---|
Identifier | tekst | Tabelcode, bv. 37230ned of 85984NED (hoofdletters verschillen per tabel) |
Title | tekst | Titel van de tabel |
Modified | datetime | Laatste wijziging (verandert ook bij metadata) |
Frequency | tekst | Permaand, Perkwartaal, Perjaar, Eenmalig … |
Period | tekst | Periode als tekst ('Januari 2002 - augustus 2026') |
OutputStatus | tekst | Regulier of Gediscontinueerd |
RecordCount | getal | Aantal rijen in TypedDataSet |
ApiUrl | url | Adres van de tabel in de OData v3-API |
Catalog | tekst | CBS (opendata.cbs.nl) of een derde (Politie, RIVM … op dataderden.cbs.nl) |
Limits and pitfalls
- OData v3 (/ODataApi/): more than 10,000 rows returns HTTP 500 "Please redefine your query so that it returns less than 10000 records". /ODataFeed/ pages per 10,000. tested
- OData v4 (datasets.cbs.nl): at most 100,000 cells per response, follow @odata.nextLink. $top above 100,000 returns 400. tested
- No key and no published rate limit. opendata.cbs.nl returned HTTP 503 (Service Unavailable) for a while on 16 Oct 2026 and earlier that day sometimes hung for a minute: use timeouts and retry later. tested
- Keys in v3 are padded with spaces to the longest code of that dimension: 'NL01 ' and 'GM0363' (RegioS, 6 characters) but 'GM0363 ' (WijkenEnBuurten, 10 characters). Without padding you get an empty list, not an error. Read the length from /{Dimension}. In v4 keys are unpadded; with spaces you get nothing there. tested
- In v3, $filter only works on dimensions. A filter on a topic (Overledenen_3 gt 12000) is silently ignored and returns every row. v4 is more honest: filtering on Value returns 400 "cannot be used in the $filter query option". tested
- The Feed endpoint (/ODataFeed/) applies only the first $filter predicate and silently ignores the rest. experience
- Period codes: 2025JJ00 (year), 2026KW02 (quarter), 2026MM08 (month). A * in the title or Status 'Voorlopig' (v4 PeriodenCodes) = provisional. Past periods get revised: always reload complete series. tested
- Topic codes differ between v3 (Overledenen_3, the number shifts per table version) and v4 (M000134, stable across tables). CBS dataset 900002NED (in v4) maps them: per table OData3Identifier to OData4Identifier. tested
- v4 only has the Dutch CBS tables (0 English, no third parties). The English tables (…ENG) and third-party tables (police, RIVM: dataderden.cbs.nl) are only in v3. tested
- v4 $metadata returns 406 with curl's default Accept header (*/*); send Accept: application/xml. ReleaseCalendar took 28 s and was empty. $apply is not supported. The odata4.cbs.nl address (old beta) no longer exists (DNS). tested
- TableInfos.Modified changes almost daily (metadata too). For freshness: the highest Perioden code, or ObservationsModified in v4. experience
- opendata.cbs.nl's robots.txt disallows /ODataAPI/OData/*, /ODataFeed/OData/* and /ODataCatalog/OData/* (with Noindex, aimed at search engines). The documented paths use /ODataApi/ (different case) and /ODataCatalog/Tables. datasets.cbs.nl and dataderden.cbs.nl have no robots.txt (404). tested
- Python urllib (LibreSSL on macOS) fails on cbs.nl's TLS; use curl, Node fetch or the packages cbsodata (Python) and cbsodataR (R). experience
Try it HTTP 200 · 328 ms · 16 Oct
https://opendata.cbs.nl/ODataCatalog/Tables?$format=json&$orderby=Modified desc&$top=3&$select=Identifier,Title,Modified,Period,RecordCount,ApiUrl
{
"odata.metadata": "https://opendata.cbs.nl/ODataCatalog/$metadata#Tables&$select=Identifier,Title,Modified,Period,RecordCount,ApiUrl",
"value": [
{
"Identifier": "81901NED",
"Title": "Beloningsverschillen tussen mannen en vrouwen; kenmerken baan, werknemer",
"Modified": "2026-10-16T02:00:00",
"Period": "2008-2025",
"ApiUrl": "https://opendata.cbs.nl/ODataApi/OData/81901NED",
"RecordCount": 468
},
{
"Identifier": "81920NED",
"Title": "Beloningsverschillen tussen mannen en vrouwen; bedrijfstakken (SBI 2008)",
"Modified": "2026-10-16T02:00:00",
"Period": "2008-2025",
"ApiUrl": "https://opendata.cbs.nl/ODataApi/OData/81920NED",
"RecordCount": 522
}
]
}Shortened response, saved at harvest time. Click the URL for the real, current response.
Read from CBS: quick start OData v3 (R package cbsodataR, Python package cbsodata) · CBS: quick start OData v4 (datasets.cbs.nl, Observations, @odata.nextLink) · Service document of the catalogue (Tables, Themes, Tables_Themes, Featured) · Service document of the new API (Datasets, Catalogs, ReleaseCalendar). Labels: from the description stated in what the api itself publishes. tested from our own small call. platform applies to every api on this platform, per its documentation. experience learned while building open data index.
More from CBS in our index
14,153 datasets in data.overheid.nl, CBS StatLine, Nationaal Georegister, NDE Datasetregister. These changed most recently.
- Nieuwbouwwoningen; inputprijsindex bouwkosten 2000=100, vanaf 19902026-10-30
- Arable crops; production, region2026-10-30
- Elektriciteitsbalans; aanbod en verbruik2026-10-30
- New dwellings; input price indices building costs 2021=1002026-10-30
- Bevolking op 31 december, immigranten niet-EU/EFTA, migratiemotief2026-10-30
- Bouwnijverheid; productieve uren in de burgerlijke en utiliteitsbouw2026-10-30
More in this topic
See how this page is built
bron: cbs-statline blokken: [] secties: - ideeen - koppelingen - vergelijkbaar - beperkingen cache: tag: bron:cbs-statline ververs: na statuscheck, als de bron nieuwer is statuscheck: methode: "ODataCatalog: nieuwste wijziging van een tabel" verwacht: dagelijks
Source: content/bronnen/cbs-statline.yaml · Markdown

