Back to skills
SkillHub ClubShip Full StackFull StackBackend

jadwal-sholat

Ambil jadwal sholat (imsak, subuh, dzuhur, ashar, maghrib, isya) untuk kota/kabupaten di Indonesia dari API Muslim api.myquran.com (sumber Kemenag Bimas Islam). Gunakan saat user minta jadwal sholat hari ini / tanggal tertentu / 1 bulan untuk lokasi tertentu, atau butuh mencari ID kab/kota.

Packaged view

This page reorganizes the original catalog entry around fit, installability, and workflow context first. The original raw source lives below.

Stars
3,110
Hot score
99
Updated
March 20, 2026
Overall rating
C4.0
Composite score
4.0
Best-practice grade
B78.7

Install command

npx @skill-hub/cli install openclaw-skills-jadwal-sholat

Repository

openclaw/skills

Skill path: skills/banghasan/jadwal-sholat

Ambil jadwal sholat (imsak, subuh, dzuhur, ashar, maghrib, isya) untuk kota/kabupaten di Indonesia dari API Muslim api.myquran.com (sumber Kemenag Bimas Islam). Gunakan saat user minta jadwal sholat hari ini / tanggal tertentu / 1 bulan untuk lokasi tertentu, atau butuh mencari ID kab/kota.

Open repository

Best for

Primary workflow: Ship Full Stack.

Technical facets: Full Stack, Backend.

Target audience: everyone.

License: Unknown.

Original source

Catalog source: SkillHub Club.

Repository owner: openclaw.

This is still a mirrored public skill entry. Review the repository before installing into production workflows.

What it helps with

  • Install jadwal-sholat into Claude Code, Codex CLI, Gemini CLI, or OpenCode workflows
  • Review https://github.com/openclaw/skills before adding jadwal-sholat to shared team environments
  • Use jadwal-sholat for development workflows

Works across

Claude CodeCodex CLIGemini CLIOpenCode

Favorites: 0.

Sub-skills: 0.

Aggregator: No.

Original source / Raw SKILL.md

---
name: jadwal-sholat
description: Ambil jadwal sholat (imsak, subuh, dzuhur, ashar, maghrib, isya) untuk kota/kabupaten di Indonesia dari API Muslim api.myquran.com (sumber Kemenag Bimas Islam). Gunakan saat user minta jadwal sholat hari ini / tanggal tertentu / 1 bulan untuk lokasi tertentu, atau butuh mencari ID kab/kota.
---

# Jadwal Sholat (api.myquran.com)

API base: `https://api.myquran.com/v3`

Script helper (rekomendasi): `scripts/myquran_sholat.py`

## Quick start

Cari lokasi (kab/kota):

```bash
python3 scripts/myquran_sholat.py cari "tangerang"
```

Jadwal sholat hari ini (Asia/Jakarta) untuk lokasi berdasarkan keyword:

```bash
python3 scripts/myquran_sholat.py hari-ini "kota tangerang"
```

Jadwal sholat tanggal tertentu (format `YYYY-MM-DD`):

```bash
python3 scripts/myquran_sholat.py tanggal "kota tangerang" 2026-02-03
```

Jadwal sholat 1 bulan (format `YYYY-MM`):

```bash
python3 scripts/myquran_sholat.py bulan "kota tangerang" 2026-02
```

## Catatan pemilihan lokasi

Endpoint pencarian mengembalikan beberapa kandidat. Script akan:
- mencoba match exact (case-insensitive) ke kolom `lokasi` bila memungkinkan
- kalau tidak, pakai hasil pertama

Kalau hasilnya kurang tepat, gunakan keyword yang lebih spesifik (mis. `KOTA TANGERANG` vs `TANGERANG`), atau ambil `id` lokasi lalu panggil mode `id`.

## Pemanggilan langsung via curl (tanpa script)

Cari kab/kota:

```bash
curl -s "https://api.myquran.com/v3/sholat/kabkota/cari/tangerang"
```

Ambil jadwal hari ini:

```bash
curl -s "https://api.myquran.com/v3/sholat/jadwal/<ID>/today?tz=Asia/Jakarta"
```

Ambil jadwal periode (bulanan / harian):

```bash
# bulanan
curl -s "https://api.myquran.com/v3/sholat/jadwal/<ID>/2026-02?tz=Asia/Jakarta"

# harian
curl -s "https://api.myquran.com/v3/sholat/jadwal/<ID>/2026-02-03?tz=Asia/Jakarta"
```


---

## Referenced Files

> The following files are referenced in this skill and included for context.

### scripts/myquran_sholat.py

```python
#!/usr/bin/env python3
"""Helper untuk API jadwal sholat Indonesia (api.myquran.com).

Tidak butuh dependency eksternal (stdlib only).

Commands:
  cari <keyword>
  hari-ini <keyword>
  tanggal <keyword> <YYYY-MM-DD>
  bulan <keyword> <YYYY-MM>
  id-hari-ini <id>
  id-tanggal <id> <YYYY-MM-DD>
  id-bulan <id> <YYYY-MM>

Output default: teks ringkas.
"""

from __future__ import annotations

import argparse
import json
import sys
import urllib.parse
import urllib.request
from typing import Any, Dict, List, Optional, Tuple

API_BASE = "https://api.myquran.com/v3"
DEFAULT_TZ = "Asia/Jakarta"


def _get_json(url: str, timeout: int = 20) -> Dict[str, Any]:
    req = urllib.request.Request(url, headers={"User-Agent": "openclaw-jadwal-sholat/1.0"})
    with urllib.request.urlopen(req, timeout=timeout) as resp:
        raw = resp.read().decode("utf-8", errors="replace")
    return json.loads(raw)


def search_locations(keyword: str) -> List[Dict[str, Any]]:
    kw = urllib.parse.quote(keyword.strip())
    url = f"{API_BASE}/sholat/kabkota/cari/{kw}"
    j = _get_json(url)
    if not j.get("status"):
        return []
    data = j.get("data")
    if isinstance(data, list):
        return data
    return []


def pick_location(keyword: str, items: List[Dict[str, Any]]) -> Optional[Dict[str, Any]]:
    if not items:
        return None
    k = keyword.strip().lower()
    # Exact match against lokasi field
    for it in items:
        lokasi = str(it.get("lokasi", "")).strip().lower()
        if lokasi == k:
            return it
    # Contains match
    for it in items:
        lokasi = str(it.get("lokasi", "")).strip().lower()
        if k and k in lokasi:
            return it
    return items[0]


def fetch_jadwal_today(id_: str, tz: str = DEFAULT_TZ) -> Dict[str, Any]:
    q = urllib.parse.urlencode({"tz": tz})
    url = f"{API_BASE}/sholat/jadwal/{urllib.parse.quote(id_)}/today?{q}"
    return _get_json(url)


def fetch_jadwal_period(id_: str, period: str, tz: str = DEFAULT_TZ) -> Dict[str, Any]:
    q = urllib.parse.urlencode({"tz": tz})
    url = f"{API_BASE}/sholat/jadwal/{urllib.parse.quote(id_)}/{urllib.parse.quote(period)}?{q}"
    return _get_json(url)


def _extract_single_day(j: Dict[str, Any]) -> Tuple[str, Dict[str, Any], Dict[str, Any]]:
    """Return (label, meta, day) where day is an entry with keys imsak/subuh/..."""
    data = j.get("data") or {}
    meta = {
        "id": data.get("id"),
        "kabko": data.get("kabko"),
        "prov": data.get("prov"),
    }
    jadwal = (data.get("jadwal") or {})
    if not isinstance(jadwal, dict) or not jadwal:
        return ("", meta, {})
    # pick first key
    key = sorted(jadwal.keys())[0]
    day = jadwal.get(key) or {}
    label = str(day.get("tanggal") or key)
    return (label, meta, day)


def format_day(label: str, meta: Dict[str, Any], day: Dict[str, Any]) -> str:
    kabko = meta.get("kabko") or "(lokasi)"
    prov = meta.get("prov") or ""
    loc = f"{kabko}{', ' + prov if prov else ''}".strip()

    fields = [
        ("Imsak", day.get("imsak")),
        ("Subuh", day.get("subuh")),
        ("Terbit", day.get("terbit")),
        ("Dhuha", day.get("dhuha")),
        ("Dzuhur", day.get("dzuhur")),
        ("Ashar", day.get("ashar")),
        ("Maghrib", day.get("maghrib")),
        ("Isya", day.get("isya")),
    ]
    lines = [f"{loc}", f"Tanggal: {label}"]
    for k, v in fields:
        if v:
            lines.append(f"- {k}: {v}")
    return "\n".join(lines)


def cmd_cari(args: argparse.Namespace) -> int:
    items = search_locations(args.keyword)
    if not items:
        print("Tidak ditemukan lokasi.")
        return 2
    # print as list
    for it in items[:30]:
        print(f"{it.get('id','')}\t{it.get('lokasi','')}")
    if len(items) > 30:
        print(f"... ({len(items)-30} lagi)")
    return 0


def cmd_hari_ini(args: argparse.Namespace) -> int:
    items = search_locations(args.keyword)
    picked = pick_location(args.keyword, items)
    if not picked:
        print("Tidak ditemukan lokasi.")
        return 2
    j = fetch_jadwal_today(str(picked.get("id")), tz=args.tz)
    if not j.get("status"):
        print(j.get("message") or "Gagal mengambil jadwal.")
        return 3
    label, meta, day = _extract_single_day(j)
    print(format_day(label, meta, day))
    return 0


def cmd_tanggal(args: argparse.Namespace) -> int:
    items = search_locations(args.keyword)
    picked = pick_location(args.keyword, items)
    if not picked:
        print("Tidak ditemukan lokasi.")
        return 2
    j = fetch_jadwal_period(str(picked.get("id")), args.date, tz=args.tz)
    if not j.get("status"):
        print(j.get("message") or "Gagal mengambil jadwal.")
        return 3
    label, meta, day = _extract_single_day(j)
    print(format_day(label, meta, day))
    return 0


def cmd_bulan(args: argparse.Namespace) -> int:
    items = search_locations(args.keyword)
    picked = pick_location(args.keyword, items)
    if not picked:
        print("Tidak ditemukan lokasi.")
        return 2
    j = fetch_jadwal_period(str(picked.get("id")), args.month, tz=args.tz)
    if not j.get("status"):
        print(j.get("message") or "Gagal mengambil jadwal.")
        return 3
    data = j.get("data") or {}
    jadwal = data.get("jadwal") or {}
    if not isinstance(jadwal, dict) or not jadwal:
        print("Jadwal kosong.")
        return 4
    # Print first 7 days as preview
    keys = sorted(jadwal.keys())
    meta = {"kabko": data.get("kabko"), "prov": data.get("prov")}
    print(f"{meta.get('kabko','(lokasi)')}, {meta.get('prov','')}``.\nBulan: {args.month} (menampilkan 7 hari pertama)".replace('`', ''))
    for k in keys[:7]:
        day = jadwal.get(k) or {}
        label = str(day.get("tanggal") or k)
        print(f"\n{label}")
        for name in ["imsak","subuh","dzuhur","ashar","maghrib","isya"]:
            val = day.get(name)
            if val:
                print(f"- {name}: {val}")
    return 0


def cmd_id_hari_ini(args: argparse.Namespace) -> int:
    j = fetch_jadwal_today(args.id, tz=args.tz)
    if not j.get("status"):
        print(j.get("message") or "Gagal mengambil jadwal.")
        return 3
    label, meta, day = _extract_single_day(j)
    print(format_day(label, meta, day))
    return 0


def cmd_id_period(args: argparse.Namespace) -> int:
    j = fetch_jadwal_period(args.id, args.period, tz=args.tz)
    if not j.get("status"):
        print(j.get("message") or "Gagal mengambil jadwal.")
        return 3
    label, meta, day = _extract_single_day(j)
    print(format_day(label, meta, day))
    return 0


def main(argv: List[str]) -> int:
    ap = argparse.ArgumentParser(prog="myquran_sholat")
    ap.add_argument("--tz", default=DEFAULT_TZ, help="Timezone (default Asia/Jakarta)")

    sub = ap.add_subparsers(dest="cmd", required=True)

    p = sub.add_parser("cari", help="Cari kab/kota")
    p.add_argument("keyword")
    p.set_defaults(func=cmd_cari)

    p = sub.add_parser("hari-ini", help="Jadwal sholat hari ini berdasarkan keyword lokasi")
    p.add_argument("keyword")
    p.set_defaults(func=cmd_hari_ini)

    p = sub.add_parser("tanggal", help="Jadwal sholat tanggal tertentu (YYYY-MM-DD) berdasarkan keyword lokasi")
    p.add_argument("keyword")
    p.add_argument("date")
    p.set_defaults(func=cmd_tanggal)

    p = sub.add_parser("bulan", help="Jadwal sholat bulan tertentu (YYYY-MM) berdasarkan keyword lokasi (preview 7 hari)")
    p.add_argument("keyword")
    p.add_argument("month")
    p.set_defaults(func=cmd_bulan)

    p = sub.add_parser("id-hari-ini", help="Jadwal sholat hari ini berdasarkan id lokasi")
    p.add_argument("id")
    p.set_defaults(func=cmd_id_hari_ini)

    p = sub.add_parser("id-period", help="Jadwal sholat period (YYYY-MM / YYYY-MM-DD) berdasarkan id lokasi")
    p.add_argument("id")
    p.add_argument("period")
    p.set_defaults(func=cmd_id_period)

    args = ap.parse_args(argv)
    return int(args.func(args))


if __name__ == "__main__":
    raise SystemExit(main(sys.argv[1:]))

```



---

## Skill Companion Files

> Additional files collected from the skill directory layout.

### _meta.json

```json
{
  "owner": "banghasan",
  "slug": "jadwal-sholat",
  "displayName": "Jadwal Sholat",
  "latest": {
    "version": "1.0.0",
    "publishedAt": 1770260954969,
    "commit": "https://github.com/clawdbot/skills/commit/accf243d59343c80c5e4dd682098f5a157533b83"
  },
  "history": []
}

```