# KB, nationale bibliotheek (linked data)

Op data.bibliotheken.nl publiceert de KB haar catalogi als linked data onder CC0: de Nederlandse Bibliografie Totaal (NBT, 4.911.178 boeken), de Short Title Catalogue Netherlands (STCN, 225.218 titels gedrukt tot 1801, met 651.395 exemplaren), de Nederlandse Thesaurus van Auteursnamen (2.816.677 personen), de Brinkman-trefwoorden en de titels en auteurs van de DBNL. Samen 258.524.625 statements, te bevragen met SPARQL (stand 16 oktober 2026).

- Uitgever: KB, nationale bibliotheek
- Gebied: Nederland · Laagste detail: titel
- Periode: 1473 – heden · Ververst: elk kwartaal
- Toegang: Open · Licentie: CC0 1.0 (alle data op data.bibliotheken.nl)
- Koppelsleutels: PPN (KB-identifier, bv. p262454742), ISBN, NTA-persoons-id
- Status: ok (2026-09-25) · 258.524.625 statements, 21 grafen
- URL: https://data.bibliotheken.nl

## Wat kun je ermee?
- **Het rampjaar in drukwerk.** In de STCN staan 1.485 titels uit 1672, tegen 808 in 1671 en 903 in 1673. Ook 1787 (2.021) en 1795 (2.195) springen eruit. Lees welke pamfletten het waren.
- **Wie schreef het?.** De auteursthesaurus (NTA) geeft elke persoon een vaste identifier, vaak met geboortedatum, beroep en links naar andere registers (schema:sameAs). Handig om naamgenoten uit elkaar te houden in een factcheck.
- **Drukkers en hun steden.** De STCN beschrijft per titel de uitgave: drukker (schema:publisher) en een regel als 'Amsterdam, J. Allart, 1781'. Haal de stad daaruit, tel per eeuw en vergelijk Amsterdam, Leiden en Den Haag.
- **Taal van de boeken.** Elke titel in de NBT heeft een schema:inLanguage. Bekijk hoe het aandeel Engelstalige titels zich ontwikkelt, met de kanttekening uit de beperkingen.

## Zo verwerk je het
1. **Een eerste telling.** Elke deelverzameling is een eigen graaf (nbt, stcn-titles, nta, brinkman …). Een GET met ?query= werkt; vraag CSV met de kop Accept: text/csv of JSON met application/sparql-results+json.
   `https://data.bibliotheken.nl/sparql?query=SELECT%20%28COUNT%28%2A%29%20AS%20%3Fn%29%20WHERE%20%7B%20GRAPH%20%3Chttp%3A%2F%2Fdata.bibliotheken.nl%2Fnbt%3E%20%7B%20%3Fs%20a%20%3Chttp%3A%2F%2Fschema.org%2FBook%3E%20%7D%20%7D`
2. **Titels uit één jaar (STCN).** Het jaar van verschijnen zit in een tussenknoop, schema:publication/schema:startDate. Onzekere jaren staan als 16XX of 179X.
   `https://data.bibliotheken.nl/sparql?query=SELECT%20%3Ftitel%20%3Fnaam%20WHERE%20%7B%20GRAPH%20%3Chttp%3A%2F%2Fdata.bibliotheken.nl%2Fstcn-titles%3E%20%7B%20%3Ftitel%20%3Chttp%3A%2F%2Fschema.org%2Fname%3E%20%3Fnaam%20%3B%20%3Chttp%3A%2F%2Fschema.org%2Fpublication%3E%2F%3Chttp%3A%2F%2Fschema.org%2FstartDate%3E%20%221672%22%20%7D%20%7D%20LIMIT%2010`
3. **Boeken per jaar (NBT).** In de NBT staat het jaar in http://purl.org/dc/terms#issued, met een hekje in plaats van een schuine streep. Met de gewone dcterms:issued vind je niets.
   `https://data.bibliotheken.nl/sparql?query=SELECT%20%3Fjaar%20%28COUNT%28%3Fs%29%20AS%20%3Fn%29%20WHERE%20%7B%20GRAPH%20%3Chttp%3A%2F%2Fdata.bibliotheken.nl%2Fnbt%3E%20%7B%20%3Fs%20a%20%3Chttp%3A%2F%2Fschema.org%2FBook%3E%20%3B%20%3Chttp%3A%2F%2Fpurl.org%2Fdc%2Fterms%23issued%3E%20%3Fjaar%20%7D%20FILTER%28STR%28%3Fjaar%29%20%3E%3D%20%222015%22%20%26%26%20STR%28%3Fjaar%29%20%3C%3D%20%222025%22%29%20%7D%20GROUP%20BY%20%3Fjaar%20ORDER%20BY%20%3Fjaar`
4. **Rustig aan.** robots.txt vraagt 2 seconden tussen verzoeken. Tel en groepeer op de server (COUNT, GROUP BY) in plaats van miljoenen rijen op te halen. Op het portaal staan ook voorbeeldvragen en het datamodel.
   `https://data.bibliotheken.nl/KB/Production`

## Interessante koppelingen
- Wat zeiden pamfletten en overheid in hetzelfde jaar? → [nationaal-archief](https://www.opendataindex.nl/bron/nationaal-archief.md) via jaar en onderwerp. Zet de STCN-titels uit 1672 of 1795 naast de archieven van de Staten-Generaal uit die jaren in de inventarissen van het Nationaal Archief.
- Wie maakte prenten en wie drukte boeken? → [rijksmuseum](https://www.opendataindex.nl/bron/rijksmuseum.md) via naam van drukker of maker. Veel drukkers en uitgevers in de STCN maakten of verkochten ook prenten. Zoek hun naam als creator in de Rijksmuseum-API.

## Vergelijkbare bronnen
- [Delpher](https://www.delpher.nl): Ook van de KB, maar de gedigitaliseerde teksten zelf (kranten, boeken, tijdschriften) in plaats van de catalogusgegevens.
- [rijksmuseum](https://www.opendataindex.nl/bron/rijksmuseum.md): Museumstukken in plaats van gedrukte titels; ook linked data en zonder sleutel.
- [europeana](https://www.opendataindex.nl/bron/europeana.md): Europese collecties met gedigitaliseerde boeken en kranten, maar met een API-sleutel.

## Waar je op moet letten
- **Geen maat voor de boekproductie.** De NBT telt 67.175 titels voor 2014, 23.339 voor 2024 en 32.578 voor 2025. Of dat aan minder boeken of aan de beschrijving en het depot ligt, staat er niet bij. Gebruik de aantallen niet zonder meer als maat voor wat er verschijnt.
- **Niet elke deelverzameling is even vers.** Laatst gewijzigd volgens de datasetbeschrijvingen (16 okt 2026): auteurs (NTA) 17 september 2026, NBT 1 juni 2026, STCN 23 februari 2026, GTT oktober 2021 (in gebruik tot 2012).
- **Jaartallen zijn tekst.** Naast 1990 staan waarden als 199X, 19XX en 2015-2016. Filter op vier cijfers als je per jaar telt, en zeg hoeveel je hebt weggelaten.
- **Titels en exemplaren door elkaar.** In de graaf stcn-titles staan zowel titels als exemplaren (met schema:exampleOfWork). Tel titels via schema:publication, anders tel je een boek meerdere keren.

## API (SPARQL 1.1 (TriplyDB, Virtuoso))

- Basis: https://data.bibliotheken.nl/sparql
- Toegang: Geen sleutel of account nodig (getest)
- Formaten: json, sparql-results+json, csv, tsv, turtle, n-triples
- Omvang: 258524625 statements in 21 grafen (TriplyDB, laatste update 25 sep 2026) (getest)
- Filteren: SPARQL 1.1: GRAPH om een deelverzameling te kiezen, FILTER, VALUES, GROUP BY en COUNT om op de server te tellen. Prefixes schema: = http://schema.org/ (http, niet https), kb: = http://data.bibliotheken.nl/def#.; SELECT, CONSTRUCT, DESCRIBE, GRAPH, FILTER, VALUES, GROUP BY, COUNT(DISTINCT), OPTIONAL, pad/pad

### Endpoints
- `GET /sparql?query=…`: SPARQL-vraag in de URL. Zonder Accept-kop of met application/json: een platte JSON-lijst van rijen; met application/sparql-results+json het standaardformaat; text/csv een tabel.
- `POST /sparql`: Dezelfde vraag als formulierveld query= (handig voor lange vragen).
- `GET https://api.bibliotheken.nl/datasets/KB/Production/services/Production-VTS/sparql`: Het Virtuoso-endpoint zelf, waar /sparql naar doorverwijst.
- `GET http://data.bibliotheken.nl/id/nbt/{ppn}`: Linked data: een URI opvragen met Accept: text/turtle geeft alle triples over die titel (via /describe?resource=).
- `GET /_api/datasets/KB/Production`: Metadata van de dataset (statements, graphCount, lastGraphsUpdateTime, licentie).

### Parameters
- `query`: De SPARQL-vraag (GET in de URL of POST als formulierveld). (getest)
- `Accept`: application/sparql-results+json, application/json (platte lijst), text/csv, text/turtle (bij CONSTRUCT/DESCRIBE en URI's). (getest)
- `GRAPH <http://data.bibliotheken.nl/nbt>`: Nederlandse Bibliografie Totaal: 4,9 mln boeken (schema:Book), 194,8 mln triples. (getest)
- `GRAPH <http://data.bibliotheken.nl/stcn-titles>`: STCN: 225.218 titels tot 1801 plus exemplaren, 13,5 mln triples. Ook stcn-persons en stcn-printers. (getest)
- `GRAPH <http://data.bibliotheken.nl/nta>`: Nederlandse Thesaurus van Auteursnamen: 2,8 mln personen, 41,8 mln triples. (getest)
- `andere grafen`: corporaties, dbnla en dbnlt (DBNL-auteurs en -titels), gtt, kbcode, brinkman, rise-alba, rise-centsprenten, datasetbeschrijvingen, en per graaf een *-invalidated met vervallen records. (getest)

### Predicaten in de grafen (selectie) (14)
`schema:name` tekst, `http://purl.org/dc/terms#issued` tekst, `schema:publication / schema:startDate` tekst, `schema:publication / sem:hasEarliestBeginTimeStamp, sem:hasLatestEndTimeStamp` gYear, `schema:publication / schema:publisher, schema:location` uri, `schema:author / schema:contributor` uri, `schema:inLanguage` tekst, `schema:isbn` tekst, `schema:about` uri, `schema:numberOfPages / schema:bookEdition / schema:bookFormat` tekst, `kb:ppn` tekst, `schema:birthDate / schema:deathDate / schema:hasOccupation` tekst, `schema:sameAs / owl:sameAs` uri, `schema:exampleOfWork` uri

### Limieten en valkuilen
- robots.txt vraagt Crawl-delay 2: wacht 2 seconden tussen vragen. (getest)
- Tel en groepeer op de server: een GROUP BY over alle 4,9 mln NBT-boeken duurde 4 seconden, een telling per graaf over alle 258 mln triples minder dan 1 seconde (vermoedelijk uit een cache). (getest)
- In de NBT heet het jaar http://purl.org/dc/terms#issued (met een hekje). Wie de gewone prefix dcterms: gebruikt, krijgt nul resultaten zonder foutmelding. (getest)
- In stcn-titles staan titels én exemplaren. Tel titels via schema:publication en met COUNT(DISTINCT). De uitkomst hangt af van de telwijze: met DISTINCT gaf 1672 1.499 titels. (getest)
- Bijna alle schema.org-predicaten staan onder http://schema.org/ (http). Uitzondering: de afbeelding in stcn-titles is https://schema.org/image. Controleer de prefix met een telling per predicaat. (getest)
- Elke graaf heeft een *-invalidated-tegenhanger met vervallen records (nbt-invalidated, nta-invalidated …). Laat die weg als je actuele aantallen wilt. (getest)

### Voorbeeld
```
https://data.bibliotheken.nl/sparql?query=SELECT%20%3Fjaar%20%28COUNT%28DISTINCT%20%3Ft%29%20AS%20%3Ftitels%29%20WHERE%20%7B%20GRAPH%20%3Chttp%3A%2F%2Fdata.bibliotheken.nl%2Fstcn-titles%3E%20%7B%20%3Ft%20%3Chttp%3A%2F%2Fschema.org%2Fpublication%3E%2F%3Chttp%3A%2F%2Fschema.org%2FstartDate%3E%20%3Fjaar%20%7D%20VALUES%20%3Fjaar%20%7B%20%221671%22%20%221672%22%20%221673%22%20%7D%20%7D%20GROUP%20BY%20%3Fjaar%20ORDER%20BY%20%3Fjaar
```

## Zo haal je het op

### curl
```bash
curl -H "Accept: text/csv" --data-urlencode 'query=SELECT (COUNT(*) AS ?n) WHERE { GRAPH <http://data.bibliotheken.nl/nbt> { ?s a <http://schema.org/Book> } }' https://data.bibliotheken.nl/sparql
```

### python
```python
import requests, time

q = """SELECT ?jaar (COUNT(DISTINCT ?t) AS ?n) WHERE {
  GRAPH <http://data.bibliotheken.nl/stcn-titles> {
    ?t <http://schema.org/publication>/<http://schema.org/startDate> ?jaar } }
GROUP BY ?jaar ORDER BY ?jaar"""
r = requests.post("https://data.bibliotheken.nl/sparql", data={"query": q},
                  headers={"Accept": "application/sparql-results+json"})
for b in r.json()["results"]["bindings"]:
    if b["jaar"]["value"] in ("1672", "1787", "1795"):
        print(b["jaar"]["value"], b["n"]["value"])
time.sleep(2)  # robots.txt: Crawl-delay 2
```


## Wat er allemaal in zit: 25 datasets en grafen

Wat de KB op data.bibliotheken.nl aanbiedt: de beschreven datasets (NBT, STCN, thesauri) met het aantal statements van hun graaf, en de grafen zonder eigen beschrijving. Elke nacht opgehaald.

- Soorten: dataset 18, graaf 7
- Laatst gewijzigd: 2026-10-16 (1 in de afgelopen 30 dagen)
- Met een API-aanroep op de datasetpagina: 25
- Zoeken: https://www.opendataindex.nl/api/catalogus/kb?q=… of de MCP-functie zoek_datasets met herkomst=kb
- Elke rij heeft een eigen pagina: https://www.opendataindex.nl/dataset/kb/<sleutel>

### Mappen
- KB-data (Production) (24): Beschreven datasets (17), Grafen zonder beschrijving (7)
- merian (1)

## Voorbeelden met echte cijfers (1)

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

- **Gedrukte titels uit de Nederlanden per jaar (STCN, KB): 1.364 titels in 1800, 49 keer zo veel als in 1540** (1800). Tabel stcn-titles. [Voorbeeld](https://www.opendataindex.nl/voorbeeld/kb-stcn-titels-per-jaar)
  - `https://data.bibliotheken.nl/sparql?query=SELECT%20%3Fjaar%20(COUNT(DISTINCT%20%3Ftitel)%20AS%20%3Fn)%20WHERE%20%7B%0A%20%20GRAPH%20%3Chttp%3A%2F%2Fdata.bibliotheken.nl%2Fstcn-titles%3E%20%7B%0A%20%20%20%20%3Ftitel%20a%20%3Chttp%3A%2F%2Fschema.org%2FBook%3E%20%3B%20%3Chttp%3A%2F%2Fschema.org%2Fpublication%3E%20%3Fpub%20.%0A%20%20%20%20%3Fpub%20%3Chttp%3A%2F%2Fschema.org%2FstartDate%3E%20%3Fjaar%20.%0A%20%20%7D%0A%7D%20GROUP%20BY%20%3Fjaar%20ORDER%20BY%20%3Fjaar`
