Query your system's time synchronization status from Python. PyChrony provides bindings for chrony, the default NTP (Network Time Protocol) client on most Linux distributions, letting you monitor clock accuracy, sync status, and time sources programmatically.
- Read-only monitoring: Access tracking (offset, drift, stratum), sources (NTP servers, peers), statistics (samples, deviation), and RTC data
- Pythonic API: Clean, typed interface following Python conventions
- CFFI binding: Efficient interface to libchrony
- Linux-first: Optimized for Linux environments with libchrony
- Type hints: Full type annotation support for better IDE integration
pip install pychronyPre-built wheels include libchrony—no system dependencies needed.
Building from Source
Source installs (sdist or development) require libchrony to be installed on your system.
| Distribution | Available | Install Command |
|---|---|---|
| Fedora 42+ | ✅ Yes | sudo dnf install libchrony-devel |
| RHEL/CentOS/Rocky/Alma 9 | ✅ Yes (EPEL) | sudo dnf install epel-release && sudo dnf install libchrony-devel |
| Debian/Ubuntu | ❌ No | Build from source (see below) |
| Alpine | ❌ No | Build from source (see below) |
| Arch Linux | ❌ No | Build from source (see below) |
# Install build dependencies
# Debian/Ubuntu:
sudo apt-get install build-essential libtool libffi-dev
# Alpine:
sudo apk add gcc make libtool libffi-dev musl-dev
# Arch:
sudo pacman -S base-devel libtool libffi
# Clone and build libchrony
git clone https://gitlab.com/chrony/libchrony.git
cd libchrony
make
sudo make install prefix=/usr
sudo ldconfiggit clone https://github.com/arunderwood/pychrony.git
cd pychrony
git submodule update --init
uv sync --all-groups
uv pip install -e .from pychrony import ChronyConnection
with ChronyConnection() as conn:
status = conn.get_tracking()
print(f"Reference: {status.reference_id_name}")
print(f"Stratum: {status.stratum}")
print(f"Offset: {status.offset:.9f} seconds")
print(f"Synchronized: {status.is_synchronized()}")With no argument, pychrony tries chronyd's Unix socket and then its localhost command port, using the first that connects — the same candidates chronyc uses.
The two are not equivalent in privilege. The Unix socket is chronyd's control
channel, restricted to the root or chrony user; the command port serves
monitoring commands only, which is everything pychrony reads. Read-only
consumers should prefer the command port and can require it:
from pychrony import ChronyConnection, Transport
with ChronyConnection() as conn:
assert conn.transport is Transport.COMMAND_PORT
status = conn.get_tracking()Note that joining the chrony group does not grant access to the Unix
socket. See Choosing a Transport
for details.
- Python: 3.10, 3.11, 3.12, 3.13, 3.14, 3.15
- Platform: Linux (primary), other platforms where libchrony is available
- chrony: 4.x and later
- Documentation — Full API reference and guides
- GitHub Issues — Report bugs or request features
- chrony documentation — Understanding NTP and chrony
PyChrony is licensed under MIT. See LICENSE.
Pre-built wheels bundle libchrony which is licensed under LGPL-2.1-or-later. See LICENSES/LGPL-2.1-or-later.txt.