Paginering med side og per_side

Hent lange lister side for side med side og per_side, kend grænserne pr. endpoint, og skriv en løkke, der stopper ved den sidste side.

4 min Niveau: Begynder ✓ Kode testet

Lister som /adresser, /vejnavne og /postnumre returnerer resultatet i sider. Du vælger siden med side og størrelsen med per_side, præcis som i DAWA. Hver side er et API-kald, så færre og større sider er billigere end mange små.

Parametrene

  • side er sidenummeret. Den første side er 1. side=0 giver en valideringsfejl.
  • per_side er antal rækker pr. side. Standarden er 100 på de fleste lister. Se tabellen for, hvad du får uden de to parametre.
Shell#page-curl
curl -s "https://api.danadresse.dk/adresser?postnr=8000&side=2&per_side=2" \
  -H "X-Api-Key: $DANADRESSE_API_KEY"

Svaret er en almindelig JSON-liste. Der er ingen header eller felt med det samlede antal, og ingen "næste side"-link. Du ved, at du er på den sidste side, når den har færre rækker end per_side.

Grænser pr. endpoint

EndpointUden side og per_sideper_side maks.side
/adresser, /adgangsadresserde første 1001000ja
/postnumre, /sogne, /supplerendebynavne, /supplerendebynavne2hele listen1000ja
/vejnavne, /vejstykkerhele listen med kommunekode eller postnr, ellers de første 1001000ja
/navngivneveje, /ejerlav, /jordstykker, /matrikelnumre, /steder, /stednavnede første 1001000ja
/kommunerhele listen500ja
/autocomplete20 forslag100nej
/adresser/autocomplete, /adgangsadresser/autocomplete, /postnumre/autocomplete, /vejnavne/autocomplete, /vejstykker/autocomplete, /ejerlav/autocomplete20 forslag1000nej
/kommuner/autocomplete20 forslag500nej
/regioner, /retskredse, /politikredse, /opstillingskredse, /landsdele, /storkredse, /valglandsdelehele listenhele listennej

Som i DAWA kommer de små lister hele tilbage, når du ikke sender side eller per_side. /postnumre giver alle postnumre i ét kald, klar til en dropdown. Sender du side eller per_side, er standarden 100 rækker pr. side. På referencelisterne i den sidste række bliver side og per_side ignoreret.

Sætter du per_side højere end grænsen, får du status 400:

JSON#per-side-too-big
{
  "type": "QueryParameterFormatError",
  "title": "Invalid query parameter",
  "details": [
    {
      "type": "less_than_equal",
      "loc": ["query", "per_side"],
      "msg": "Input should be less than or equal to 1000",
      "input": "5000",
      "ctx": {"le": 1000}
    }
  ],
  "code": "invalid_query_parameter"
}

Løkken: hent indtil en kort side

Opskriften er den samme i alle sprog: start på side 1, hent, og stop når siden har færre rækker end per_side. Går antallet op i per_side, er den sidste side tom, og det koster ét ekstra kald.

En generator i Python, der giver dig rækkerne en ad gangen:

Python#paginate-python
import os
from collections.abc import Iterator

import requests

API = "https://api.danadresse.dk"
session = requests.Session()
session.headers["X-Api-Key"] = os.environ["DANADRESSE_API_KEY"]


def pages(path: str, params: dict | None = None, per_side: int = 1000) -> Iterator[dict]:
    """Giv alle rækker fra en DAWA-liste, side for side."""
    side = 1
    while True:
        r = session.get(
            API + path,
            params={**(params or {}), "side": side, "per_side": per_side},
            timeout=30,
        )
        r.raise_for_status()
        rows = r.json()
        yield from rows
        if len(rows) < per_side:
            return
        side += 1


alle = list(pages("/postnumre"))
print(f"Hentede {len(alle)} postnumre. Første: {alle[0]['nr']} {alle[0]['navn']}")

En async iterator i JavaScript til Node 18+. Eksemplet henter alle kommuner i sider på 50:

JavaScript#paginate-js
const API = "https://api.danadresse.dk";

export async function* pages(path, params = {}, perSide = 1000) {
  for (let side = 1; ; side++) {
    const url = new URL(API + path);
    for (const [k, v] of Object.entries(params)) url.searchParams.set(k, v);
    url.searchParams.set("side", String(side));
    url.searchParams.set("per_side", String(perSide));

    const res = await fetch(url, {
      headers: { "X-Api-Key": process.env.DANADRESSE_API_KEY },
    });
    if (!res.ok) throw new Error(`HTTP ${res.status}: ${await res.text()}`);
    const rows = await res.json();
    yield* rows;
    if (rows.length < perSide) return;
  }
}

let antal = 0;
for await (const kommune of pages("/kommuner", {}, 50)) antal++;
console.log(`Hentede ${antal} kommuner`);

Vil du afbryde tidligt, så stop løkken. Generatoren henter kun den næste side, når du beder om flere rækker.

Ting, der er værd at vide

  • Rækkefølge. Lister uden q har en fast rækkefølge: /adresser og /adgangsadresser efter id, de andre lister efter kode eller navn. På /adresser og /adgangsadresser overlapper siderne derfor ikke og springer ingen rækker over. Adressedata bliver opdateret løbende, så til et komplet udtræk bruger du replikering.
  • Fritekst q. Med q er siderne sorteret efter relevans. Dybe sider giver sjældent mening. Gør søgningen mere præcis i stedet.
  • Cirkel og polygon. Med cirkel= eller polygon= bliver kandidaterne fundet først og derefter delt i sider, de nærmeste først i en cirkel. Dækker området mere end 50.000 adgangsadresser, får du 400 med koden area_too_large i stedet for et afskåret svar. Gør området mindre, eller tilføj postnr eller kommunekode.
  • Hver side er et kald. 2.500 adresser med per_side=100 er 25 kald. Med per_side=1000 er det 3. Se Grænser, kvoter og 429.

Når du skal bruge alt: replikering

Paginering er beregnet til lister, som en bruger eller et job har brug for nu: adresserne i et postnummer, vejene i en kommune. Skal du bruge alle Danmarks adresser, så hent dem med /replikering/udtraek?entitet=adresse. Det er én lang JSON-liste i ét kald (eller NDJSON, én række pr. linje, med &ndjson), og bagefter kan du holde dine data opdateret med hændelser. Se Replikering: det første udtræk.

format=ndjson på /adresser giver også NDJSON, men det følger stadig side og per_side. Det er praktisk til at skrive en side direkte til en fil, men det henter ikke hele datasættet.

Næste skridt

Relaterede guides

Markdown-kilde Fejl i guiden? Skriv til os API-reference (Swagger)

Prøv det med en gratis nøgle

2 000 kald/måned på gratisplanen. Intet kreditkort.

Opret konto →