# Find the address from a GPS position

> Look up the nearest address from longitude and latitude with reverse geocoding, and handle GPS inaccuracy with a radius search.
>
> https://danadresse.dk/en/guides/reverse-geokodning-gps · verified 2026-11-02
A tradesperson app should fill in the address from the phone's position. An insurance claim only has a point on a map. A fleet tool should show which address a vehicle is parked at. All three are reverse geocoding: from coordinate to address.

The API has two endpoints for it, plus a radius search that gives you more control when the position is inaccurate.

## The simple call

`GET /adgangsadresser/reverse` returns the nearest active access address (the building entrance) to the point:

```bash id=reverse-curl run=live expect="adressebetegnelse"
curl -s "https://api.danadresse.dk/adgangsadresser/reverse?x=12.5757&y=55.7326" \
  -H "X-Api-Key: $DANADRESSE_API_KEY"
```

`x` is longitude and `y` is latitude. Swapping them is the most common mistake: Denmark lies at roughly 8-15° east and 54-58° north, so an `x` above 50 is almost always a swap.

The response has the same shape as `GET /adgangsadresser/{id}`, and `struktur=mini` or `struktur=flad` works here too. The most important fields:

| Field | Content |
|---|---|
| `id` | The access-address UUID |
| `adressebetegnelse` | E.g. `Strandvejen 100, 2900 Hellerup` |
| `vejstykke.navn`, `husnr`, `postnummer.nr`, `postnummer.navn` | The parts of the address |
| `kommune`, `sogn`, `politikreds` … | Administrative areas |
| `adgangspunkt.koordinater` | The address's own point, `[x, y]` |

If your coordinates are in UTM32 (metres), add `srid=25832`. Then both the input and the coordinates in the response are in metres:

```bash id=reverse-utm run=live expect="adressebetegnelse"
curl -s "https://api.danadresse.dk/adgangsadresser/reverse?x=724434.93&y=6175755.61&srid=25832" \
  -H "X-Api-Key: $DANADRESSE_API_KEY"
```

`GET /adresser/reverse` works the same way but returns a full address with floor and door. It picks one of the units in the building. In a block of flats the API cannot know which flat the user is in, so let the user choose floor and door afterwards. Fetch the list with `GET /adresser?adgangsadresseid={id}&struktur=mini`.

## What reverse does not tell you

- **No distance.** The response does not say how far the point is from the address. Calculate it yourself from `adgangspunkt.koordinater` (see [Distance between two addresses](/en/guides/afstand-mellem-adresser)).
- **No maximum distance.** The endpoint looks up to about 60 km away. If the user stands in the middle of a field, you still get an address, maybe a few kilometres away. Only when there is no address within that distance does the API answer `404` with the code `not_found`.
- **Active addresses only.** Current and provisional addresses are included. Retired addresses are not.
- **Always the nearest.** Reverse searches in growing areas until the nearest entrance is found, also in dense city areas. It returns the same address the radius search below puts first.

## GPS is not exact: use a radius

A phone reports its position with an uncertainty (`coords.accuracy` in the browser, in metres). Outdoors it is typically 5-20 metres, indoors and between tall buildings often 50 metres or more. With an uncertainty of 40 metres the user could just as well be at the house next door.

So use `cirkel=lon,lat,radius` on `/adgangsadresser` with the radius set from the uncertainty. Results come sorted with the nearest first. If there are several candidates, show them as a short list:

```js id=gps-node run=live expect="afstand"
const API = "https://api.danadresse.dk";
const headers = { "X-Api-Key": process.env.DANADRESSE_API_KEY };

function afstandMeter(lat1, lon1, lat2, lon2) {
  const R = 6371008.8, rad = Math.PI / 180;
  const dLat = (lat2 - lat1) * rad, dLon = (lon2 - lon1) * rad;
  const a = Math.sin(dLat / 2) ** 2 +
    Math.cos(lat1 * rad) * Math.cos(lat2 * rad) * Math.sin(dLon / 2) ** 2;
  return 2 * R * Math.asin(Math.sqrt(a));
}

async function adresserVed(lat, lon, noejagtighed) {
  const radius = Math.min(Math.max(Math.round(noejagtighed), 25), 250);
  const url = new URL(`${API}/adgangsadresser`);
  url.searchParams.set("cirkel", `${lon},${lat},${radius}`);
  url.searchParams.set("struktur", "mini");
  url.searchParams.set("per_side", "5");
  const res = await fetch(url, { headers });
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
  const kandidater = await res.json();
  if (kandidater.length > 0) return kandidater;
  // Nothing within the radius: fall back to the nearest address at all
  const rev = await fetch(`${API}/adgangsadresser/reverse?x=${lon}&y=${lat}`, { headers });
  if (rev.status === 404) return [];
  const a = await rev.json();
  const [x, y] = a.adgangspunkt.koordinater;
  return [{ id: a.id, betegnelse: a.adressebetegnelse, x, y }];
}

const lat = 55.67565, lon = 12.56935, noejagtighed = 30;
for (const a of await adresserVed(lat, lon, noejagtighed)) {
  console.log(`${a.betegnelse} (afstand ${Math.round(afstandMeter(lat, lon, a.y, a.x))} m)`);
}
```

The radius must be between 1 and 50,000 metres, otherwise the API answers `400` with the code `invalid_cirkel`. With `srid=25832` the centre is in metres.

## In the browser

`navigator.geolocation` gives position and uncertainty. Call the API with a browser key locked to your domain (see [Browser keys and allowed domains](/en/guides/browser-noegler-domaener)):

```js id=gps-browser run=no
const API_KEY = "dawa_live_your_browser_key"; // locked to your domain

navigator.geolocation.getCurrentPosition(async ({ coords }) => {
  const radius = Math.min(Math.max(Math.round(coords.accuracy), 25), 250);
  const url = `https://api.danadresse.dk/adgangsadresser?cirkel=${coords.longitude},${coords.latitude},${radius}&struktur=mini&per_side=5`;
  const res = await fetch(url, { headers: { "X-Api-Key": API_KEY } });
  const forslag = await res.json();
  visForslag(forslag.map((a) => ({ id: a.id, tekst: a.betegnelse })));
}, (fejl) => console.warn(fejl.message), { enableHighAccuracy: true, timeout: 10000 });
```

The browser asks the user for permission. If the user says no, or it takes too long, fall back to a normal address field with autocomplete.

## Edge cases

- **At sea or abroad.** If the point is far from any Danish address, reverse gives `404` and the circle gives an empty list.
- **Large plots.** The address point sits at the entrance or the road. On a farm or an industrial site the user can be several hundred metres from the point and still be at the right address.
- **Missing parameters.** Both `x` and `y` are required. If one is missing the API answers `400` with `invalid_query_parameter`.
- **Precision in the response.** Coordinates in the response have eight decimals, as in DAWA. To calculate distances in metres without converting, use `srid=25832`. Any `srid` other than 4326 and 25832 gives `400`.

## Next steps

- [Addresses in a radius or a polygon](/en/guides/adresser-i-radius-og-polygon)
- [Coordinates and srid 4326/25832](/en/guides/koordinater-srid)
- [Distance between two addresses](/en/guides/afstand-mellem-adresser)
