Keeping a website online is a non‑negotiable requirement for businesses, bloggers, and developers alike. Even a few minutes of downtime can translate into lost revenue, damaged reputation, and frustrated users. While many commercial services offer uptime monitoring, building a Python automated website uptime monitor gives you full control, zero recurring costs, and a great learning opportunity. In this guide we’ll walk through the why, what, and how of creating a reliable, customizable monitor that checks your sites, logs results, and sends instant alerts—all using plain Python and a handful of popular libraries.
Why Build Your Own Uptime Monitor?
Before diving into code, it’s worth understanding the benefits of a DIY solution:
- Cost‑effective: No subscription fees, only the cost of the server or VPS you already own.
- Full customization: Tailor the frequency, timeout thresholds, and alert channels (email, Slack, SMS, etc.) to match your exact needs.
- Learning experience: Gain hands‑on knowledge of HTTP requests, scheduling, logging, and error handling in Python.
- Data ownership: Store logs and metrics in your own database or file system, ensuring privacy and compliance.
Core Components of a Python Uptime Monitor
A robust monitor typically consists of four building blocks:
- HTTP request engine – Sends a GET request to each target URL and records the response status.
- Scheduler – Triggers the checks at regular intervals (e.g., every minute).
- Logging & persistence – Stores results for historical analysis and reporting.
- Alerting system – Notifies you immediately when a site becomes unreachable or returns an unexpected status code.
Choosing the Right Libraries
Python’s ecosystem offers several mature libraries that make each component painless:
requests– Simple, human‑readable HTTP client.httpx– Async‑ready alternative if you need high concurrency.schedule– Human‑friendly job scheduler for lightweight scripts.APScheduler– More powerful, supports cron‑style expressions and background threads.logging– Built‑in module for structured log output.smtplibor third‑party services (Twilio, Slack webhook) – For sending alerts.
Step‑by‑Step Implementation
1. Set Up the Project Structure
Organize your files for clarity and future expansion:
uptime-monitor/
│
├─ config.yaml # List of URLs, thresholds, and alert settings
├─ monitor.py # Main script that runs the scheduler
├─ logger.py # Helper for file/console logging
└─ alerts.py # Functions to send email, Slack, etc.
2. Define Configuration in YAML
Keeping URLs and thresholds outside the code makes updates painless. Example config.yaml:
sites:
- url: https://example.com
expected_status: 200
timeout_seconds: 5
- url: https://api.myservice.io/health
expected_status: 200
timeout_seconds: 3
schedule:
interval_minutes: 1
alerts:
email:
enabled: true
smtp_server: smtp.gmail.com
smtp_port: 587
username: your.email@gmail.com
password: your_app_password
recipients:
- admin@example.com
slack:
enabled: false
webhook_url: https://hooks.slack.com/services/...
3. Build the HTTP Check Function
This function performs the actual request and returns a structured result.
import requests
from datetime import datetime
def check_site(url, expected_status=200, timeout=5):
try:
response = requests.get(url, timeout=timeout)
status_ok = response.status_code == expected_status
return {
"url": url,
"timestamp": datetime.utcnow().isoformat(),
"status_code": response.status_code,
"ok": status_ok,
"response_time_ms": int(response.elapsed.total_seconds() * 1000)
}
except requests.RequestException as e:
return {
"url": url,
"timestamp": datetime.utcnow().isoformat(),
"status_code": None,
"ok": False,
"error": str(e)
}
4. Implement Logging
A simple logger that writes JSON lines to uptime.log keeps the file lightweight and easy to parse later.
import logging
import json
logger = logging.getLogger("uptime")
logger.setLevel(logging.INFO)
handler = logging.FileHandler("uptime.log")
handler.setFormatter(logging.Formatter("%(message)s"))
logger.addHandler(handler)
def log_result(result):
logger.info(json.dumps(result))
5. Create Alert Functions
Below is a minimal email alert. You can extend it with Slack, SMS, or PagerDuty.
import smtplib
from email.mime.text import MIMEText
from pathlib import Path
import yaml
def load_alert_config():
cfg = yaml.safe_load(Path("config.yaml").read_text())
return cfg["alerts"]["email"]
def send_email(subject, body):
cfg = load_alert_config()
if not cfg["enabled"]:
return
msg = MIMEText(body, "plain")
msg["Subject"] = subject
msg["From"] = cfg["username"]
msg["To"] = ", ".join(cfg["recipients"])
with smtplib.SMTP(cfg["smtp_server"], cfg["smtp_port"]) as server:
server.starttls()
server.login(cfg["username"], cfg["password"])
server.send_message(msg)
6. Tie Everything Together with a Scheduler
The schedule library offers a readable syntax. For production you might switch to APScheduler to survive process restarts.
import yaml
import schedule
import time
def load_sites():
cfg = yaml.safe_load(Path("config.yaml").read_text())
return cfg["sites"]
def monitor_job():
for site in load_sites():
result = check_site(
url=site["url"],
expected_status=site.get("expected_status", 200),
timeout=site.get("timeout_seconds", 5)
)
log_result(result)
if not result["ok"]:
subject = f"⚠️ Site Down: {result['url']}"
body = (
f"Timestamp: {result['timestamp']}\n"
f"URL: {result['url']}\n"
f"Error: {result.get('error', 'Unexpected status ' + str(result['status_code']))}\n"
)
send_email(subject, body)
def start_scheduler():
cfg = yaml.safe_load(Path("config.yaml").read_text())
interval = cfg["schedule"]["interval_minutes"]
schedule.every(interval).minutes.do(monitor_job)
print(f"✅ Python uptime monitor started – checking every {interval} minute(s).")
while True:
schedule.run_pending()
time.sleep(1)
if __name__ == "__main__":
start_scheduler()
Running the Monitor as a Service
For continuous operation, run the script as a systemd service (Linux) or a Windows Service. Example systemd unit:
[Unit]
Description=Python Website Uptime Monitor
After=network.target
[Service]
User=monitor
WorkingDirectory=/opt/uptime-monitor
ExecStart=/usr/bin/python3 monitor.py
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
Enable and start the service:
sudo systemctl daemon-reload
sudo systemctl enable uptime-monitor
sudo systemctl start uptime-monitor
Enhancing the Monitor for Production Use
Once the basic version is stable, consider adding these advanced features:
- Concurrency: Switch to
httpx.AsyncClientwithasyncioto check dozens of URLs in parallel without blocking. - Database storage: Persist results in PostgreSQL or InfluxDB for richer analytics and Grafana dashboards.
- Historical reporting: Generate daily/weekly uptime percentages, mean time to recovery (MTTR), and trend graphs.
- Dynamic configuration: Expose a tiny Flask or FastAPI endpoint to add/remove URLs without editing YAML.
- Health checks for the monitor itself: Ensure the script is alive by exposing a `/ping` endpoint monitored by an external service.
SEO Tips Embedded in This Post
When you publish a tutorial like this, remember to optimize for search engines:
- Use the exact phrase Python automated website uptime monitor in the title, headings, and first 100 words.
- Include related keywords such as “website uptime monitoring”, “Python script”, “monitoring script”, “alerting”, and “systemd service”.
- Add a concise meta description (≈155 characters) that mentions the main benefit: “Learn how to build a free, Python‑based website uptime monitor that logs results and sends instant alerts.”
- Structure the article with clear
<h2>and<h3>tags, and use bullet points for readability—both improve dwell time. - Provide a downloadable
.zipor GitHub link
Leave a Reply