Indonesia Region API
A free, static JSON API of Indonesia's administrative regions: provinces, regencies/cities, districts and villages. No API key, no rate limits, and any website can call it (CORS enabled).
Endpoints
All endpoints are GET requests for static files under https://your-site.pages.dev/api/.
| Endpoint | Returns | Example |
|---|---|---|
/api/provinces.json | All provinces | provinces.json |
/api/regencies/{provinceCode}.json | Regencies and cities in a province | regencies/11.json |
/api/districts/{regencyCode}.json | Districts in a regency or city | districts/11.01.json |
/api/villages/{districtCode}.json | Villages in a district | villages/11.01.01.json |
Response format
Every endpoint returns a JSON array of { code, name } objects, sorted by code.
[
{ "code": "11.01", "name": "Kabupaten Aceh Selatan" },
{ "code": "11.02", "name": "Kabupaten Aceh Tenggara" }
]Region codes
Codes follow the official Kemendagri format. Each level adds a dot-separated segment to its parent's code, so a region's parent can always be read from its own code.
| Level | Format | Example |
|---|---|---|
| Province | PP | 11 Aceh |
| Regency / city | PP.RR | 11.01 Kabupaten Aceh Selatan |
| District | PP.RR.DD | 11.01.01 Bakongan |
| Village | PP.RR.DD.VVVV | 11.01.01.2001 Keude Bakongan |
Errors
A code that does not exist returns HTTP 404. Always check response.ok before parsing the body.
Calling from the browser (CORS)
Every /api/* response includes these headers, so JavaScript on any website can call the API directly with fetch: from your own domain, another domain, or localhost during development. No proxy or backend is needed.
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, HEADTo keep requests working from the browser:
- Use a plain
GETrequest, likefetch(url). OnlyGETandHEADare supported. - Don't add custom request headers (such as
AuthorizationorContent-Type). They make the browser send anOPTIONSpreflight request first, which a static site cannot answer, so the request fails. - Don't set
credentials: "include". Browsers reject a wildcard*origin for credentialed requests, and the API needs no cookies or keys anyway.
Examples
JavaScript
const BASE = "https://your-site.pages.dev/api";
async function getRegions(path) {
const res = await fetch(`${BASE}/${path}.json`);
if (!res.ok) throw new Error(`Region not found: ${path}`);
return res.json();
}
const provinces = await getRegions("provinces");
const regencies = await getRegions(`regencies/${provinces[0].code}`);curl
curl https://your-site.pages.dev/api/districts/11.01.jsonTry it
Each selection fetches the next level from this API.
…