Referensi API

Setiap contoh di halaman ini dapat dijalankan langsung ke API.

Dasar

  • URL dasar: https://bmkg-api.dhanypedia.com/v1
  • Semua endpoint memakai GET dan dapat dipanggil tanpa API key.
  • CORS terbuka, sehingga API dapat dipanggil dari browser.
  • Data milik BMKG. Nilai attribution perlu ditampilkan saat data dipublikasikan.

Format response

Response berhasil selalu memuat data, meta, dan attribution.

200
{
  "data": { "magnitude": 5.4, "region": "18 km TimurLaut Pekalongan" },
  "meta": { "fetched_at": "2026-02-16T08:30:00Z", "cache_ttl": 60 },
  "attribution": "BMKG (Badan Meteorologi, Klimatologi, dan Geofisika)"
}

Response gagal memuat error, message, dan status.

404
{
  "error": "not_found",
  "message": "Weather data not available for ADM4 code '99.99.99.9999'.",
  "status": 404
}
StatusArti
200Berhasil
400Format argumen salah
404Tidak ada data untuk kode itu
422Parameter wajib tidak ada atau di luar rentang
429Rate limit terlampaui. Coba lagi setelah satu menit
503BMKG tidak terjangkau, atau server ini mencapai batas request-nya ke BMKG

Cache dan rate limit

BMKG memperbarui datanya pada selang tetap. Setiap response di-cache selama datanya masih berlaku, di server ini dan di CDN di depannya. Request yang lebih sering dari masa cache menerima jawaban yang sama.

  • Cache-Control menyatakan berapa lama response tetap fresh.
  • X-Cache bernilai HIT saat server ini menjawab dari cache.
  • Rate limit-nya 30 request per menit per endpoint untuk tiap client. X-RateLimit-Remaining menunjukkan sisa jatah.

Untuk kebutuhan yang lebih besar tersedia panduan menjalankan instance sendiri.

Gempa bumi

GET /v1/earthquake/latest cache 60 detik

Satu gempa terbaru: magnitudo, kedalaman, koordinat, wilayah, potensi tsunami, laporan dirasakan, dan URL shakemap. Waktu dalam UTC.

Buka di Explorer /v1/earthquake/latest
GET /v1/earthquake/recent cache 5 menit

15 gempa terakhir bermagnitudo 5,0 ke atas, dari yang terbaru.

Buka di Explorer /v1/earthquake/recent
GET /v1/earthquake/felt cache 5 menit

15 gempa terakhir yang dilaporkan dirasakan, termasuk gempa kecil, beserta tempat dan intensitasnya.

Buka di Explorer /v1/earthquake/felt
GET /v1/earthquake/nearby cache 5 menit

Gempa dari daftar terkini dan dirasakan dalam radius tertentu dari satu titik, dari yang terdekat, dengan distance_km. Daftar kosong berarti tidak ada di antara catatan terbaru BMKG, bukan tidak pernah ada.

latwajibLintang, -90 sampai 90
lonwajibBujur, -180 sampai 180
radius_kmopsionalRadius pencarian dalam km, default 100
Buka di Explorer /v1/earthquake/nearby?lat=-6.2&lon=106.8&radius_km=300

Cuaca

GET /v1/weather/{adm4_code} cache 15 menit

Prakiraan satu desa atau kelurahan untuk tiga hari, tiap 3 jam: suhu, kelembapan, cuaca dalam bahasa Indonesia dan Inggris, angin, dan tutupan awan. visibility_m dapat bernilai null.

adm4_codedi pathKode desa dengan pola 2.2.2.4 digit, misalnya 31.74.04.1006
Buka di Explorer /v1/weather/31.74.04.1006
GET /v1/weather/{adm4_code}/current cache 15 menit

Entri prakiraan yang paling dekat dengan waktu sekarang untuk satu desa. Ini prakiraan BMKG untuk slot 3 jam berjalan, bukan pengamatan stasiun.

adm4_codedi pathKode desa dengan pola 2.2.2.4 digit, misalnya 31.74.04.1006
Buka di Explorer /v1/weather/31.74.04.1006/current

Peringatan dini

GET /v1/nowcast cache 2 menit

Provinsi yang sedang punya peringatan dini cuaca, masing-masing dengan kode untuk endpoint rinciannya. Daftar kosong berarti tidak ada peringatan aktif.

langopsionalid (default) atau en
Buka di Explorer /v1/nowcast
GET /v1/nowcast/warnings cache 2 menit

Semua peringatan aktif secara lengkap dalam satu request, masing-masing dengan wilayah terdampak sebagai poligon. meta.missing memuat kode peringatan yang rinciannya tidak terbaca dari BMKG, supaya daftar yang pendek tidak dikira lengkap.

langopsionalid (default) atau en
Buka di Explorer /v1/nowcast/warnings
GET /v1/nowcast/{alert_code} cache 2 menit

Satu peringatan secara lengkap: kejadian, tingkat keparahan, masa berlaku, uraian, URL infografik, dan wilayah terdampak sebagai poligon. Hanya kode dari daftar aktif yang tersedia; kode lain menghasilkan 404.

alert_codedi pathKode dari /v1/nowcast
langopsionalid (default) atau en
Buka di Explorer /v1/nowcast/{alert_code}
GET /v1/nowcast/check cache 2 menit

Peringatan aktif yang teksnya menyebut nama tempat. has_warnings bernilai false berarti tidak ada peringatan aktif yang menyebutnya, bukan prakiraan cuaca baik.

locationwajibNama kecamatan, kota, atau kabupaten seperti ditulis BMKG
langopsionalid (default) atau en
Buka di Explorer /v1/nowcast/check?location=Jakarta

Wilayah

GET /v1/wilayah/provinces cache 24 jam

Semua provinsi dengan kode dua digit.

Buka di Explorer /v1/wilayah/provinces
GET /v1/wilayah/districts cache 24 jam

Kabupaten dan kota dalam satu provinsi.

provincewajibKode provinsi dua digit, misalnya 31
Buka di Explorer /v1/wilayah/districts?province=31
GET /v1/wilayah/subdistricts cache 24 jam

Kecamatan dalam satu kabupaten atau kota.

districtwajibKode kabupaten atau kota, misalnya 31.74
Buka di Explorer /v1/wilayah/subdistricts?district=31.74
GET /v1/wilayah/villages cache 24 jam

Desa dan kelurahan dalam satu kecamatan. Kodenya adalah kode adm4 yang dipakai endpoint cuaca.

subdistrictwajibKode kecamatan, misalnya 31.74.04
Buka di Explorer /v1/wilayah/villages?subdistrict=31.74.04

Mengolah poligon peringatan

Endpoint rincian peringatan mengembalikan tiap wilayah terdampak sebagai poligon. Ada dua hal yang sering keliru:

  • Titik ditulis sebagai [lintang, bujur]. Sebagian besar library peta meminta [bujur, lintang].
  • Daftar satu wilayah memuat beberapa ring yang disambung tanpa pemisah.

Peta di situs ini memisahkannya dengan cara berikut:

JavaScript
// One area's polygon is a flat list of [lat, lon] points holding several
// closed rings back to back. A ring ends when a point returns to the ring's
// start, or when the next point is more than 10 km away.
function splitRings(coords) {
  const rings = [];
  let start = coords[0];
  let ring = [coords[0]];

  for (let i = 1; i < coords.length; i++) {
    const point = coords[i];

    if (ring.length >= 4 && distanceKm(ring.at(-1), point) > 10) {
      rings.push([...ring, ring[0]]);
      start = point;
      ring = [point];
      continue;
    }

    ring.push(point);
    if (samePoint(point, start) && ring.length >= 4) {
      rings.push(ring);
      ring = [];
      if (i + 1 < coords.length) {
        start = coords[i + 1];
        ring = [start];
        i++;
      }
    }
  }

  if (ring.length >= 4) rings.push([...ring, ring[0]]);
  return rings;
}

// Real boundaries have short edges. A ring with an edge over 20 km joins
// two distant clusters and is dropped.
const drawable = splitRings(area.polygon).filter((ring) =>
  ring.every((point, i) => i === 0 || distanceKm(ring[i - 1], point) <= 20)
);