Byg en vejr-app med rigtige data fra DMI
Hent de nyeste målinger fra DMI’s vejrstationer med JavaScript, og vis temperaturen lige nu og en graf over det seneste døgn i din egen app.

DMI – Danmarks Meteorologiske Institut – har vejrstationer over hele landet, der måler temperatur, vind og regn hvert 10. minut. Målingerne er frie data: alle må bruge dem, og du behøver hverken at oprette dig eller få en nøgle. I dette projekt henter du dem direkte ind i din egen side med JavaScript.
Sådan gør du
- Lav en fil, der hedder vejr.html, i en teksteditor, fx VS Code. Kopiér koden nedenfor ind, og gem filen.
- Åbn filen i din browser. Efter et øjeblik ser du temperaturen lige nu og en søjle for hver time i det seneste døgn. Hold musen over en søjle for at se tallet.
- Skift station i menuen. Hvor er det varmest lige nu?
- Se de rå data: åbn de fem nyeste målinger fra Københavns Lufthavn direkte i browseren. Det er JSON – det samme, som din app får.
- Tryk F12 (på Mac: Cmd+Option+I) for at åbne udviklerværktøjerne, og kig under Network, mens siden henter data. Her kan du se forespørgslen til DMI og svaret.
Eksempel (HTML og JavaScript)
<!DOCTYPE html>
<html lang="da">
<head>
<meta charset="utf-8">
<title>Min vejr-app</title>
<style>
body { font-family: sans-serif; max-width: 600px; margin: 40px auto; padding: 0 16px; }
#nu { font-size: 3rem; margin: 16px 0 0; }
#graf { display: flex; align-items: flex-end; gap: 2px; height: 150px; margin-top: 24px; }
.soejle { flex: 1; background: #2F6BFF; border-radius: 3px 3px 0 0; }
small { color: #666; }
</style>
</head>
<body>
<h1>Vejret lige nu</h1>
<select id="station">
<option value="06180">København (Kastrup)</option>
<option value="06070">Aarhus Lufthavn</option>
<option value="06120">Odense (H.C. Andersen Airport)</option>
<option value="06030">Aalborg</option>
<option value="06080">Esbjerg Lufthavn</option>
<option value="06193">Bornholm (Hammer Odde Fyr)</option>
</select>
<p id="nu">Henter …</p>
<p id="tid"></p>
<div id="graf"></div>
<p><small>Temperaturen det seneste døgn – én søjle pr. time. Data: DMI (CC BY 4.0)</small></p>
<script>
const API = 'https://opendataapi.dmi.dk/v2/metObs/collections/observation/items';
// Hent alle temperaturmålinger fra det seneste døgn (DMI måler hvert 10. minut)
async function hentMaalinger(station) {
const url = `${API}?stationId=${station}¶meterId=temp_dry&period=latest-day&limit=300`;
const svar = await fetch(url);
if (!svar.ok) {
throw new Error('DMI svarede med fejlkode ' + svar.status);
}
const data = await svar.json();
const maalinger = data.features
.map(f => ({ tid: new Date(f.properties.observed), grader: f.properties.value }))
.filter(m => typeof m.grader === 'number')
.sort((a, b) => a.tid - b.tid); // ældste først
if (maalinger.length === 0) {
throw new Error('ingen målinger fra stationen lige nu');
}
return maalinger;
}
function komma(tal) {
return tal.toLocaleString('da-DK', { minimumFractionDigits: 1, maximumFractionDigits: 1 });
}
function tegnGraf(maalinger) {
const timer = maalinger.filter(m => m.tid.getMinutes() === 0); // kun hele timer
const graf = document.getElementById('graf');
graf.innerHTML = '';
const grader = timer.map(m => m.grader);
const bund = Math.min(...grader) - 1;
const top = Math.max(...grader);
for (const m of timer) {
const soejle = document.createElement('div');
soejle.className = 'soejle';
soejle.style.height = ((m.grader - bund) / (top - bund)) * 100 + '%';
soejle.title = `Kl. ${m.tid.getHours()}: ${komma(m.grader)} °C`;
graf.appendChild(soejle);
}
}
async function opdater() {
const station = document.getElementById('station').value;
const nu = document.getElementById('nu');
const tid = document.getElementById('tid');
nu.textContent = 'Henter …';
tid.textContent = '';
try {
const maalinger = await hentMaalinger(station);
const seneste = maalinger[maalinger.length - 1];
nu.textContent = komma(seneste.grader) + ' °C';
tid.textContent = 'Målt kl. ' + seneste.tid.toLocaleTimeString('da-DK', { hour: '2-digit', minute: '2-digit' });
tegnGraf(maalinger);
} catch (fejl) {
nu.textContent = 'Kunne ikke hente vejret: ' + fejl.message;
}
}
document.getElementById('station').addEventListener('change', opdater);
opdater();
</script>
</body>
</html>Sådan virker koden
fetch(url)beder DMI’s server om data. Det tager lidt tid, så funktionen erasync, ogawaitventer på svaret uden at fryse siden.svar.json()laver svaret om til JavaScript-objekter. Hver måling ligger idata.featuresmed et tidspunkt (observed) og en værdi (value).map,filterogsortlaver listen om, rydder op og sorterer målingerne efter tid.- Grafen er bare
div-elementer, hvor højden er sat i procent. Bunden er den laveste temperatur minus én grad, og toppen er den højeste. tryogcatchfanger fejl – fx hvis du ikke har internet – og viser en besked i stedet for at gå i stå.
💡 DMI’s data må bruges frit under licensen CC BY 4.0. Den kræver, at man skriver, hvor data kommer fra – derfor står der “Data: DMI” nederst i appen. Læs mere om de frie data på dmi.dk/frie-data.
Er JavaScript nyt for dig, så start med JavaScript – gør din hjemmeside levende. Vil du hellere måle vejret selv? Byg en vejrstation med Raspberry Pi.
🧠 Udfordring – prøv selv
Tilføj vinden: hent også parameterId=wind_speed for samme station, og vis vindhastigheden i meter pr. sekund under temperaturen. Kan du også farve søjlerne blå, når det er under 0 grader, og orange, når det er over 20?