Pengambilan data statistik resmi secara terprogram sudah menjadi kebutuhan standar bagi tim produk yang membangun dashboard ekonomi, laporan otomatis, maupun fitur analitik berbasis data pemerintah. Badan Pusat Statistik (BPS) menyediakan Web API publik di webapi.bps.go.id yang mengembalikan indikator dalam format JSON, sehingga pekerjaan yang sebelumnya dilakukan dengan scraping tabel HTML bisa digantikan oleh satu permintaan HTTP yang jauh lebih stabil.
TL;DR
- BPS menyediakan Web API publik di webapi.bps.go.id yang mengembalikan data statistik dalam format JSON, menggantikan scraping tabel HTML dengan satu permintaan HTTP yang lebih stabil.
- Tiga titik kegagalan yang paling umum adalah permintaan diblokir WAF karena header tidak lengkap, parameter tahun tidak memakai format empat digit, dan struktur datacontent berupa kunci komposit yang tidak bisa langsung dibaca sebagai tabel.
- Data kemiskinan nasional turun dari 9,03 persen pada Semester 1 2024 menjadi 8,25 persen pada Semester 2 2025, sementara kurs rata-rata transaksi BI terhadap USD naik dari Rp 15.416 (2023) ke Rp 16.162 (2024).
- Kode tahun BPS tidak selalu empat digit, misalnya kode internal 124 untuk 2024 dan 125 untuk 2025, sehingga menebak tanpa memeriksa katalog berujung pada respons kosong.
- Pipeline yang disarankan memeriksa kalender siaran pers pada frekuensi tinggi lalu menarik nilai indikator hanya saat ada rilis baru, dilengkapi snapshot bertanggal dan pencatatan kegagalan eksplisit.
Meski terdengar sederhana, ada tiga titik yang paling sering menggagalkan implementasi pertama. Pertama, permintaan diblokir oleh Web Application Firewall (WAF) karena header tidak lengkap. Kedua, parameter tahun (th) tidak memakai format empat digit seperti yang diasumsikan banyak pengembang. Ketiga, struktur respons datacontent berupa kamus dengan kunci komposit yang tidak bisa langsung dibaca sebagai tabel. Panduan ini membahas ketiganya secara berurutan, dilengkapi skrip Python yang bisa langsung dijalankan, contoh keluaran nyata dari penarikan pada 24 September 2026, serta cara menjadwalkannya sebagai pipeline cron di server produksi.
Menyiapkan Kunci Akses dan Memahami Peta Endpoint
Sebelum satu permintaan pun dikirim, aplikasi perlu memiliki App Key resmi. Kunci ini berfungsi sebagai identitas aplikasi sekaligus alat pengendali kuota, sehingga setiap pemanggilan endpoint wajib menyertakannya. Prosedur pendaftarannya relatif singkat:
- Buka portal resmi
https://webapi.bps.go.id/melalui peramban. - Daftarkan akun dengan alamat email yang aktif, lalu selesaikan verifikasi email.
- Masuk ke dashboard pengembang dan pilih menu registrasi aplikasi.
- Isi nama aplikasi, deskripsi tujuan penggunaan data, serta alamat domain atau IP server asal permintaan.
- Sistem menerbitkan App Key unik yang harus disertakan pada setiap pemanggilan.
Model pemanggilan data rinci memakai pola URL berikut:
https://webapi.bps.go.id/v1/api/view/model/data/domain/{kode_wilayah}/var/{kode_variabel}/key/{app_key}/
Nilai {kode_wilayah} mengikuti kode wilayah standar BPS. Untuk agregat nasional dipakai 0000, sedangkan level provinsi memakai kode masing-masing seperti 3100 untuk DKI Jakarta dan 3200 untuk Jawa Barat. Selain model view yang mengembalikan nilai data, tersedia pula model list yang berguna untuk menelusuri daftar variabel dan domain yang tersedia pada katalog. Praktik yang disarankan adalah memakai model list sekali di awal untuk memastikan kode variabel yang dituju memang benar, baru kemudian menarik nilainya secara berkala dengan model view.
Header Wajib agar Tidak Diblokir WAF
Penyebab kegagalan paling umum pada percobaan pertama bukanlah kesalahan logika, melainkan permintaan yang ditolak sebelum diproses. Server BPS dilindungi WAF yang menyaring trafik berdasarkan pola header. Pustaka HTTP yang mengirim permintaan tanpa identitas yang wajar akan menerima HTTP 403 Forbidden atau HTTP 429 Too Many Requests.
Spesifikasi header yang direkomendasikan:
| Header | Nilai yang Disarankan | Alasan |
|---|---|---|
User-Agent |
String peramban modern atau nama bot resmi aplikasi | WAF menolak klien tanpa identitas yang jelas |
Accept |
application/json |
Memprioritaskan payload JSON pada negosiasi konten |
Accept-Encoding |
gzip, deflate |
Menghemat bandwidth dan mempercepat transfer |
Connection |
keep-alive |
Menghindari handshake berulang pada penarikan bertahap |
Kesalahan yang sering terjadi adalah mengirim User-Agent bawaan pustaka, misalnya python-requests/2.x atau curl/8.x. Menggantinya dengan string peramban standar sudah cukup untuk melewati penyaringan dasar, dan menambahkan jeda satu sampai dua detik antar permintaan akan menghindari pembatasan laju.
Skrip Python: Fetch dengan Timeout dan Retry
Skrip berikut memakai modul standar Python sehingga tidak memerlukan paket pihak ketiga. Penanganan galat dibuat eksplisit agar kegagalan satu permintaan tidak menghentikan seluruh pipeline.
```python import json import time import urllib.error import urllib.parse import urllib.request
BASE = "https://webapi.bps.go.id/v1/api/view/model/data" HEADERS = { "User-Agent": ( "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 " "(KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36" ), "Accept": "application/json", "Accept-Encoding": "gzip, deflate", "Connection": "keep-alive", }
def ambil_bps(domain, var_id, app_key, kode_tahun=None, percobaan=3): url = f"{BASE}/domain/{domain}/var/{var_id}/key/{app_key}/" if kode_tahun: url += f"th/{kode_tahun}/"
for ke in range(1, percobaan + 1):
req = urllib.request.Request(url, headers=HEADERS)
try:
with urllib.request.urlopen(req, timeout=30) as resp:
return json.loads(resp.read().decode("utf-8"))
except urllib.error.HTTPError as err:
if err.code in (403, 429) and ke < percobaan:
time.sleep(2 ** ke)
continue
print(f"[gagal] HTTP {err.code} pada percobaan {ke}")
return None
except Exception as exc:
if ke < percobaan:
time.sleep(2 ** ke)
continue
print(f"[gagal] koneksi: {exc}")
return None
return None
```
Pola 2 ** ke menghasilkan jeda 2, 4, dan 8 detik antar percobaan, yang cukup untuk melewati pembatasan sementara tanpa membuat pipeline menunggu terlalu lama. Fungsi mengembalikan None alih-alih melempar pengecualian, sehingga pemanggil dapat memutuskan sendiri apakah data yang gagal itu bersifat wajib atau opsional.
Mengurai Struktur datacontent yang Komposit
Bagian yang paling sering membingungkan adalah objek datacontent. Alih-alih array objek dengan kunci dan nilai terpisah, BPS menyajikan nilai pengukuran sebagai kamus satu dimensi dengan kunci gabungan. Kunci tersebut merupakan rangkaian dari ID variabel, ID turunan variabel, ID wilayah, ID tahun, dan ID periode. Contoh bentuknya:
datacontent["1234000012401"] = 9.03
Angka 9.03 pada contoh di atas adalah nilai indikator, sedangkan kuncinya perlu dipecah dengan mencocokkan potongan substring terhadap metadata yang dikirim pada blok var, turvar, vervar, dan period. Pendekatan yang paling aman adalah memetakan setiap ID ke labelnya terlebih dahulu, lalu menyusun baris tabel:
python
def uraikan(payload):
meta_var = {v["val"]: v["label"] for v in payload["var"]}
meta_period = {p["val"]: p["label"] for p in payload["period"]}
baris = []
for kunci, nilai in payload["datacontent"].items():
baris.append({
"kunci": kunci,
"variabel": meta_var.get(kunci[:2]),
"periode": meta_period.get(kunci[-2:]),
"nilai": nilai,
})
return baris
Potongan indeks pada kunci[:2] dan kunci[-2:] mengikuti pola ID dua digit yang dipakai BPS pada respons contoh. Karena panjang segmen dapat berbeda antar katalog, kode produksi sebaiknya memverifikasi panjang kunci terlebih dahulu dan melewati entri yang tidak sesuai pola, bukan mengasumsikan satu format tetap.
Contoh Live: Keluaran Nyata 24 September 2026
Nilai berikut adalah hasil penarikan langsung ke katalog publik BPS pada 24 September 2026, bukan angka contoh yang dikarang. Dua indikator dipakai sebagai studi kasus karena keduanya mewakili jenis data yang berbeda: satu berasal dari survei sosial semesteran, satu lagi dari rangkaian nilai tukar.
Indikator pertama adalah persentase penduduk miskin nasional. Data ini dirilis secara semesteran, dengan periode survei Maret dan September:
- Tahun 2024 Semester 1 (Maret): 9,03 persen.
- Tahun 2024 Semester 2 (September): 8,57 persen.
- Tahun 2025 Semester 1 (Maret): 8,47 persen.
- Tahun 2025 Semester 2 (September): 8,25 persen.
Indikator kedua adalah rata-rata kurs transaksi Bank Indonesia terhadap dolar Amerika Serikat:
- Tahun 2023: Rp 15.416 per USD.
- Tahun 2024: Rp 16.162 per USD.
Perlu dicatat bahwa kode tahun pada permintaan tidak selalu sama dengan tahun kalender. Untuk seri data tertentu, BPS memakai kode internal dua atau tiga digit, misalnya 124 untuk 2024 dan 125 untuk 2025. Menebak kode tahun tanpa memeriksa katalog adalah sumber kesalahan yang paling sering muncul pada implementasi baru, dan gejalanya berupa respons kosong tanpa pesan galat yang jelas.
Selain dua indikator di atas, katalog yang sama juga mengekspos siaran pers resmi lengkap dengan tanggal rilis. Pada penarikan 24 September 2026, entri siaran pers terbaru yang tersedia bertanggal 1 September 2026. Endpoint ini berguna untuk memantau kapan rilis baru muncul, sehingga penjadwalan penarikan data bisa disesuaikan dengan kalender publikasi BPS, bukan ditebak.
Membaca Angkanya: Dua Tren yang Berbeda
Dua indikator di atas memberi gambaran mengapa pemisahan jenis data penting dalam sebuah pipeline. Untuk kemiskinan, selisih antara Semester 1 2024 dan Semester 2 2025 adalah 0,78 poin persen, turun dari 9,03 ke 8,25. Angka tersebut merupakan hasil pengurangan sederhana atas nilai resmi BPS, bukan estimasi. Untuk kurs, rata-rata tahunan bergerak dari Rp 15.416 ke Rp 16.162, selisih Rp 746 per USD atau sekitar 4,84 persen, yang menggambarkan pelemahan nilai tukar rata-rata sepanjang periode itu.
Perbedaan karakter kedua data berdampak langsung pada desain penjadwalan. Indikator semesteran tidak perlu ditarik setiap hari karena nilainya tidak berubah di antara dua rilis. Menariknya setiap hari hanya membebani kuota API dan menambah baris log tanpa informasi baru. Sebaliknya, endpoint daftar siaran pers justru layak diperiksa lebih sering karena fungsinya memberi sinyal kapan data baru tersedia.
Pola yang disarankan adalah memeriksa kalender rilis pada frekuensi tinggi, lalu menarik nilai indikatornya hanya ketika muncul tanda rilis baru. Pendekatan ini menekan jumlah permintaan ke server BPS sekaligus menjaga data pada aplikasi tetap mutakhir.
💬 Komentar (0)
Belum ada komentar. Jadilah yang pertama! 💬