This project plays the adhan on a Raspberry Pi at the five prayer times. A Python script calculates the prayer times for your location each day. Cron then plays each adhan at its time.
This repository is the maintained fork of achaudhry/adhan. See Credits.
- A Raspberry Pi with Raspberry Pi OS.
- A Raspberry Pi Zero has no audio output port. If you are new to the Raspberry Pi, use a different model.
- To install Raspberry Pi OS, follow the getting started guide.
- Speakers.
- An auxiliary audio cable.
- A player for the adhan. Install only the player that you use (see Choosing the player):
sudo apt install vlc # player = vlc (the default)
sudo apt install pulseaudio-utils # player = paplayThe Bluetooth drivers of the Raspberry Pi have known problems. The speaker can disconnect at random times. We recommend a wired speaker.
- Install git. Open a terminal on the Raspberry Pi and type:
sudo apt install git- Clone this repository into your home directory:
cd ~
git clone https://github.com/rehanhaider/adhan.gitYou now have an adhan directory in your home directory.
3. Install uv with its official installer. It puts uv in
~/.local/bin and does not need sudo:
curl -LsSf https://astral.sh/uv/install.sh | shOpen a new terminal, so that uv is on your PATH.
4. Install the Python library of the script, python-crontab:
cd ~/adhan
uv syncuv makes a virtual environment in ~/adhan/.venv and installs the library in it. uv
uses the Python 3.11 of Raspberry Pi OS Bookworm, so it does not download a second
Python. The cron jobs run ~/adhan/.venv/bin/python, not uv, so they do not need
the network or uv at run time.
The examples in this README use ~/adhan. You can clone the repository into a different
directory. The script finds its files from its own location, and the cron jobs use the full
path of that directory.
Before #29, a copy of python-crontab was
in this repository and the cron jobs ran python3. After git pull, the old nightly job
finds no python-crontab. It stops, does not change your crontab, and writes the steps
below to adhan.log. Until you do these steps, the prayer times are not updated:
- Install uv (step 3 above).
- Install the library and run the script once. The run replaces the old jobs with jobs
that run
~/adhan/.venv/bin/python:
cd ~/adhan
uv sync
~/adhan/.venv/bin/python ~/adhan/updateAzaanTimers.pyType this command:
~/adhan/.venv/bin/python ~/adhan/updateAzaanTimers.py --lat <YOUR_LAT> --lon <YOUR_LNG> --method <METHOD>Replace the arguments with your location and your calculation method:
--latand--lon: the latitude and longitude of your location. The script uses them to calculate the prayer times.--method: the calculation method for the prayer times.
The script uses the timezone of the Raspberry Pi. Make sure that the timezone is correct.
| Method | Name | Parameters |
|---|---|---|
MWL |
Muslim World League | Fajr 18°, Isha 17° |
ISNA |
Islamic Society of North America (ISNA) | Fajr 15°, Isha 15° |
Egypt |
Egyptian General Authority of Survey | Fajr 19.5°, Isha 17.5° |
Makkah |
Umm Al-Qura University, Makkah | Fajr 18.5°, Isha 90 minutes after Maghrib |
Karachi |
University of Islamic Sciences, Karachi | Fajr 18°, Isha 18° |
Tehran |
Institute of Geophysics, University of Tehran | Fajr 17.7°, Isha 14°, Maghrib 4.5°, Jafari midnight |
Jafari |
Shia Ithna-Ashari, Leva Institute, Qum | Fajr 16°, Isha 14°, Maghrib 4°, Jafari midnight |
The script adds 2 minutes to the Maghrib time of each method. Most methods put Maghrib at
the sunset, and calculate the sunset as if the land at the horizon is at the height of
your eyes. When the land at the horizon is lower than your eyes, you see the sun for
longer, so the sun sets later. For example, the land around Bengaluru makes the sunset up
to 1 minute later. With the 2 minutes, the adhan does not play before the sun has set.
Tehran and Jafari put Maghrib later, when the sun is 4.5° or 4° below the horizon, so
for them the 2 minutes are only extra time.
The script rounds Maghrib to the nearest minute, and the adhan starts at the start of that minute. So the adhan plays 1.5 to 2.5 minutes after the time of the method. This is enough when your eyes are up to about 90 m above the land at your horizon in Bengaluru, and up to about 25 m in London. Far from the equator, the sun goes down more slowly, so the same minutes cover less height. If your home is higher, add an offset to Maghrib.
The 2 minutes are not a setting, and the script does not save them in adhan.toml. They
move Maghrib only. The Maghrib offset adds to them, so --maghrib-offset -2 gives the time
of the method.
If the script runs correctly, the output is similar to this. USER is your user name.
2026-05-15 12:00:00 Updating the prayer times
2026-05-15 12:00:00 ---------------------------------
2026-05-15 12:00:00 Co-ordinates provided
2026-05-15 12:00:00 ---------------------------------
2026-05-15 12:00:00 Latitude: 28.4792507
2026-05-15 12:00:00 Longitude: 77.535747
2026-05-15 12:00:00 Method: Karachi
2026-05-15 12:00:00 Asr school: Standard
2026-05-15 12:00:00 Player: vlc
2026-05-15 12:00:00 Lead-in: 0 seconds
2026-05-15 12:00:00 ---------------------------------
2026-05-15 12:00:00
2026-05-15 12:00:00 ---------------------------------
2026-05-15 12:00:00 Prayer Times
2026-05-15 12:00:00 ---------------------------------
2026-05-15 12:00:00 Fajr: 04:01 hrs
2026-05-15 12:00:00 Dhuhr: 12:16 hrs
2026-05-15 12:00:00 Asr: 15:50 hrs
2026-05-15 12:00:00 Maghrib: 19:05 hrs (2 safety minutes added)
2026-05-15 12:00:00 Isha: 20:32 hrs
2026-05-15 12:00:00 ---------------------------------
2026-05-15 12:00:00
2026-05-15 12:00:00 ---------------------------------
2026-05-15 12:00:00 Cron jobs scheduled
2026-05-15 12:00:00 ---------------------------------
2026-05-15 12:00:00 1 4 * * * /home/USER/adhan/playAzaan.sh /home/USER/adhan/media/Adhan-fajr.mp3 0 vlc >> /home/USER/adhan/adhan.log 2>&1 # rpiAdhanClockJob
2026-05-15 12:00:00 16 12 * * * /home/USER/adhan/playAzaan.sh /home/USER/adhan/media/Adhan-Makkah1.mp3 0 vlc >> /home/USER/adhan/adhan.log 2>&1 # rpiAdhanClockJob
2026-05-15 12:00:00 50 15 * * * /home/USER/adhan/playAzaan.sh /home/USER/adhan/media/Adhan-Makkah1.mp3 0 vlc >> /home/USER/adhan/adhan.log 2>&1 # rpiAdhanClockJob
2026-05-15 12:00:00 5 19 * * * /home/USER/adhan/playAzaan.sh /home/USER/adhan/media/Adhan-Makkah1.mp3 0 vlc >> /home/USER/adhan/adhan.log 2>&1 # rpiAdhanClockJob
2026-05-15 12:00:00 32 20 * * * /home/USER/adhan/playAzaan.sh /home/USER/adhan/media/Adhan-Makkah1.mp3 0 vlc >> /home/USER/adhan/adhan.log 2>&1 # rpiAdhanClockJob
2026-05-15 12:00:00 15 3 * * * /home/USER/adhan/.venv/bin/python /home/USER/adhan/updateAzaanTimers.py >> /home/USER/adhan/adhan.log 2>&1 # rpiAdhanClockJob
2026-05-15 12:00:00 @reboot /home/USER/adhan/.venv/bin/python /home/USER/adhan/updateAzaanTimers.py --wait-for-time-sync >> /home/USER/adhan/adhan.log 2>&1 # rpiAdhanClockJob
2026-05-15 12:00:00 ---------------------------------
2026-05-15 12:00:00 Script execution finished at: 2026-05-15 12:00:00.123456
The "Cron jobs scheduled" part shows the jobs that the script added to your crontab:
- The first 5 jobs play the 5 adhans at today's prayer times.
- After them, there is one job for each rule that is on. The first run has no rules.
- The
15 3 * * *job runs the script again at 03:15 every night. That run calculates the prayer times for the new day and replaces the adhan jobs. It also deletes the lines ofadhan.logthat are older than 30 days, so the log does not become too large. - The
@rebootjob runs the script each time the Raspberry Pi starts, because the Raspberry Pi can be off at 03:15. A Raspberry Pi has no clock battery, so this run first waits for the clock to synchronize, for a maximum of 15 minutes. If the clock does not synchronize, the run changes nothing, and the 03:15 run updates the times.
Each job ends with the comment # rpiAdhanClockJob. The script uses this comment to find
its own jobs. Each run removes all the jobs with this comment and adds the new jobs. Your
other cron jobs do not change. Do not add this comment to your own jobs.
The script saves its settings in ~/adhan/adhan.toml. For the next runs, you do not
have to give the arguments again. The nightly run uses the saved settings.
You are done. Connect your speakers and enjoy!
You can give each setting on the command line, or write it in adhan.toml. The script
uses the value from the command line first, then the value in adhan.toml, then the
default. You can give the optional settings in the first run or in a later run.
Each run writes all the settings to adhan.toml again, with the values from the command
line. Thus the nightly run uses them too. The comments in the file are lost.
After you edit adhan.toml, the new values apply at the next run. To apply them now,
run the script again without arguments:
~/adhan/.venv/bin/python ~/adhan/updateAzaanTimers.pyTo see all the arguments, type:
~/adhan/.venv/bin/python ~/adhan/updateAzaanTimers.py -hIf a value is not correct, the script stops and writes the reason to the output. It does
not change your crontab or adhan.toml. The adhan jobs of the last correct run stay. These
are not correct:
- A file that is not TOML. For example, a text must be in double
quotes:
method = "Karachi", notmethod = Karachi. - A table or a key that is not in the tables below, for example a key with a typo.
- A value of the wrong type, for example
volume = "0"orenabled = "true". A number has no quotes.trueandfalsehave no quotes. - A value that is not in the range of its setting, or an audio file that is not there.
This is the adhan.toml that the first run writes:
# The settings of the adhan clock. See README.md.
# updateAzaanTimers.py writes this file again on each run, so comments are lost.
[location]
lat = 28.4792507
lon = 77.535747
method = "Karachi"
asr = "Standard"
[audio]
player = "vlc"
leadin_seconds = 0
volume = 0
file = "Adhan-Makkah1.mp3"
[prayers.fajr]
file = "Adhan-fajr.mp3"
volume = 0
offset_minutes = 0
enabled = true
[prayers.dhuhr]
offset_minutes = 0
enabled = true
[prayers.asr]
offset_minutes = 0
enabled = true
[prayers.maghrib]
offset_minutes = 0
enabled = true
[prayers.isha]
offset_minutes = 0
enabled = trueOnly lat, lon and method are necessary. Each key that is not in the file has its
default value. For example, this file is also correct. It plays Fajr more quietly, plays
Maghrib 3 minutes later, turns off the Isha adhan and plays Surah Baqarah on Fridays at
07:00 (see Rules):
[location]
lat = 51.5072
lon = -0.1276
method = "MWL"
asr = "Hanafi"
[audio]
leadin_seconds = 2
[prayers.fajr]
volume = -1000
[prayers.maghrib]
offset_minutes = 3
[prayers.isha]
enabled = false
[[rule]]
name = "Surah Baqarah"
days = ["fri"]
at = "07:00"
file = "002-surah-baqarah-mishary.mp3"The tables of adhan.toml are:
[location]: the location, the calculation method and the Asr school.[audio]: the player, the lead-in, and the volume and file of each prayer that has no volume or file of its own.[prayers.fajr],[prayers.dhuhr],[prayers.asr],[prayers.maghrib]and[prayers.isha]: the settings of one prayer.[[rule]]: one rule, which plays a file at a time. There can be many rules. See Rules.
| Command line | adhan.toml |
Values |
|---|---|---|
--lat |
[location] lat |
A number from -90 to 90. Required on the first run. |
--lon |
[location] lon |
A number from -180 to 180. Required on the first run. |
--method |
[location] method |
One of the calculation methods, in quotes. Required on the first run. |
The Asr school sets the method for the Asr time. The Hanafi school gives a later Asr time.
| Command line | adhan.toml |
Values | Default |
|---|---|---|---|
--asr |
[location] asr |
"Standard" or "Hanafi" |
"Standard" |
For example:
~/adhan/.venv/bin/python ~/adhan/updateAzaanTimers.py --asr HanafiYou set the volume in millibels. 0 is the normal volume of the file. 1500 is loud.
-30000 is almost silent. The maximum gain is 8 times the normal volume (+18 dB).
| Command line | adhan.toml |
Applies to | Default |
|---|---|---|---|
--fajr-azaan-volume |
[prayers.fajr] volume |
Fajr | 0 |
--azaan-volume |
[audio] volume |
Each prayer that has no volume of its own | 0 |
| none | [prayers.dhuhr] volume, and the same for asr, maghrib and isha |
That prayer | The [audio] volume |
A volume is a whole number.
playAzaan.sh changes the millibels to the volume scale of the selected player. Thus the
same numbers work as they did with omxplayer.
An offset moves a prayer time by a number of minutes. A positive number makes the adhan later. A negative number makes it earlier. The Maghrib offset adds to the 2 safety minutes of Maghrib.
| Command line | adhan.toml |
Values | Default |
|---|---|---|---|
--fajr-offset, --dhuhr-offset, --asr-offset, --maghrib-offset, --isha-offset |
[prayers.fajr] offset_minutes, and the same for dhuhr, asr, maghrib and isha |
A whole number of minutes, for example 5 or -3 |
0 |
For example, this command plays the Isha adhan 10 minutes later:
~/adhan/.venv/bin/python ~/adhan/updateAzaanTimers.py --isha-offset 10You can turn the adhan of each prayer on or off. The script calculates the time of a prayer that is off, but it adds no job for that prayer. The output shows "(not scheduled)" after that prayer.
| Command line | adhan.toml |
Values | Default |
|---|---|---|---|
--play-fajr or --no-play-fajr, and the same for dhuhr, asr, maghrib and isha |
[prayers.fajr] enabled, and the same for dhuhr, asr, maghrib and isha |
true or false |
true |
For example, this command turns off the Fajr adhan:
~/adhan/.venv/bin/python ~/adhan/updateAzaanTimers.py --no-play-fajrYou can select the adhan file for each prayer. Give the name of a file in the media
directory, or the full path of a file. The media directory has these adhan files:
Adhan-fajr.mp3, Adhan-Madinah.mp3, Adhan-Makkah1.mp3, Adhan-Makkah1-Dua.mp3,
Adhan-Makkah2.mp3, Adhan-Makkah-Dua.mp3 and Adhan-Turkish.mp3.
| Command line | adhan.toml |
Applies to | Default |
|---|---|---|---|
--audio |
[audio] file |
Each prayer that has no file of its own | "Adhan-Makkah1.mp3" |
--fajr-audio |
[prayers.fajr] file |
Fajr | "Adhan-fajr.mp3" |
--dhuhr-audio, --asr-audio, --maghrib-audio, --isha-audio |
[prayers.dhuhr] file, and the same for asr, maghrib and isha |
That prayer | The [audio] file |
For example, this command plays Adhan-Madinah.mp3 for Isha:
~/adhan/.venv/bin/python ~/adhan/updateAzaanTimers.py --isha-audio Adhan-Madinah.mp3The script makes sure that the file of each prayer that is on is there and that it can read
the file. A file name must not contain %, # or a control character. In adhan.toml, put
the file name in double quotes. Write a \ in a file name as \\.
Some speakers go to sleep when they play no sound. Such a speaker can need some time to wake up, and then it does not play the start of the adhan. A lead-in plays seconds of silence before the adhan, so the speaker is awake when the adhan starts.
| Command line | adhan.toml |
Values | Default |
|---|---|---|---|
--leadin-seconds |
[audio] leadin_seconds |
A whole number from 0 to 10 |
0 (no silence) |
For example:
~/adhan/.venv/bin/python ~/adhan/updateAzaanTimers.py --leadin-seconds 2playAzaan.sh plays media/silence-1s.wav one time for each second. If that file is not
there, it plays the adhan without the lead-in. With a lead-in, each adhan job has one more
number after the player, for example ... 0 vlc 2 >> ....
A rule plays an audio file at a time that you select: a fixed time, or a time before or
after a prayer. A rule can play every day or only on some days. You write the rules in
adhan.toml. There is no command-line argument for them. Each rule starts with the line
[[rule]]:
[[rule]]
name = "Surah Baqarah"
days = ["fri"]
at = "07:00"
file = "002-surah-baqarah-mishary.mp3"
volume = 0
[[rule]]
name = "Surah Kahf"
days = ["fri"]
at = "dhuhr - 30min"
file = "018-kahf.mp3"
[[rule]]
name = "Evening dua"
at = "maghrib + 10min"
file = "dua.mp3"
enabled = false- The first rule plays Surah Al-Baqarah every Friday at 07:00. The
mediadirectory has this file. - The second rule plays Surah Al-Kahf every Friday, 30 minutes before Dhuhr.
- The third rule plays a dua every day, 10 minutes after Maghrib. It is off.
018-kahf.mp3 and dua.mp3 are examples. They are not in the media directory. Before you
use these rules, put your files in the media directory.
| Key | Required | Values | Default |
|---|---|---|---|
name |
Yes | A name on one line. Each rule must have a different name. The output of the script shows it. | |
at |
Yes | A fixed time, "HH:MM", for example "07:00". Or a time before or after a prayer, "<prayer> - <N>min" or "<prayer> + <N>min", for example "dhuhr - 30min". The prayer is fajr, sunrise, dhuhr, asr, maghrib or isha. |
|
days |
No | A list of days: "mon", "tue", "wed", "thu", "fri", "sat", "sun". For example ["fri"] or ["sat", "sun"]. |
Every day |
file |
Yes | The name of a file in the media directory, or the full path of a file, the same as an adhan file. |
|
volume |
No | A whole number of millibels, the same as the adhan volume. | The [audio] volume |
enabled |
No | true or false. A rule that is off has no job. |
true |
A rule plays its file in the same way as an adhan: with playAzaan.sh, the selected
player and lead-in, and the
hooks.
A time before or after a prayer starts from the time of the adhan of that prayer. Thus it includes the offset of that prayer, and for Maghrib the 2 safety minutes. It is also correct for a prayer that is off. Sunrise has no adhan and no offset. Each night, the script calculates the time again, as it does for the adhan.
The script stops and changes nothing if a rule is not correct, for example:
- A key is not in the table above, or a value has the wrong type.
atis not a correct time, or it has an unknown prayer.- A day is not in the list above.
- Two rules have the same name.
- The file of a rule that is on is not there, or the script cannot read it.
- A time before or after a prayer is before 00:00 or after 23:59. A rule plays on the same day as its prayer.
Each rule that is on has one job in the crontab. The job plays only on the days of the rule. For example, the Surah Baqarah rule gives this job:
0 7 * * 5 /home/USER/adhan/playAzaan.sh /home/USER/adhan/media/002-surah-baqarah-mishary.mp3 0 vlc >> /home/USER/adhan/adhan.log 2>&1 # rpiAdhanClockJob
The script runs each night at 03:15. A job at a time before 03:15 plays after the next midnight, before the next run. Cron checks the day when it plays the job, so the rule plays on its own days only. The time of a rule before or after a prayer comes from the last run, the same as the time of the adhan. Thus a rule "fajr - 150min" at 03:01 on a Friday has the time of Thursday's Fajr. A prayer time changes by approximately 1 minute or less in one day. After a reboot, the script runs again and gives the same jobs.
Before #43, Surah Baqarah had its own
table in adhan.toml, [surah_baqarah]. The script does not read this table now. If
your adhan.toml has it, the script stops and changes nothing. The output gives the rule
that you must write in place of the table. For example, replace:
[surah_baqarah]
enabled = true
volume = 0with:
[[rule]]
name = "Surah Baqarah"
days = ["fri"]
at = "07:00"
file = "002-surah-baqarah-mishary.mp3"
volume = 0If the table had enabled = false, delete it, or add enabled = false to the rule.
The adhan can play through VLC (cvlc) or the PulseAudio paplay. VLC is the default.
| Command line | adhan.toml |
Values | Default |
|---|---|---|---|
--player |
[audio] player |
"vlc" or "paplay" |
"vlc" |
For example:
~/adhan/.venv/bin/python ~/adhan/updateAzaanTimers.py --player paplayYou must install only the selected player. Each run of updateAzaanTimers.py makes sure
that the selected player is on PATH. If it is not, the script stops and writes the reason
to adhan.log. It does not change to the other player. To read MP3 files, paplay also
needs libsndfile 1.1 or newer. The script also makes sure of this.
Cron does not start the player directly. Each adhan job runs playAzaan.sh. This script:
- Runs each executable script in
before-hooks.d/. - Plays the lead-in of silence, if there is one.
- Plays the audio with the selected player (
cvlc --play-and-exitorpaplay) at the configured volume. - Runs each executable script in
after-hooks.d/.
You can play a file manually in the same way as the jobs do. The arguments are the file, the volume in millibels, the player and the lead-in in seconds. The last 3 arguments are optional:
cd ~/adhan
./playAzaan.sh media/Adhan-Makkah1.mp3 0 vlcSometimes you must run commands before the adhan, after the adhan, or both. For example, if you have Quran playing continuously, you can pause the Quran before the adhan and resume it after the adhan. Other examples are to set your status on a social network or a calendar, or to block and unblock the Internet with Pi-hole rules.
To do this, add scripts to these directories:
before-hooks.d: scripts that run before the adhan.after-hooks.d: scripts that run after the adhan.
The scripts run in alphabetical order. If a script fails, the adhan still plays.
To pause and resume the Quran with the RPi_QuranSpeaker project, add these 2 new files to the 2 directories. Change the path if you installed RPi_QuranSpeaker in a different directory:
# before-hooks.d/01-pause-quran-speaker.sh
#!/usr/bin/env bash
"$HOME/RPi_QuranSpeaker/pauser.py" pause# after-hooks.d/01-resume-quran-speaker.sh
#!/usr/bin/env bash
"$HOME/RPi_QuranSpeaker/pauser.py" resumeMake the scripts executable. A script that is not executable does not run:
cd ~/adhan
chmod u+x ./before-hooks.d/01-pause-quran-speaker.sh
chmod u+x ./after-hooks.d/01-resume-quran-speaker.sh- To see your scheduled jobs, type
crontab -l. - All the jobs write their output to
~/adhan/adhan.log. Use the log to make sure that each run was successful and to find problems. Each adhan writes a line when it starts and a line when it ends, with the errors from the player. Each line starts with the date and time. The log keeps the lines of the last 30 days. To see the log, typecat ~/adhan/adhan.log.
The tests use only python-crontab and the Python standard library. They do not change your
crontab, adhan.toml or adhan.log, and they do not play audio. To run them, type:
cd ~/adhan
uv run python -m unittest discover testsThis repository is the maintained fork of achaudhry/adhan. That project used these as a starting point:
- Python code to calculate the adhan times: http://praytimes.org/code/
- Basic code to make an adhan clock from the code above: http://randomconsultant.blogspot.co.uk/2013/07/turn-your-raspberry-pi-into-azaanprayer.html
- Cron scheduler: https://pypi.python.org/pypi/python-crontab/
See the PrayTimes manual for more information about the calculation of the prayer times.