Formats: JSON, CSV, GeoJSON, NDJSON and struktur

Get addresses as JSON, CSV, GeoJSON or NDJSON with format=, choose between nested, flat and mini with struktur=, and use JSONP or fetch in the browser.

4 min Level: Intermediate ✓ Code tested

The default response is JSON in DAWA's nested form. On the address lists you can ask for CSV, GeoJSON or NDJSON with format=, and for a flat or short JSON form with struktur=. The parameters work as in DAWA. Here is what each endpoint supports.

What each endpoint supports

Endpointformatstruktur
/adresserjson, csv, geojson, geojsonz, ndjsonnestet (default), flad, mini
/adgangsadresserjson, csv, geojson, geojsonz, ndjsonnestet (default), flad, mini
/adresser/{id}json, csvalways nested
/adgangsadresser/{id}JSON onlyalways nested
/adresser/reverse, /adgangsadresser/reverseJSON onlynestet (default), flad, mini
/autocompleteJSON onlyaccepted, but does not change the response
Every other endpointJSON onlyno

Two things to watch:

  • An unknown value in format or struktur on /adresser and /adgangsadresser gives 400 invalid_query_parameter.
  • On endpoints without format the parameter is ignored without an error. /postnumre?format=csv returns JSON.

struktur: nested, flat or mini

nestet is the default: the address with embedded objects for adgangsadresse, vejstykke, postnummer, kommune, sogn and so on. The coordinates are in adgangsadresse.adgangspunkt.koordinater.

flad puts everything on one level with DAWA's flat field names such as kommunekode, sognenavn and kvhx. Coordinates are given in both systems at once: wgs84koordinat_længde, wgs84koordinat_bredde, etrs89koordinat_øst and etrs89koordinat_nord.

mini is a small flat object for lists and dropdowns with DAWA's keys: id, status, darstatus, vejkode, vejnavn, adresseringsvejnavn, husnr, etage, dør, supplerendebynavn, postnr, postnrnavn, stormodtagerpostnr, stormodtagerpostnrnavn, kommunekode, x, y, href, betegnelse and adgangsadresseid.

Python#struktur-mini
import os
import requests

r = requests.get(
    "https://api.danadresse.dk/adresser",
    params={"postnr": "4200", "vejnavn": "Rådhuspladsen", "husnr": "1",
            "struktur": "mini", "per_side": 1},
    headers={"X-Api-Key": os.environ["DANADRESSE_API_KEY"]},
    timeout=10,
)
r.raise_for_status()
adresse = r.json()[0]
print(sorted(adresse))
print(adresse["betegnelse"], adresse["x"], adresse["y"])

For storing in a database flad is often easiest, because each key becomes a column. For showing a suggestion, mini is enough.

CSV

format=csv gives a comma-separated file with a header line. The columns are fixed and independent of struktur:

Shell#csv-curl
curl -s "https://api.danadresse.dk/adresser?postnr=4200&vejnavn=R%C3%A5dhuspladsen&husnr=1&per_side=3&format=csv" \
  -H "X-Api-Key: $DANADRESSE_API_KEY"
Text#csv-output
id,status,vejnavn,husnr,etage,dør,supplerendebynavn,postnr,postnrnavn,kommunekode,kommunenavn,vejkode,etrs89koordinat_øst,etrs89koordinat_nord,wgs84koordinat_bredde,wgs84koordinat_længde,betegnelse
0a3f50ae-b4ee-32b8-e044-0003ba298018,1,Rådhuspladsen,1,st,th,,4200,Slagelse,0330,Slagelse,1407,649189.55,6142347.15,55.40464424,11.35623868,"Rådhuspladsen 1, st. th, 4200 Slagelse"

/adgangsadresser has the same columns without etage and dør and with adresseringsvejnavn. That is fewer columns than DAWA's CSV, which also had, for example, cadastre data. If you need more fields, fetch JSON with struktur=flad and write your own CSV.

  • The file is UTF-8 without a BOM. If you double-click it in Excel on Windows, æøå come out wrong. See Æ, ø and å.
  • The file always has both coordinate systems: etrs89koordinat_øst and etrs89koordinat_nord in metres and wgs84koordinat_bredde and wgs84koordinat_længde in degrees. That holds whatever srid you send.
  • CSV follows side and per_side like everything else. See Pagination.

GeoJSON

format=geojson gives a FeatureCollection you can drop straight into Leaflet, Mapbox, QGIS or geojson.io. Each address is a Feature with a Point and the flat fields as properties:

Python#geojson-python
import os
import requests

r = requests.get(
    "https://api.danadresse.dk/adgangsadresser",
    params={"postnr": "8000", "per_side": 5, "format": "geojson"},
    headers={"X-Api-Key": os.environ["DANADRESSE_API_KEY"]},
    timeout=10,
)
r.raise_for_status()
fc = r.json()
print(fc["type"], "with", len(fc["features"]), "points")
first = fc["features"][0]
print(first["geometry"]["coordinates"], first["properties"]["adressebetegnelse"])
JSON#geojson-output
{
  "type": "FeatureCollection",
  "crs": {"type": "name", "properties": {"name": "EPSG:4326"}},
  "features": [
    {
      "type": "Feature",
      "geometry": {"type": "Point", "coordinates": [10.20285443, 56.14811374]},
      "properties": {
        "id": "…",
        "kvh": "…",
        "husnr": "90A",
        "x": 10.20285443,
        "y": 56.14811374,
        "adressebetegnelse": "Jægergårdsgade 90A, 8000 Aarhus C"
      }
    }
  ]
}

The response is shortened. The crs member states the coordinate system: EPSG:4326 (the default, longitude first) or EPSG:25832 when you send srid=25832. The GeoJSON standard (RFC 7946) uses WGS84 and many tools ignore crs, so use srid=4326 unless your tool reads UTM.

format=geojsonz gives the same with the height as a third coordinate when it is known.

NDJSON

format=ndjson gives one JSON address per line (application/x-ndjson). It is easy to write to a file or pass on to a tool that reads line by line. struktur works here too:

Shell#ndjson-curl
curl -s "https://api.danadresse.dk/adresser?postnr=8000&per_side=3&format=ndjson&struktur=mini" \
  -H "X-Api-Key: $DANADRESSE_API_KEY"

NDJSON on /adresser is still one page. You get the full data set as NDJSON from /replikering/udtraek. See Pagination.

JSONP: works, but prefer fetch

As in DAWA, callback=name wraps the response as name(…); with Content-Type: application/javascript. It works on the DAWA-compatible paths. A <script> tag cannot send headers, so with JSONP the key must be in the URL as api_key.

The API sends Access-Control-Allow-Origin: *, so you can also call it directly with fetch from any page. That is better, because you then see the status code and can read the error body. Old code with jQuery and JSONP:

JavaScript#jsonp-old
$.ajax({
  url: "https://dawa.aws.dk/autocomplete",
  dataType: "jsonp",
  data: { q: text },
  success: showSuggestions,
});

It works against api.danadresse.dk once you change the domain and add api_key to data. The same call with fetch. Use a browser key locked to your domain, see Browser keys and allowed domains:

JavaScript#jsonp-fetch
const API_KEY = "dawa_live_your_browser_key"; // locked to your domain

async function fetchSuggestions(text) {
  const url = new URL("https://api.danadresse.dk/autocomplete");
  url.searchParams.set("q", text);
  const res = await fetch(url, { headers: { "X-Api-Key": API_KEY } });
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
  return res.json();
}

fetchSuggestions("Rådhuspladsen 1").then(showSuggestions);

With jQuery it is enough to change dataType: "jsonp" to dataType: "json" and add the key in headers. If you get a CORS error, see CORS errors.

Next steps

Related guides

Markdown source Spotted an error? Tell us API-reference (Swagger)

Try it with a free key

2,000 calls/month on the free plan. No credit card.

Create account →