If you've ever built a website for Indonesian users and needed to show today's Hijri date, you probably know the pain. Most Hijri calendar APIs and libraries default to Umm al-Qura (Saudi Arabia's calendar), which can differ by a full day from what's actually observed and announced in Indonesia.
It's not just a theoretical mismatch. In my own community, this got bad enough that nobody trusts online Hijri dates anymore. People just wait for the official government announcement instead of checking a website or app, because too many times, the date shown online didn't match what Kemenag (Indonesia's Ministry of Religious Affairs) actually announced. A one-day difference sounds small, until it's the difference between fasting on the right day or not.
The root cause is simple: Indonesia (along with Malaysia, Brunei, and Singapore) uses a different visibility standard called MABIMS, not Umm al-Qura. Most APIs just never bothered to support it.
That's exactly the gap I set out to close: mabims.dev an open-source Hijri calendar API for Indonesia, built on the country's official MABIMS criteria instead of Saudi Arabia's Umm al-Qura standard. Free, open-source, no API key required. Here's how to use it.
What We're Building
A simple "Today in Hijri" widget, then leveling it up into a date converter and a full month grid. All plain JavaScript, no dependencies.
Step 1: Get Today's Date
GET https://api.mabims.dev/api/v1/today
Response:
{
"input": { "date": "2026-08-24", "calendar": "gregorian", "tz": "Asia/Jakarta" },
"output": {
"date": "1448-03-11",
"calendar": "hijri",
"day": 11,
"month": 3,
"month_name": "Rabiul Akhir",
"year": 1448
},
"source": "mabims",
"warnings": []
}
Note the output object already gives you day, month_name, and year separately — no string parsing needed.
Step 2: Render It
<span id="hijri-date">Loading...</span>
<script>
fetch('https://api.mabims.dev/api/v1/today')
.then(res => res.json())
.then(data => {
const { day, month_name, year } = data.output
document.getElementById('hijri-date').textContent = `${day} ${month_name} ${year} H`
})
.catch(() => {
document.getElementById('hijri-date').textContent = '-'
})
</script>
That's it. Output: 11 Rabiul Akhir 1448 H.
Step 3: Add a Date Converter
Sometimes you need to convert a specific date, not just "today." Use /convert:
GET https://api.mabims.dev/api/v1/convert?date=2026-08-24&calendar=gregorian
async function convertDate(date) {
const res = await fetch(`https://api.mabims.dev/api/v1/convert?date=${date}&calendar=gregorian`)
const data = await res.json()
return data.output
}
convertDate('2026-08-24').then(output => {
console.log(`${output.day} ${output.month_name} ${output.year} H`)
})
Flip calendar=gregorian to calendar=hijri (with a Hijri-format date like 1448-03-11) to convert the other direction.
Step 4: Render a Full Month Grid
Need a whole calendar, not just one date? Use /month:
GET https://api.mabims.dev/api/v1/month?year=1447&month=9&calendar=hijri
fetch('https://api.mabims.dev/api/v1/month?year=1447&month=9&calendar=hijri')
.then(res => res.json())
.then(data => {
data.items.forEach(item => {
console.log(`${item.hijri} — ${item.gregorian}`)
})
})
Need a whole year in one call instead of looping /month twelve times? There's a /year endpoint too, grouped by month.
What's Under the Hood
mabims.dev sources its dates from Kemenag RI's official tables (2024–2026 currently), and falls back to computed Neo MABIMS criteria (moon altitude ≥ 3°, elongation ≥ 6.4°) for dates outside that range, up to 2053. Every response tells you which one you got via the source field: "mabims" for table data, "mabims-computed" for the calculated fallback.
There's also a genuinely fun endpoint, /hilal/viz, that renders an actual sky chart PNG showing moon position, visibility criteria, and verdict for any given month — worth a look if you're curious how moon-sighting criteria translate visually.
Try It / Contribute
- Docs: mabims.dev
- Source: github.com/PijarAdiluhung/mabims-api
No API key, no rate-limit paywall, CORS-open so you can call it straight from the browser. If you build something with it, or hit an edge case, issues and PRs are welcome.
Top comments (0)