Skip to content

Address autocomplete API

Danish address suggestions, as the user types

An address field that suggests real Danish addresses from the second keystroke. It forgives typos and half-typed street names, and every suggestion carries a stable address ID — so the choice can go straight on to the property behind it.

Læs denne side på dansk

Try it

Misspell a street name

The box opens on “Vestrebrogade 10” — a typo — and still finds Vesterbrogade in five towns. Type any Danish address to search the live register.

Real results · type any Danish address

  • Vesterbrogade 10, 8800 Viborg

    0a3f5098-fed5-32b8-e044-0003ba298018

    BFE 5588347
  • Vesterbrogade 10, 4930 Maribo

    0a3f5085-7d1d-32b8-e044-0003ba298018

    BFE 5414863
  • Vesterbrogade 10, 6000 Kolding

    0a3f5090-66bb-32b8-e044-0003ba298018

    BFE 8069127
  • Vesterbrogade 10, 7200 Grindsted

    0a3f508e-0a9a-32b8-e044-0003ba298018

    BFE 5138843
  • Vesterbrogade 10, 8000 Aarhus C

    0a3f5097-2080-32b8-e044-0003ba298018

    BFE 5623355
GET /v1/adresse/search — here through its keyless demo, capped at six hits.

Prefix matches rank first, then matches by similarity. Danish letters can be typed the way a non-Danish keyboard allows: ae, oe and aa find æ, ø and å.

The demo calls the keyless /v1/demo/adresse-search, the same search service as the keyed endpoint. Each hit shows its BFE number — the national ID of the property the address sits on, and the key to its buildings, parcels and valuation.

The answer

Text to show, a value to store

Each suggestion has tekst for the list and vaerdi as the key — the address UUID, a street name or a postcode, depending on type. The field names are the register’s own Danish terms.

GET /v1/autocomplete?q=rådhuspladsen+1550json
{
  "type": "adgangsadresse",
  "antal": 3,
  "resultater": [
    {
      "type": "adgangsadresse",
      "tekst": "Rådhuspladsen 1, 1550 København V",
      "vaerdi": "0a3f507a-ec01-32b8-e044-0003ba298018"
    },
    {
      "type": "adgangsadresse",
      "tekst": "Rådhuspladsen 2, 1550 København V",
      "vaerdi": "39ece5fb-ee06-0ee2-e044-0003ba298018"
    },
    {
      "type": "adgangsadresse",
      "tekst": "Rådhuspladsen 3, 1550 København V",
      "vaerdi": "0a3f507a-ec03-32b8-e044-0003ba298018"
    }
  ]
}
Response fields
FieldContents
antalNumber of suggestions, at most 20.
resultater[].tekstThe line to show, e.g. “Rådhuspladsen 1, 1550 København V”.
resultater[].vaerdiThe key to store: the UUID of the unit or access address, the street name or the postcode.
Parameters
ParameterDescription
qThe text typed so far, at least 2 characters. Typos still match, and ae / oe / aa are read as æ / ø / å.
typeadgangsadresse (default), adresse, vejnavn or postnummer. “adresse” walks from street to house number to floor and door; every hit carries its own type.
adgangsadresseidOnly with type=adresse: a chosen access address — the answer is its units, with floor and door.
kommunekodeLimits street names to one municipality, e.g. 0101.

Build the field

Debounce, abort, show the text, store the value

A good address field is four rules: wait for a pause in typing, abort the previous request, show tekst in the list, and store vaerdi — never the text.

address-field.jsjavascript
// An address field with suggestions — one call per pause in typing, not per letter.
// /api/addresses is your own backend, which calls /v1/autocomplete with the key.
const input = document.querySelector('#address');
const list = document.querySelector('#suggestions');
let timer, ctrl;

input.addEventListener('input', () => {
  clearTimeout(timer);
  const q = input.value.trim();
  if (q.length < 2) return list.replaceChildren();
  timer = setTimeout(async () => {
    ctrl?.abort(); // the newest keystroke always wins
    ctrl = new AbortController();
    const res = await fetch('/api/addresses?q=' + encodeURIComponent(q), {
      signal: ctrl.signal,
    });
    const { resultater } = await res.json();
    list.replaceChildren(
      ...resultater.map((hit) => {
        const li = document.createElement('li');
        li.textContent = hit.tekst; // what the user sees
        li.dataset.uuid = hit.vaerdi; // what you store
        return li;
      }),
    );
  }, 150);
});

Call the API from your own backend so the secret key never reaches the browser — or create a publishable gf_pub_live_ key locked to your domains. With a 150 ms debounce a field typically sends three or four calls per address.

Coming from DAWA’s /autocomplete? The request is the same, but the answer is wrapped in { type, antal, resultater }. The DAWA replacement guide maps every endpoint.

Call it

One endpoint for addresses, streets and postcodes

Same key and the same response shape as the rest of the API. The TypeScript SDK aborts a stale request for you when you pass it a signal.

import { GrundfastClient } from '@grundfast/sdk';

const gf = new GrundfastClient({ apiKey: 'gf_live_…' });

let inFlight: AbortController | undefined;

export async function suggest(q: string) {
  inFlight?.abort(); // a newer keystroke overtakes the previous answer
  inFlight = new AbortController();
  const { resultater } = await gf.autocomplete(q, 'adgangsadresse', undefined, {
    signal: inFlight.signal,
  });
  return resultater; // [{ type, tekst, vaerdi }] — show tekst, store vaerdi
}

npm i @grundfast/sdk

FAQ

Questions about address autocomplete

Danish addresses come in two levels. An adgangsadresse (access address) is a street, house number and postcode — the door you walk up to. An adresse adds floor and door for a single flat or office inside it. Autocomplete suggests access addresses by default; with type=adresse it continues down to the unit.

Suggestions come from Grundfast’s own index of the whole Danish address register (DAR), not from a call upstream per keystroke, so the latency is our database plus the network between you and it. The demo on this page shows the measured round trip from your own browser.

On every pause instead. Wait 100–200 ms after the last keystroke and abort the previous request when a new one starts. An address then costs three or four calls instead of twenty, and a slow answer can never overwrite a newer one.

Yes, with a publishable key (gf_pub_live_…). It only opens the address endpoints a form needs, only answers requests from the domains you list in the dashboard, and has a per-visitor rate limit. A secret gf_live_ key belongs on your server.

/v1/autocomplete returns a light list of tekst and vaerdi and can also suggest street names and postcodes. /v1/adresse/search returns the full address for each hit — street, number, postcode, municipality code, coordinate and BFE number — and is what you use when the choice has to continue to the property.

Every request counts as one call, including the ones a field sends while someone types — which is why debouncing pays. The Free plan includes 5,000 calls a month and Starter 100,000. A gf_test_ key gives free test calls for development that are never billed.

See also

Put suggestions on your address field today

Create a free key and make your first call in a minute. Build against a gf_test_ key that is never billed, and upgrade when the traffic is real.

Free up to 5,000 calls a month · no card · test keys never billed · data from Klimadatastyrelsen / Datafordeler, CC BY 4.0