Loading...
Sign in to see the examples with your own API key.

JavaScript Client

A TypeScript client for every endpoint: autocomplete, adresser, adgangsadresser, reverse geocoding, vejnavne, postnumre and usage. No dependencies; Node 18+ and every modern browser; types included. The current version is 1.0.0.

Install

npm install getaddress-dk-api

On your server, with your API key:

import Client from 'getaddress-dk-api';

const api = new Client('{your-api-key}');

const autocompleteResult = await api.adresserAutocomplete('Amagerbrogade 217A');

if (autocompleteResult.isSuccess) {
    for (const suggestion of autocompleteResult.toSuccess()) {
        const getResult = await api.adresse(suggestion.adresse, { struktur: 'mini' });

        if (getResult.isSuccess) {
            const adresse = getResult.toSuccess();
            console.log(adresse.vejnavn, adresse.husnr, adresse.etage, adresse['dør'], adresse.postnr, adresse.postnrnavn);
        }
    }
} else {
    const failed = autocompleteResult.toFailed();
    console.log(failed.status, failed.message);
}

CommonJS works too: const { Client } = require('getaddress-dk-api');. Records keep DAWA's Danish field names, so read dør as adresse['dør']. Ids are DAR's UUIDs, the same ids DAWA gave, so ids you have stored still work.

In the browser

The API refuses an API key sent from a web page. In the browser, pass a domain token where the key would go; the client sends it in the path (https://api.getaddress.dk/t/{your-domain-token}/autocomplete?q=…).

import Client from 'getaddress-dk-api';

const api = new Client('{your-domain-token}');

input.addEventListener('input', async () => {
    const result = await api.autocomplete(input.value, { caretpos: input.selectionStart });
    if (!result.isSuccess) return;

    for (const suggestion of result.toSuccess()) {
        // suggestion.type is 'vejnavn', 'adgangsadresse' or 'adresse'
        show(suggestion.forslagstekst, suggestion.tekst, suggestion.caretpos);
    }
});

For a ready-made list under an input, use the autocomplete widget instead.

Autocomplete

autocomplete is DAWA's combined /autocomplete: street names first, then access addresses, then addresses, moving on as the text narrows. Branch on type. Street names are free; an answer that suggests addresses costs one look-up.

const result = await api.autocomplete('Amagerbrogade 217A', { type: 'adresse', postnr: 2300, fuzzy: true });

for (const s of result.toSuccess()) {
    if (s.type === 'adresse') console.log(s.data.id, s.data.etage, s.data['dør']);
    if (s.type === 'vejnavn') console.log(s.data.navn);
}

One kind of thing only:

await api.adresserAutocomplete('Amagerbrogade 217A, kl.', { postnr: 2300 });   // [{ tekst, adresse }]   1 look-up if not empty
await api.adgangsadresserAutocomplete('Amagerbrogade 217A');                    // [{ tekst, adgangsadresse }]
await api.vejnavneAutocomplete('Amag');                                          // [{ tekst, vejnavn }]   free
await api.postnumreAutocomplete('23');                                           // [{ tekst, postnummer }] free

Adresser and adgangsadresser

One record by id is one look-up; an id that is not found costs nothing. struktur picks the record type (nestet by default, flad or mini) and format: 'geojson' returns a GeoJSON Feature. See Adresser and Adgangsadresser.

const nestet = await api.adresse('3bba05d4-c8c4-4c90-8a64-a4dff11b9d1b');
const mini = await api.adresse('3bba05d4-c8c4-4c90-8a64-a4dff11b9d1b', { struktur: 'mini' });
const flad = await api.adresse('3bba05d4-c8c4-4c90-8a64-a4dff11b9d1b', { struktur: 'flad', srid: 25832 });
const feature = await api.adresse('3bba05d4-c8c4-4c90-8a64-a4dff11b9d1b', { format: 'geojson' });

const adgang = await api.adgangsadresse('099f3e28-4fb8-4c61-86a1-edff5df52409', { struktur: 'mini' });

Search a page at a time — one look-up per record returned, per_side at most 100. Several values of one parameter go as an array (sent DAWA's way, joined with |).

const page = await api.adresser({ postnr: 2300, vejnavn: 'Amagerbrogade', husnr: '217A', struktur: 'mini' });
const text = await api.adresser({ q: 'Amagerbrogade 217A, kl. 5, 2300 København S' });
const adgange = await api.adgangsadresser({ vejnavn: 'Amagerbrogade', postnr: [2300, 2100] });

Reverse geocoding

The access address nearest a point. One look-up; nothing within reach is a 404 that costs nothing.

const nearest = await api.reverse(12.6137425, 55.6490036);                                 // longitude, latitude
const utm = await api.reverse(556488.89, 6323087.65, { srid: 25832, struktur: 'mini' });   // easting, northing

Vejnavne and postnumre

Street names and postcodes. Free, and rate limited.

const streets = await api.vejnavne({ postnr: 2300 });
const street = await api.vejnavn('Amagerbrogade');

const postnumre = await api.postnumre({ kommunekode: '0101' });
const postnummer = await api.postnummer(2300);

Usage

Pass your admin key as the second argument. See Usage.

const api = new Client('{your-api-key}', '{your-admin-key}');

const today = await api.usage();
const oneDay = await api.usage(1, 9, 2026);
const range = await api.usageRange(new Date('2026-09-01'), new Date('2026-09-14'));

Failures

Errors the API reports, and network failures, are results, never thrown. status is the HTTP status (0 when no response arrived), message says what went wrong, a 429 carries retryAfterSeconds, and code is what to branch on:

const result = await api.adresse(id);

if (!result.isSuccess) {
    const failed = result.toFailed();

    if (failed.isNotFound) { /* no such address — costs nothing */ }
    else if (failed.isInvalid) console.log(failed.dawaError.details);
    else if (failed.isRateLimited) await wait(failed.retryAfterSeconds ?? 60);
    else if (failed.isUnauthorized) { /* key missing or unknown, or an API key sent from a browser */ }
    else console.log(failed.code, failed.message);
}

Options

new Client('{your-api-key}', '{your-admin-key}', {
    baseUrl: 'https://api.getaddress.dk', // the API origin
    timeoutMs: 30000,                     // 0 for no timeout
    fetch: customFetch                    // defaults to the global fetch
});
Top