DEV Community

Pijar Sukma Adiluhung
Pijar Sukma Adiluhung

Posted on

Hijri Dates in Indonesia Were a Pain to Get Right. Not Anymore.

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
Enter fullscreen mode Exit fullscreen mode

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": []
}
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode
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`)
})
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode
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}`)
    })
  })
Enter fullscreen mode Exit fullscreen mode

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

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)