Van "bis" tot "III", van "-hs" tot "rood": een uitgebreide handleiding voor het correct parseren en matchen van Nederlandse huisnummer toevoegingen. Met code voorbeelden en regex patronen.
Nederlandse huisnummers behoren tot de meest complexe ter wereld. Waar veel landen simpelweg nummers gebruiken (123, 456), kent Nederland een rijke historie van toevoegingen, letters, Romeinse cijfers en zelfs kleuren. Voor ontwikkelaars die werken met adresdata is het correct parseren en matchen van deze toevoegingen een echte uitdaging.
In deze uitgebreide gids duiken we diep in de wereld van Nederlandse huisnummer toevoegingen. We bekijken de historische achtergrond, alle mogelijke variaties, en geven je concrete code voorbeelden om zelf aan de slag te gaan met adres parsing.

Waarom zijn Nederlandse huisnummers zo complex?
De complexiteit van Nederlandse huisnummers is historisch gegroeid. In de eeuwen dat steden zich ontwikkelden, werden bestaande panden gesplitst, samengevoegd of opgedeeld in meerdere wooneenheden. Om toch elk adres uniek te houden, ontstonden creatieve oplossingen.
Grachtenpanden en verticale splitsing
De Amsterdamse grachtenpanden vormen het bekendste voorbeeld. Deze panden zijn vaak verticaal opgedeeld in appartementen op verschillende verdiepingen. Om deze te onderscheiden ontstonden toevoegingen als Romeinse cijfers (I, II, III) en aanduidingen als "huis" (hs) voor de begane grond en "souterrain" (sous) voor de kelder.

Horizontale splitsing en nieuwbouw
Bij horizontale splitsing (naast elkaar gelegen woningen in één pand) worden vaak letters gebruikt: A, B, C of kleine letters a, b, c. Bij nieuwbouw op voormalige percelen zien we ook "bis" en "ter" voor respectievelijk de tweede en derde woning op een perceel.
Alle types huisnummer toevoegingen
In de officiële BAG (Basisregistratie Adressen en Gebouwen) worden toevoegingen geregistreerd in twee aparte velden: huisletter en huisnummertoevoeging. Laten we alle mogelijke types bekijken:
1. Letters (huisletter)
Enkelvoudige letters zijn de meest voorkomende toevoeging. In de BAG worden deze geregistreerd in het huisletter-veld.
| Notatie | Voorbeelden | Opmerkingen |
|---|---|---|
| Hoofdletter | 12A, 12B, 12C | Officiële BAG-notatie |
| Kleine letter | 12a, 12b, 12c | Vaak gebruikt, moet genormaliseerd worden |
| Met spatie | 12 A, 12 B | Informele schrijfwijze |
| Met koppelteken | 12-A, 12-B | Informele schrijfwijze |
BAG normalisatie
In de BAG worden huisletters altijd als hoofdletter opgeslagen, zonder scheidingsteken. "12a", "12 a" en "12-A" worden allemaal "12A" in de officiële registratie.
2. Romeinse cijfers
Romeinse cijfers duiden vaak verdiepingen aan, vooral in grachtenpanden. Ze worden opgeslagen in het huisnummertoevoeging-veld.
| Romeins | Arabisch | Betekenis |
|---|---|---|
| I | 1 | Eerste verdieping |
| II | 2 | Tweede verdieping |
| III | 3 | Derde verdieping |
| IV | 4 | Vierde verdieping |
| V | 5 | Vijfde verdieping |
// Functie om Romeinse cijfers te converteren naar Arabische getallenfunction romanToArabic(roman) {const romanNumerals = {'I': 1, 'V': 5, 'X': 10, 'L': 50,'C': 100, 'D': 500, 'M': 1000};let result = 0;for (let i = 0; i < roman.length; i++) {const current = romanNumerals[roman[i]];const next = romanNumerals[roman[i + 1]];if (next && current < next) {result -= current;} else {result += current;}}return result;}// Voorbeeldconsole.log(romanToArabic('III')); // 3console.log(romanToArabic('IV')); // 4
3. Huis, souterrain en bel-etage
Deze historische aanduidingen verwijzen naar specifieke verdiepingen in traditionele panden:
| Toevoeging | Afkorting | Betekenis | Locatie |
|---|---|---|---|
| huis | hs | De hoofdwoning | Begane grond of bel-etage |
| souterrain | sous | Kelder/ondergelegen | Onder straatniveau |
| bel-etage | bel | Verhoogde begane grond | Half niveau boven straat |
| parterre | part | Gelijkvloers | Begane grond |
| bovenhuis | bov | Bovengelegen woning | Boven de hoofdwoning |
Afkortingen in de praktijk
Let op: in de praktijk worden zowel voluit geschreven termen ("huis") als afkortingen ("hs") gebruikt. Je parsing logica moet beide varianten ondersteunen.
4. Bis en ter
"Bis" (Latijn voor "tweemaal") en "ter" (Latijn voor "driemaal") worden gebruikt wanneer er meerdere woningen op één perceel zijn gebouwd. Dit zie je vaak bij nieuwbouw op voormalige tuinen of na splitsing van grote kavels.
| Toevoeging | Betekenis | Voorbeeld |
|---|---|---|
| bis | Tweede woning op perceel | Hoofdstraat 12bis |
| ter | Derde woning op perceel | Hoofdstraat 12ter |
| quater | Vierde woning (zeldzaam) | Hoofdstraat 12quater |
5. Kleur aanduidingen
In sommige oude stadsdelen, met name in Amsterdam, werden historisch kleuren gebruikt om panden te onderscheiden. Dit komt voort uit de tijd dat huizen nog geen nummers hadden.
| Kleur | Voorbeelden | Herkomst |
|---|---|---|
| rood | Keizersgracht 123-rood | Rode gevelsteen of deur |
| zwart | Herengracht 45-zwart | Zwart geschilderde elementen |
| groen | Prinsengracht 78-groen | Groene luiken of deur |
| wit | Singel 99-wit | Witte gevel |
Kleur toevoegingen zijn zeldzaam
Kleur-gebaseerde toevoegingen komen vrijwel alleen voor in historische binnensteden en zijn grotendeels verdwenen door hernummering. Je hoeft ze niet te ondersteunen voor de meeste toepassingen, maar wees je er wel van bewust.
6. Numerieke toevoegingen
Naast Romeinse cijfers worden ook gewone (Arabische) cijfers als toevoeging gebruikt, vooral bij appartementen en flats.
| Notatie | Voorbeeld | Uitleg |
|---|---|---|
| Direct | 12-1, 12-2 | Appartement 1, 2, etc. |
| Genest | 12-1a, 12-1b | Sub-appartementen |
| Hoog | 12-101, 12-201 | Verdieping + appartement nummer |
BAG structuur: huisletter vs huisnummertoevoeging
In de BAG worden toevoegingen opgesplitst in twee velden. Dit onderscheid is cruciaal voor correcte matching:
| Veld | Type | Maximaal | Voorbeelden |
|---|---|---|---|
| huisletter | Enkele letter | 1 karakter | A, B, C, D... |
| huisnummertoevoeging | Tekst | 4 karakters | bis, I, II, 101, hs |
// BAG adres structuurinterface BAGAddress {straatnaam: string;huisnummer: number;huisletter?: string; // Max 1 karakter: A-Zhuisnummertoevoeging?: string; // Max 4 karakters: bis, I, 101, hspostcode: string;woonplaatsnaam: string;}// Voorbeelden van BAG adressenconst examples: BAGAddress[] = [{straatnaam: "Damrak",huisnummer: 1,huisletter: undefined,huisnummertoevoeging: undefined,postcode: "1012LG",woonplaatsnaam: "Amsterdam"},{straatnaam: "Herengracht",huisnummer: 123,huisletter: "A",huisnummertoevoeging: undefined,postcode: "1015BK",woonplaatsnaam: "Amsterdam"},{straatnaam: "Keizersgracht",huisnummer: 456,huisletter: undefined,huisnummertoevoeging: "III",postcode: "1016EJ",woonplaatsnaam: "Amsterdam"},{straatnaam: "Prinsengracht",huisnummer: 789,huisletter: "B",huisnummertoevoeging: "hs",postcode: "1017KL",woonplaatsnaam: "Amsterdam"}];
Adres parsing met regex
Het parsen van Nederlandse adressen vereist een robuuste regex die alle variaties ondersteunt. Hier is een uitgebreide implementatie:
/*** Nederlandse adres parser* Ondersteunt alle gangbare huisnummer toevoegingen*/const ADDRESS_REGEX = /^(.+?)\s+(\d+)\s*([A-Za-z])?\s*[-\/]?\s*(.+)?$/;function parseAddress(address) {// Normaliseer de inputconst normalized = address.trim().replace(/\s+/g, ' ').replace(/,/g, '');const match = normalized.match(ADDRESS_REGEX);if (!match) {return null;}const [, street, number, letter, addition] = match;return {street: street.trim(),number: parseInt(number, 10),letter: letter ? letter.toUpperCase() : null,addition: normalizeAddition(addition)};}function normalizeAddition(addition) {if (!addition) return null;const normalized = addition.trim().toLowerCase();// Normaliseer bekende afkortingenconst abbreviations = {'huis': 'hs','souterrain': 'sous','beletage': 'bel','bel-etage': 'bel','bovenhuis': 'bov','parterre': 'part','1e': 'I','2e': 'II','3e': 'III','4e': 'IV','1ste': 'I','2de': 'II','3de': 'III'};return abbreviations[normalized] || addition.toUpperCase();}// Test voorbeeldenconst testAddresses = ["Herengracht 123A","Keizersgracht 456 III","Prinsengracht 789-bis","Damrak 1 B hs","Rokin 50-2","Singel 100 huis"];testAddresses.forEach(addr => {console.log(`Input: ${addr}`);console.log('Parsed:', parseAddress(addr));console.log('---');});
Python implementatie
import refrom dataclasses import dataclassfrom typing import Optional@dataclassclass ParsedAddress:street: strnumber: intletter: Optional[str] = Noneaddition: Optional[str] = Nonedef parse_address(address: str) -> Optional[ParsedAddress]:"""Parse een Nederlands adres en extraheer componenten.Ondersteunt:- Letters: 12A, 12 A, 12-A- Romeinse cijfers: 12-III, 12 III- Toevoegingen: 12bis, 12-hs, 12 huis"""# Regex voor Nederlandse adressenpattern = r'^(.+?)\s+(\d+)\s*([A-Za-z])?\s*[-/]?\s*(.+)?$'normalized = ' '.join(address.strip().split())match = re.match(pattern, normalized)if not match:return Nonestreet, number, letter, addition = match.groups()return ParsedAddress(street=street.strip(),number=int(number),letter=letter.upper() if letter else None,addition=normalize_addition(addition))def normalize_addition(addition: Optional[str]) -> Optional[str]:"""Normaliseer huisnummer toevoegingen naar BAG-standaard."""if not addition:return Nonenormalized = addition.strip().lower()abbreviations = {'huis': 'hs','souterrain': 'sous','bel-etage': 'bel','beletage': 'bel','bovenhuis': 'bov','parterre': 'part',}return abbreviations.get(normalized, addition.upper())# Testif __name__ == "__main__":test_addresses = ["Herengracht 123A","Keizersgracht 456-III","Prinsengracht 789 bis","Damrak 1B hs",]for addr in test_addresses:result = parse_address(addr)print(f"{addr} -> {result}")
Fuzzy matching van toevoegingen
In de praktijk komen gebruikers met allerlei schrijfvarianten. Een robuuste matcher moet "12A", "12 A", "12-A" en "12a" allemaal als hetzelfde adres herkennen.
/*** Fuzzy matcher voor huisnummer toevoegingen*/function normalizeForMatching(address) {return {...address,// Normaliseer letter naar hoofdletterletter: address.letter?.toUpperCase(),// Normaliseer toevoegingaddition: normalizeAdditionForMatch(address.addition)};}function normalizeAdditionForMatch(addition) {if (!addition) return null;// Verwijder alle spaties en koppeltekenslet normalized = addition.replace(/[\s-]/g, '').toLowerCase();// Map varianten naar standaardconst variants = {// Huis varianten'huis': 'hs', 'h': 'hs',// Souterrain varianten'souterrain': 'sous', 'sout': 'sous', 's': 'sous',// Romeinse cijfer varianten'1': 'i', '2': 'ii', '3': 'iii', '4': 'iv', '5': 'v','eerste': 'i', 'tweede': 'ii', 'derde': 'iii','1e': 'i', '2e': 'ii', '3e': 'iii',// Bis varianten'b': 'bis',};return variants[normalized] || normalized;}function addressesMatch(addr1, addr2) {const n1 = normalizeForMatching(addr1);const n2 = normalizeForMatching(addr2);return n1.street.toLowerCase() === n2.street.toLowerCase() &&n1.number === n2.number &&n1.letter === n2.letter &&n1.addition === n2.addition;}// Testconst input = { street: 'Herengracht', number: 123, letter: 'a', addition: 'huis' };const bag = { street: 'Herengracht', number: 123, letter: 'A', addition: 'hs' };console.log('Match:', addressesMatch(input, bag)); // true
GeoRex API: automatische normalisatie
De GeoRex API lost al deze complexiteit automatisch voor je op. Je kunt een adres invoeren in vrijwel elke notatie, en de API normaliseert het naar de officiële BAG-standaard.
# Alle varianten geven hetzelfde resultaat:curl "https://api.georex.nl/geocode?q=Herengracht+123A+hs+Amsterdam&token=YOUR_TOKEN"curl "https://api.georex.nl/geocode?q=Herengracht+123+A+huis+Amsterdam&token=YOUR_TOKEN"curl "https://api.georex.nl/geocode?q=Herengracht+123-a-hs+Amsterdam&token=YOUR_TOKEN"# Response bevat genormaliseerde BAG-data:# {# "features": [{# "properties": {# "street": "Herengracht",# "housenumber": "123",# "houseletter": "A",# "addition": "hs",# "postcode": "1015BK",# "city": "Amsterdam"# }# }]# }
Laat GeoRex het werk doen
In plaats van zelf complexe parsing logica te schrijven, kun je de GeoRex API gebruiken als normalisatie service. Stuur het adres zoals de gebruiker het invoert, en krijg gestructureerde, genormaliseerde BAG-data terug.
Veelvoorkomende valkuilen
Bij het werken met Nederlandse huisnummer toevoegingen zijn er enkele veelvoorkomende valkuilen:
1. Case sensitivity
Huisletters zijn in de BAG altijd hoofdletters, maar gebruikers typen vaak kleine letters. Vergeet niet te normaliseren voor matching.
2. Scheidingstekens
Spaties, koppeltekens en schuine strepen worden allemaal als scheiding gebruikt. "12-A", "12 A", "12/A" en "12A" kunnen allemaal hetzelfde adres betekenen.
3. Volgorde van toevoegingen
Sommige adressen hebben zowel een letter als een toevoeging (bijv. "123B-hs"). De volgorde is altijd: nummer + letter + toevoeging.
4. Verwarring met postcodes
Let op dat je huisletters (A, B, C) niet verwart met het letter-gedeelte van de postcode (1012 AB). Valideer altijd dat postcodes 4 cijfers + 2 letters zijn.
Best practices
- Accepteer meerdere formaten - Sta gebruikers toe om adressen te typen zoals zij gewend zijn
- Normaliseer vroeg - Converteer naar een standaardformaat direct bij invoer
- Gebruik de BAG als referentie - De officiële registratie is altijd leidend
- Test met edge cases - Gebruik de moeilijkste Amsterdamse adressen als test
- Bouw feedback loops - Laat gebruikers kiezen uit suggesties bij ambigue invoer
- Log mismatches - Monitor welke adressen niet gevonden worden om je parser te verbeteren
Veelgestelde vragen
Zijn alle toevoegingen officieel geregistreerd?
Ja, sinds de invoering van de BAG in 2009 zijn alle Nederlandse adressen officieel geregistreerd, inclusief alle toevoegingen. Historische aanduidingen zoals kleuren zijn grotendeels vervangen door standaard toevoegingen.
Hoeveel karakters kan een toevoeging maximaal zijn?
In de BAG is het huisnummertoevoeging veld maximaal 4 karakters. De huisletter is altijd exact 1 karakter. De langste toegestane combinatie is dus bijvoorbeeld "12A-bis" (nummer 12, letter A, toevoeging "bis").
Wat als een adres niet gevonden wordt?
Als een adres niet gevonden wordt, probeer dan: (1) alleen het huisnummer zonder toevoegingen te zoeken, (2) de postcode te gebruiken voor validatie, (3) fuzzy matching toe te passen op de straatnaam. De GeoRex API doet dit automatisch en geeft suggesties bij partiële matches.
Samenvatting
Nederlandse huisnummer toevoegingen zijn een uniek en complex fenomeen dat voorkomt uit eeuwen van stedelijke ontwikkeling. Van Romeinse cijfers in grachtenpanden tot kleur-gebaseerde aanduidingen in historische binnensteden - de variatie is enorm.
Voor ontwikkelaars betekent dit dat robuuste adres parsing essentieel is. Door de BAG-structuur te begrijpen (huisletter vs huisnummertoevoeging), alle varianten te ondersteunen, en slim te normaliseren, kun je ook de lastigste Nederlandse adressen correct verwerken.
Volgende stap
Wil je direct aan de slag? De GeoRex API handelt alle complexiteit rondom huisnummer toevoegingen automatisch af. Probeer het gratis uit met 1.000 requests per maand en ervaar hoe eenvoudig Nederlandse adresverwerking kan zijn.
Gerelateerde artikelen

Van adres naar coördinaten: een complete handleiding
Een uitgebreide stap-voor-stap handleiding voor het converteren van Nederlandse adressen naar GPS-coördinaten, inclusief edge cases en validatie.
Lees meer
BAG data uitgelegd: de complete gids over de officiële Nederlandse adres database
Alles wat je moet weten over de Basisregistratie Adressen en Gebouwen (BAG): de structuur, objecttypen, actualiteit, en waarom het de beste bron is voor Nederlandse locatiedata.
Lees meer
Postcodes in Nederland: de complete gids over het PC4 en PC6 systeem
Alles wat je moet weten over het Nederlandse postcodesysteem: de structuur van PC4 en PC6, hoe postcodes zijn opgebouwd, en praktische tips voor geocoding en data-analyse.
Lees meer