Coordinates and srid 4326/25832

Find the coordinates in the response, choose between WGS84 and ETRS89/UTM32 with srid, reverse geocode in both systems, and convert yourself with pyproj or proj4.

3 min Level: Intermediate ✓ Code tested

Every access address has an access point: the coordinate of the entrance to the building. The API can return it in two coordinate systems, and you choose with the srid parameter. It is the same parameter as in DAWA.

The two systems

sridSystemUnitOrderExample (Aarhus C)
4326 (default)WGS84, longitude and latitudedegreeslongitude, latitude[10.20285443, 56.14811374]
25832ETRS89 / UTM zone 32Nmetreseast, north[574730.16, 6223215.94]

WGS84 is what GPS, Google Maps, Leaflet and most web maps use. ETRS89/UTM32 is the official Danish system, used by municipalities, GIS tools and the Danish Agency for Climate Data's map data. The advantage of UTM is that the coordinates are metres: the distance between two points is plain Pythagoras.

srid only accepts 4326 and 25832. Any other value gives 400 with type QueryParameterFormatError and the text "srid skal være 4326 (WGS84) eller 25832 (ETRS89/UTM32)".

Where the coordinates are in the response

ResponseField
/adgangsadresser, /adgangsadresser/{id}, /adgangsadresser/reverse (nested)adgangspunkt.koordinater
/adresser, /adresser/{id}, /adresser/reverse (nested)adgangsadresse.adgangspunkt.koordinater
struktur=minix, y
struktur=fladwgs84koordinat_længde, wgs84koordinat_bredde, etrs89koordinat_øst, etrs89koordinat_nord (always both systems)
format=csvwgs84koordinat_længde, wgs84koordinat_bredde, etrs89koordinat_øst, etrs89koordinat_nord (always both systems)
format=geojsongeometry.coordinates (the system is stated in crs)
/autocompletedata.x, data.y

koordinater is a list of two numbers, and the order is always [x, y]: longitude before latitude, or east before north. An adresse (unit) has no coordinate of its own. A flat on the 3rd floor has its access address's point.

/autocomplete follows srid too: with srid=25832, data.x and data.y are UTM metres instead of degrees.

Fetch the same address in both systems:

Python#both-srids
import os
import requests

API = "https://api.danadresse.dk"
headers = {"X-Api-Key": os.environ["DANADRESSE_API_KEY"]}
adresse_id = "0a3f50ae-b4ee-32b8-e044-0003ba298018"

for srid, name in ((4326, "WGS84"), (25832, "ETRS89/UTM32")):
    r = requests.get(f"{API}/adresser/{adresse_id}", params={"srid": srid},
                     headers=headers, timeout=10)
    r.raise_for_status()
    x, y = r.json()["adgangsadresse"]["adgangspunkt"]["koordinater"]
    print(f"{name:13} x={x} y={y}")
Text#both-srids-output
WGS84         x=11.35623868 y=55.40464424
ETRS89/UTM32  x=649189.55 y=6142347.15

Axis order: the most common bug

The API gives [longitude, latitude], like GeoJSON. Many map libraries want it the other way round:

LibraryExpects
GeoJSON, OpenLayers, Mapbox GL, Turf[longitude, latitude]
Leaflet L.marker(), L.latLng()[latitude, longitude]
Google Maps{ lat: latitude, lng: longitude }
JavaScript#leaflet-marker
const [lon, lat] = adresse.adgangsadresse.adgangspunkt.koordinater;
L.marker([lat, lon]).addTo(map); // Leaflet: latitude first

If your markers land in the Arabian Sea instead of Denmark, the axes are swapped.

Reverse geocoding with srid

/adgangsadresser/reverse and /adresser/reverse find the nearest address to a point. x and y are read in the system given by srid, and the response comes back in the same system:

Shell#reverse-wgs84
curl -s "https://api.danadresse.dk/adgangsadresser/reverse?x=12.5683&y=55.6761" \
  -H "X-Api-Key: $DANADRESSE_API_KEY"

With UTM coordinates you must set srid=25832:

Shell#reverse-utm
curl -s "https://api.danadresse.dk/adgangsadresser/reverse?x=574730.16&y=6223215.94&srid=25832" \
  -H "X-Api-Key: $DANADRESSE_API_KEY"

If you forget srid=25832 for UTM coordinates, or swap x and y, there is no address nearby and you get 404 with "title": "No address within range". See No results?

The same applies to cirkel= and polygon= on /adresser and /adgangsadresser: the coordinates are read in the system given by srid. The radius in cirkel is always metres.

Convert yourself

If you have coordinates in one system and need the other, convert locally instead of making extra calls. In Python with pyproj (pip install pyproj):

Python#pyproj-convert
from pyproj import Transformer

# always_xy=True means (longitude, latitude) in and (east, north) out, as in the API.
to_utm = Transformer.from_crs("EPSG:4326", "EPSG:25832", always_xy=True)
to_wgs84 = Transformer.from_crs("EPSG:25832", "EPSG:4326", always_xy=True)

east, north = to_utm.transform(10.20285443, 56.14811374)
print(f"UTM32: {east:.2f} {north:.2f}")

lon, lat = to_wgs84.transform(east, north)
print(f"WGS84: {lon:.8f} {lat:.8f}")

Without always_xy=True pyproj follows the EPSG definition of 4326, which is latitude before longitude. That is a classic source of swapped axes.

In JavaScript with proj4 (npm install proj4):

JavaScript#proj4-convert
import proj4 from "proj4";

proj4.defs("EPSG:25832", "+proj=utm +zone=32 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs");

// proj4 always uses [longitude, latitude] / [east, north].
const [east, north] = proj4("EPSG:4326", "EPSG:25832", [10.20285443, 56.14811374]);
console.log(`UTM32: ${east.toFixed(2)} ${north.toFixed(2)}`);

const [lon, lat] = proj4("EPSG:25832", "EPSG:4326", [east, north]);
console.log(`WGS84: ${lon.toFixed(8)} ${lat.toFixed(8)}`);

Precision and height

  • WGS84 coordinates have 8 decimals (about a millimetre). UTM coordinates have 2 decimals (a centimetre). There is no need to round them before storing.
  • adgangspunkt.nøjagtighed tells you how well the point is determined: A is placed precisely on the base map, B is calculated, and U is uncertain.
  • adgangspunkt.højde is the terrain height in metres at the access point, when known.

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 →