Find addresses in a radius or a polygon
Fetch every address inside a circle or a drawn area with cirkel and polygon, URL-encode the polygon correctly and page through large results.
A utility has to notify every household within 300 metres of a burst pipe. A municipality wants the addresses in a local-plan area. An estate agent wants to show every house in an area drawn on a map. These are spatial searches, and /adgangsadresser and /adresser have two filters for them: cirkel and polygon.
Use /adgangsadresser when you want one row per building entrance (one household per house, one point per staircase). Use /adresser when you need every flat.
Circle
The format is cirkel=longitude,latitude,radius_in_metres:
curl -s "https://api.danadresse.dk/adgangsadresser?cirkel=12.5683,55.6761,100&struktur=mini&per_side=5" \ -H "X-Api-Key: $DANADRESSE_API_KEY"
- Results are sorted by distance, nearest first. The distance itself is not in the response.
- The radius must be between 1 and 50,000 metres. Other values give
400with the codeinvalid_cirkel. - With
srid=25832you give the centre in UTM32 metres:cirkel=724400,6175700,100&srid=25832. The coordinates in the response are then in metres too. - You can combine it with
postnr,kommunekode,statusandmedtagnedlagte. Withoutstatusandmedtagnedlagteyou get current and provisional addresses.
Polygon
polygon takes the outer ring of a GeoJSON polygon as JSON: [[[lon,lat],[lon,lat],…]]. The ring needs at least three points, and it is good practice to close it by repeating the first point at the end.
The polygon contains [, ] and ,, so it has to be URL-encoded. Let your HTTP library do it:
import json import os import requests ring = [ [12.5665, 55.6750], [12.5700, 55.6750], [12.5700, 55.6770], [12.5665, 55.6770], [12.5665, 55.6750], ] polygon = json.dumps([ring], separators=(",", ":")) s = requests.Session() s.headers["X-Api-Key"] = os.environ["DANADRESSE_API_KEY"] alle, side, per_side = [], 1, 100 while side <= 5: r = s.get( "https://api.danadresse.dk/adgangsadresser", params={"polygon": polygon, "struktur": "mini", "per_side": per_side, "side": side}, timeout=30, ) r.raise_for_status() rows = r.json() alle.extend(rows) if len(rows) < per_side: break side += 1 print(f"{len(alle)} adgangsadresser i polygonet") for a in alle[:3]: print(" ", a["betegnelse"])
With curl, use -G --data-urlencode and curl handles the encoding:
curl -s -G "https://api.danadresse.dk/adgangsadresser" \ --data-urlencode 'polygon=[[[12.5665,55.6750],[12.5700,55.6750],[12.5700,55.6770],[12.5665,55.6750]]]' \ --data-urlencode "struktur=mini" \ --data-urlencode "per_side=3" \ -H "X-Api-Key: $DANADRESSE_API_KEY"
Rules for polygon:
- Only the outer ring is used. Holes in the polygon (inner rings) are ignored.
- Fewer than three points or invalid JSON gives
400with the codeinvalid_polygon. - With
srid=25832the points are in UTM32 metres. - Results are sorted by id, so pages never overlap. They are not sorted by distance.
- The polygon travels in the URL, and there is no POST variant. Simplify large polygons to a few hundred points so the URL stays under about 8 KB.
Page through the results
per_side is at most 1000 (default 100), and side starts at 1. There is no header with the total count, so keep going until you get a page with fewer rows than per_side.
On /adresser with cirkel or polygon, per_side counts addresses (flats), as on every other list. The addresses come building by building, with the nearest building first for cirkel.
const url = new URL("https://api.danadresse.dk/adresser"); url.searchParams.set("cirkel", "12.5757,55.7326,40"); url.searchParams.set("struktur", "mini"); url.searchParams.set("per_side", "20"); const alle = []; for (let side = 1; side <= 10; side++) { url.searchParams.set("side", String(side)); const res = await fetch(url, { headers: { "X-Api-Key": process.env.DANADRESSE_API_KEY } }); if (!res.ok) throw new Error(`HTTP ${res.status}`); const rows = await res.json(); alle.push(...rows); if (rows.length < 20) break; // last page } console.log(`${alle.length} adresser i alt`); console.log(alle.slice(0, 3).map((a) => a.betegnelse).join("\n"));
Straight onto a map
With format=geojson you get a FeatureCollection that Leaflet, MapLibre and QGIS read directly. crs names the coordinate system (EPSG:25832 with srid=25832), and properties has the same fields as the normal JSON response (shortened here):
{
"type": "FeatureCollection",
"crs": { "type": "name", "properties": { "name": "EPSG:4326" } },
"features": [
{
"type": "Feature",
"geometry": { "type": "Point", "coordinates": [12.56823601, 55.67611003] },
"properties": {
"id": "0a3f507a-ec03-32b8-e044-0003ba298018",
"kvh": "01016152___3",
"status": 1,
"betegnelse": "Rådhuspladsen 3, 1550 København V"
}
}
]
}See Formats: JSON, CSV, GeoJSON and NDJSON for the other formats.
Large areas
A circle or polygon may cover at most 50,000 access addresses (measured on its bounding rectangle). If the area is larger, the API answers 400 with the code area_too_large instead of returning an incomplete result. Split large areas into smaller pieces (for example one circle per postcode area or a grid of polygons), or add postnr or kommunekode, and remove duplicates on id afterwards. If you need every address in a municipality or a postcode, use the kommunekode or postnr filters instead.
Next steps
Related guides
Markdown source Spotted an error? Tell us API-reference (Swagger)