Salaah (prayer) times for every masjid on MasjidScreen, as simple JSON. Free to use, no key and no sign-up: one GET request per masjid.
FreeNo API keyCORS enabled1 request / second
Every masjid has its own address on MasjidScreen, called its slug (for example northcliff for masjidscreen.co.za/northcliff/). Add /api/prayertimes.php to it:
curl "https://masjidscreen.co.za/northcliff/api/prayertimes.php?fields=fajr,zuhr,asr,maghrib,esha"
That returns today's times for that masjid, in the masjid's own timezone, with no authentication.
Press "Send request" to see a live response.
| Name | Where | Description |
|---|---|---|
slug | path | The masjid's slug, e.g. northcliff. Required. |
date | query | YYYY-MM-DD. Defaults to today in the masjid's timezone. Times repeat every year, so any year returns that day and month's times. |
fields | query | Comma-separated list to get a smaller, flat response: fajr, zuhr, asr, maghrib, esha, jummah, sunrise, sehri, zawal. (Also accepted: zohr, dhuhr, magrib, isha, jumuah, suhoor.) |
{
"masjid": {
"slug": "northcliff",
"name": "Northcliff Masjid",
"area": "Risidale, Randburg",
"address": "3 Salerno Road, Risidale, Randburg",
"timezone": "Africa/Johannesburg",
"url": "https://masjidscreen.co.za/northcliff/"
},
"date": "2026-10-29",
"salaah_times": {
"fajr": { "athaan": "04:25:00", "jamaat": "04:45:00" },
"zuhr": { "athaan": "12:55:00", "jamaat": "13:15:00" },
"asr": { "athaan": "17:00:00", "jamaat": "17:15:00" },
"maghrib": { "athaan": "18:25:00", "jamaat": "18:25:00" },
"esha": { "athaan": "19:45:00", "jamaat": "20:00:00" },
"jummah": { "athaan": "12:20:00", "jamaat": "12:50:00" }
},
"reference_times": { "sehri_end": "03:54:00", "sunrise": "05:21:00", "zawal": "11:47:00", "source": "city" },
"upcoming_changes": [
{ "salaah": "asr", "effective_date": "2026-11-01", "athaan": "17:15:00", "jamaat": "17:30:00" }
]
}
HH:MM:SS, in the masjid's own timezone.null. jummah only applies on Fridays; some masjids don't have one.reference_times are astronomical times for the masjid's area: sehri_end, sunrise, zawal.upcoming_changes lists time changes coming up shortly, so an app can warn people in advance.?fields=fajr,sunrise&date=2026-12-25){
"masjid": "northcliff",
"date": "2026-12-25",
"fajr": { "athaan": "04:10:00", "jamaat": "04:30:00" },
"sunrise": "05:14:00"
}
Errors are JSON like {"error": "…"}.
| Status | When |
|---|---|
400 | The date isn't YYYY-MM-DD, or a fields name is unknown (the response lists the valid ones). |
404 | There is no masjid with that slug. |
429 | Too many requests. Wait the number of seconds in the Retry-After header, then try again. |
500 | Something went wrong on our side. Try again shortly. |
Responses allow requests from any website (Access-Control-Allow-Origin: *), so it works straight from browser JavaScript.
# Today's times for one masjid
curl "https://masjidscreen.co.za/northcliff/api/prayertimes.php?fields=fajr,zuhr,asr,maghrib,esha"
# Just the Asr jamaat time, using jq
curl -s "https://masjidscreen.co.za/northcliff/api/prayertimes.php?fields=asr" | jq -r '.asr.jamaat'
# A specific date (identify your app with a User-Agent)
curl -A "my-app/1.0 (you@example.com)" "https://masjidscreen.co.za/northcliff/api/prayertimes.php?date=2026-12-25&fields=fajr"
// Works in a browser or Node 18+
async function getTimes(slug) {
const url = `https://masjidscreen.co.za/${slug}/api/prayertimes.php?fields=fajr,zuhr,asr,maghrib,esha`;
const res = await fetch(url);
if (res.status === 429) { // too many requests: wait, then retry once
const wait = Number(res.headers.get('Retry-After') || 1);
await new Promise(r => setTimeout(r, wait * 1000));
return getTimes(slug);
}
if (!res.ok) throw new Error((await res.json()).error);
return res.json();
}
const t = await getTimes('northcliff');
console.log(`${t.date}: Asr jamaat ${t.asr.jamaat}`);
Cache the result instead of fetching on every page view; the times only change once a day.
// Needs the full response, which includes the masjid's timezone
const res = await fetch('https://masjidscreen.co.za/northcliff/api/prayertimes.php');
const { masjid, salaah_times } = await res.json();
const parts = new Intl.DateTimeFormat('en-GB', { timeZone: masjid.timezone, hour: '2-digit', minute: '2-digit', hourCycle: 'h23' })
.formatToParts(new Date());
const nowMin = Number(parts.find(p => p.type === 'hour').value) * 60 + Number(parts.find(p => p.type === 'minute').value);
const toMin = (t) => { const [h, m] = t.split(':'); return h * 60 + Number(m); };
const next = ['fajr', 'zuhr', 'asr', 'maghrib', 'esha']
.map((name) => ({ name, jamaat: salaah_times[name].jamaat }))
.find((p) => p.jamaat && toMin(p.jamaat) > nowMin);
console.log(next ? `Next: ${next.name} at ${next.jamaat.slice(0, 5)}` : "All of today's prayers have passed");
import time
import requests
HEADERS = {"User-Agent": "my-app/1.0 (you@example.com)"} # tell us who you are
def get_times(slug, **params):
r = requests.get(f"https://masjidscreen.co.za/{slug}/api/prayertimes.php", params=params, headers=HEADERS, timeout=10)
if r.status_code == 429: # too many requests: wait, then retry once
time.sleep(int(r.headers.get("Retry-After", 1)))
return get_times(slug, **params)
r.raise_for_status()
return r.json()
t = get_times("northcliff", fields="fajr,zuhr,asr,maghrib,esha")
print(t["date"], "Asr jamaat", t["asr"]["jamaat"])
import re, time, requests
sitemap = requests.get("https://masjidscreen.co.za/sitemap.php", timeout=10).text
slugs = re.findall(r"masjidscreen\.co\.za/([a-z0-9_]+)/<", sitemap)
for slug in slugs[:20]:
t = get_times(slug, fields="fajr,asr") # get_times from above
print(slug, t["fajr"]["jamaat"], t["asr"]["jamaat"])
time.sleep(1.1) # at most one request per second
<?php
$url = "https://masjidscreen.co.za/northcliff/api/prayertimes.php?fields=fajr,zuhr,asr,maghrib,esha";
$context = stream_context_create(["http" => [
"header" => "User-Agent: my-app/1.0 (you@example.com)\r\n",
"timeout" => 10,
"ignore_errors" => true, // so a 4xx/5xx body can be read
]]);
$body = file_get_contents($url, false, $context);
$data = json_decode($body, true);
if (isset($data["error"])) {
exit("Error: " . $data["error"]); // e.g. a 429 when requests are too frequent
}
echo $data["date"] . " Asr jamaat " . $data["asr"]["jamaat"] . "\n";
masjidscreen.co.za/slug/.429 Too Many Requests with a Retry-After header.Developers are welcome to use the API, as long as it's used responsibly:
fields to keep responses small.429. Wait for Retry-After instead of retrying immediately.User-Agent and a contact address, so we can reach you if something misbehaves.Need more than this allows, a bulk export, or have something to report? Email support@masjidscreen.co.za.
AI assistants and agents are welcome to use the same API. A short guide written for them is at /llms.txt, and the same rate limit and fair-use guidelines apply.