Regions
Regions follow Kepmendagri 300.2.2-2138/2025 as amended by 300.2.2-2430/2025. Each level adds one segment to the code:
- Province
province31DKI Jakarta - Regency or city
regency31.71Jakarta Pusat - District
district31.71.01Gambir - Village
village31.71.01.1001Gambir
- GambirDistrict
31.71.01Daerah Khusus Ibukota Jakarta › Kota Administrasi Jakarta Pusat - GambirVillage
31.71.01.1001Daerah Khusus Ibukota Jakarta › Kota Administrasi Jakarta Pusat › Gambir - GambiranDistrict
35.10.07Jawa Timur › Kabupaten Banyuwangi - Gambir BaruVillage
12.09.20.1012Sumatera Utara › Kabupaten Asahan › Kota Kisaran Timur - GambirmanisVillage
33.12.01.2004Jawa Tengah › Kabupaten Wonogiri › Pracimantoro - GambiranomVillage
33.12.07.2006Jawa Tengah › Kabupaten Wonogiri › Baturetno
Runs in your browser.
Codes may be written with or without dots, spaces or hyphens (3171, 31.71, 31 71).
Functions
Section titled “Functions”| Go | TypeScript | Returns |
|---|---|---|
region.Get(code) |
region.get(code) |
One region with the current code |
region.Resolve(code) |
region.resolve(code) |
Like Get, but follows codes renumbered by the 2012 Kalimantan Utara and 2022 Papua splits |
region.Children(code) |
region.children(code) |
Direct children, "" lists the provinces |
region.Search(q, opts) |
region.search(q, opts) |
Regions whose name matches q, best match first |
region.ByPlate(code) |
region.byPlate(code) |
Regencies registered under a plate code such as DR |
region.ByAreaCode(code) |
region.byAreaCode(code) |
Province or regencies behind a fixed-line area code |
region.FromNIK(nik) |
region.fromNik(nik) |
Province, regency and district names for a NIK |
In TypeScript every function is async: district and village data are split into one chunk per province and load only when needed. The index of provinces, regencies, aliases, plates and area codes is under 16 KB gzip. In Go, data loads once on first use (about 10 ms).
The per-province chunks rely on dynamic import(). Vite, webpack, Rollup and esbuild with splitting: true emit them as separate files. A bundler that inlines dynamic imports puts every province into one file (about 500 KB gzip), so enable code splitting for browser builds.
Search options
Section titled “Search options”Go SearchOptions |
TypeScript | Meaning |
|---|---|---|
Level |
level |
Only one level: province, regency, district, village |
Within |
within |
Only descendants of this code |
Limit |
limit |
1 to 100, default 10 |
Matching ignores case and the Kabupaten/Kota prefix. Exact names rank first, then prefixes, then word starts, then any substring. Queries are limited to 256 characters.
Searching districts or villages without within reads every province. In a browser, pass within to load a single province.
Place (from a NIK)
Section titled “Place (from a NIK)”| Field | Notes |
|---|---|
province |
Always present |
regency |
Present when the regency still exists |
district |
Present when the district still exists |
historical |
true when the NIK uses a code from before a split, names are current |
Errors
Section titled “Errors”length, charset, unknown (well-formed code that does not exist), options.
Example
Section titled “Example”package main
import ( "fmt"
"github.com/haikalmumtaz233/nusaindex/region")
func main() { regency, err := region.Get("31.71") if err == nil { fmt.Println(regency.Name, regency.Level, regency.ParentCode) }
districts, err := region.Children("31.71") if err == nil { fmt.Println(len(districts), districts[0].Name) }
found, err := region.Search("gambir", region.SearchOptions{Level: region.LevelDistrict, Limit: 2}) if err == nil { for _, r := range found { fmt.Println(r.Code, r.Name) } }
current, err := region.Resolve("91.04") if err == nil { fmt.Println(current.Code, current.Name) }
byPlate, err := region.ByPlate("DR") if err == nil { fmt.Println(len(byPlate), byPlate[0].Name) }
byArea, err := region.ByAreaCode("0274") if err == nil { fmt.Println(byArea[0].Code, byArea[0].Name) }
place, err := region.FromNIK("7502010706599583") if err == nil { fmt.Println(place.Province.Name, place.Regency.Name, place.District.Name, place.Historical) }}import * as region from "nusaindex/region";
const regency = await region.get("31.71");if (regency.ok) { console.log(regency.value.name, regency.value.level, regency.value.parentCode);}
const districts = await region.children("31.71");if (districts.ok) { console.log(districts.value.length, districts.value[0]?.name);}
const found = await region.search("gambir", { level: "district", limit: 2 });if (found.ok) { for (const r of found.value) { console.log(r.code, r.name); }}
const current = await region.resolve("91.04");if (current.ok) { console.log(current.value.code, current.value.name);}
const byPlate = await region.byPlate("DR");if (byPlate.ok) { console.log(byPlate.value.length, byPlate.value[0]?.name);}
const byArea = await region.byAreaCode("0274");if (byArea.ok) { console.log(byArea.value[0]?.code, byArea.value[0]?.name);}
const place = await region.fromNik("7502010706599583");if (place.ok) { const { province, regency: kab, district, historical } = place.value; console.log(province.name, kab?.name, district?.name, historical);}Kota Administrasi Jakarta Pusat regency 318 Gambir31.71.01 Gambir35.10.07 Gambiran94.01 Kabupaten Nabire5 Kabupaten Lombok Barat34.71 Kota YogyakartaGorontalo Kabupaten Boalemo Paguyaman false© 2026 Haikal Mumtaz