# 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.
>
> https://danadresse.dk/en/guides/formater-json-csv-geojson · verified 2026-11-02
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

| Endpoint | `format` | `struktur` |
|---|---|---|
| `/adresser` | `json`, `csv`, `geojson`, `geojsonz`, `ndjson` | `nestet` (default), `flad`, `mini` |
| `/adgangsadresser` | `json`, `csv`, `geojson`, `geojsonz`, `ndjson` | `nestet` (default), `flad`, `mini` |
| `/adresser/{id}` | `json`, `csv` | always nested |
| `/adgangsadresser/{id}` | JSON only | always nested |
| `/adresser/reverse`, `/adgangsadresser/reverse` | JSON only | `nestet` (default), `flad`, `mini` |
| `/autocomplete` | JSON only | accepted, but does not change the response |
| Every other endpoint | JSON only | no |

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 id=struktur-mini run=live expect="adgangsadresseid"
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`:

```bash id=csv-curl run=live expect="betegnelse"
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 id=csv-output run=no
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 å](/en/guides/aeoeaa-tegnsaet).
- 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](/en/guides/paginering).

## 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 id=geojson-python run=live expect="FeatureCollection"
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 id=geojson-output run=no
{
  "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:

```bash id=ndjson-curl run=live expect="betegnelse"
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](/en/guides/paginering).

## 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:

```js id=jsonp-old run=no
$.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](/en/guides/browser-noegler-domaener):

```js id=jsonp-fetch run=no
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](/en/guides/cors-fejl).

## Next steps

- [Coordinates and srid 4326/25832](/en/guides/koordinater-srid)
- [Æ, ø and å: character sets and URL encoding](/en/guides/aeoeaa-tegnsaet)
- [Pagination with side and per_side](/en/guides/paginering)
