Kodifikasi wilayah · static JSON · /api/v1
Indonesia Region API
Machine-readable Indonesian administrative region codes and hierarchy. Free, read-only, no API key, served as static files from a CDN.
Dataset kepmendagri-300.2.2-2138-2025+2430-2025 · effective 2025-06-23
Administrative levels
-
Province
Provinsi
38
31
-
Regency / City
Kabupaten / Kota
514
31.71
416 kabupaten · 98 kota
-
District
Kecamatan / Distrik
7,285
31.71.01
-
Village
Kelurahan / Desa
83,762
31.71.01.1001
8,496 kelurahan · 75,252 desa · 14 desa adat
Quick start
Every endpoint is a plain JSON file. Walk the hierarchy one level at a time instead of downloading everything.
# All provinces
curl https://indonesia-region.caturseptian.site/api/v1/provinces.json
# Regencies/cities in DKI Jakarta (31)
curl https://indonesia-region.caturseptian.site/api/v1/provinces/31/regencies.json
# Districts in Kota Administrasi Jakarta Pusat (31.71)
curl https://indonesia-region.caturseptian.site/api/v1/regencies/31.71/districts.json
# Villages in Kecamatan Gambir (31.71.01)
curl https://indonesia-region.caturseptian.site/api/v1/districts/31.71.01/villages.json
const BASE = "https://indonesia-region.caturseptian.site/api/v1";
const provinces = await fetch(`${BASE}/provinces.json`).then((r) => r.json());
const regencies = await fetch(`${BASE}/provinces/31/regencies.json`).then((r) => r.json());
const villages = await fetch(`${BASE}/districts/31.71.01/villages.json`).then((r) => r.json());
console.log(villages[0]);
// { code: "31.71.01.1001", name: "Gambir", type: "kelurahan", district_code: "31.71.01", ... }
import requests
BASE = "https://indonesia-region.caturseptian.site/api/v1"
provinces = requests.get(f"{BASE}/provinces.json", timeout=30).json()
districts = requests.get(f"{BASE}/regencies/31.71/districts.json", timeout=30).json()
for d in districts:
print(d["code"], d["name"])
Base URL: https://indonesia-region.caturseptian.site/api/v1/. No API key, no sign-up.
Endpoints
- GET/api/v1/meta.jsonversion, sources, counts
- GET/api/v1/provinces.json38 provinces
- GET/api/v1/provinces/{code}/regencies.jsonregencies/cities of a province
- GET/api/v1/regencies/{code}/districts.jsondistricts of a regency/city
- GET/api/v1/districts/{code}/villages.jsonvillages of a district
- GET/api/v1/{provinces|regencies|districts}/{code}.jsonone record with its parents and counts
- GET/api/v1/export/indonesia-regions.{csv|json|xml|sql|xlsx|pdf}full dataset download: CSV, JSON, XML, SQL, Excel, PDF
- GET/api/v1/islands.json · islands.geojson17,374 islands with coordinates (also GeoJSON) · map
- GET/api/v1/villages.jsonall 83,762 villages (24 MB, deprecated; use the per-province or per-district files)
- GET/api/v1/provinces/{code}/villages.jsonvillages of a province
Response
GET /api/v1/districts/31.71.01/villages.json (first record)
[
{
"code": "31.71.01.1001",
"name": "Gambir",
"type": "kelurahan",
"district_code": "31.71.01",
"regency_code": "31.71",
"province_code": "31",
"source_page": 1335
},
...
]
Codes are always strings (leading zeros are significant). source_page is the page of the source PDF the record was read from.
Where the data comes from
The dataset is extracted from the annex of Keputusan Menteri Dalam Negeri Nomor 300.2.2-2138 Tahun 2025 (as amended by Kepmendagri 300.2.2-2430 Tahun 2025, which changes island data only), validated against the document's own recap totals, and published as static files. Every record carries the PDF page it came from. Earlier code tables (Permendagri 137/2017, Kepmendagri 100.1.1-6117/2022) are kept as historical snapshots with change lists.
This is an independent project providing machine-readable data derived from publicly available Indonesian government regulatory documents. It is not an official government API and is not endorsed by the Ministry of Home Affairs.