Keeping your website online 24/7 is crucial for user trust, SEO rankings, and revenue. Yet, even the most robust hosting providers can experience occasional outages that go unnoticed until customers start complaining. That’s where a Python automated website uptime monitor comes in handy—offering real‑time alerts, detailed logs, and the peace of mind that your digital storefront is always reachable. In this guide, we’ll walk through the core concepts, essential libraries, and step‑by‑step code to build a reliable uptime monitoring script that you can run on any server or even your local machine.
Why Choose Python for Uptime Monitoring?
Python’s readability, extensive ecosystem, and cross‑platform compatibility make it an ideal choice for building monitoring tools. With just a few lines of code, you can:
- Send HTTP requests and check response status codes.
- Schedule recurring checks without a heavyweight cron configuration.
- Integrate with popular notification services (email, Slack, SMS).
- Store logs in CSV, JSON, or a lightweight SQLite database.
All of these capabilities are available through well‑maintained packages like requests, schedule, and smtplib, keeping your solution lightweight and easy to maintain.
Core Components of an Automated Uptime Monitor
1. URL List Management
The monitor needs a source of URLs to check. You can store them in a simple text file, a JSON configuration, or a database. For most small‑to‑medium projects, a JSON file offers a good balance between readability and flexibility.
2. HTTP Request and Validation
Using the requests library, you can send a GET request to each URL and evaluate the HTTP status code. A response in the 200–299 range typically indicates a healthy site, while anything else should trigger an alert.
3. Scheduling Checks
Instead of relying on system cron jobs, the schedule library lets you define human‑readable intervals directly in Python. This keeps the entire monitoring logic in one place and simplifies deployment on platforms that restrict cron access.
4. Notification System
When a website goes down, you want to be notified instantly. Common channels include:
- Email: Using
smtplibor third‑party services like SendGrid. - Slack: Posting to a webhook URL.
- SMS: Via Twilio or similar APIs.
Choose the channel that best fits your team’s workflow.
Step‑by‑Step Implementation
Prerequisites
Make sure you have Python 3.8+ installed and run the following command to install required packages:
pip install requests schedule
Project Structure
uptime_monitor/
│
├─ config.json # List of URLs and optional settings
├─ monitor.py # Main script
└─ logs/
└─ uptime_log.csv # Log file (auto‑generated)
Sample config.json
{
"sites": [
{
"url": "https://example.com",
"name": "Main Site"
},
{
"url": "https://api.example.com/health",
"name": "API Endpoint"
}
],
"check_interval_minutes": 5,
"alert": {
"email": "admin@example.com",
"slack_webhook": "https://hooks.slack.com/services/XXXX/XXXX/XXXX"
}
}
Full monitor.py Script
import json
import csv
import smtplib
import requests
import schedule
import time
from datetime import datetime
from email.mime.text import MIMEText
from pathlib import Path
# Load configuration
CONFIG_PATH = Path(__file__).parent / 'config.json'
with open(CONFIG_PATH, 'r') as f:
config = json.load(f)
LOG_FILE = Path(__file__).parent / 'logs' / 'uptime_log.csv'
LOG_FILE.parent.mkdir(parents=True, exist_ok=True)
def send_email(subject: str, body: str):
"""Send a simple email alert using localhost SMTP."""
msg = MIMEText(body)
msg['Subject'] = subject
msg['From'] = 'monitor@example.com'
msg['To'] = config['alert']['email']
with smtplib.SMTP('localhost') as server:
server.send_message(msg)
def send_slack(message: str):
"""Post a message to a Slack webhook."""
webhook_url = config['alert'].get('slack_webhook')
if not webhook_url:
return
payload = {'text': message}
requests.post(webhook_url, json=payload)
def log_result(site_name: str, url: str, status: str, response_time: float):
"""Append a single check result to the CSV log."""
now = datetime.utcnow().isoformat()
with open(LOG_FILE, 'a', newline='') as csvfile:
writer = csv.writer(csvfile)
writer.writerow([now, site_name, url, status, f"{response_time:.2f}"])
def check_site(site):
"""Perform a single HTTP GET request and handle the outcome."""
url = site['url']
name = site.get('name', url)
start = time.time()
try:
response = requests.get(url, timeout=10)
elapsed = time.time() - start
if 200 <= response.status_code < 300:
status = 'UP'
else:
status = f'DOWN (HTTP {response.status_code})'
except requests.RequestException as e:
elapsed = time.time() - start
status = f'DOWN ({e.__class__.__name__})'
# Log every attempt
log_result(name, url, status, elapsed)
# Notify only on failures
if status.startswith('DOWN'):
alert_msg = f"[{datetime.utcnow().isoformat()}] {name} is down!\nURL: {url}\nStatus: {status}"
send_email(f"⚠️ {name} is DOWN", alert_msg)
send_slack(alert_msg)
def run_checks():
"""Iterate over all configured sites and check each one."""
for site in config['sites']:
check_site(site)
# Schedule the job based on the interval defined in config
interval = config.get('check_interval_minutes', 5)
schedule.every(interval).minutes.do(run_checks)
# Initial run
run_checks()
# Keep the script alive
while True:
schedule.run_pending()
time.sleep(1)
Explanation of Key Sections
- Configuration Loading: Reads
config.jsonso you can add or remove sites without touching the code. - Logging: Each check is appended to
uptime_log.csvwith a UTC timestamp, making it easy to generate uptime reports later. - Alerting: The script sends both email and Slack notifications when a site is unreachable or returns an unexpected status code.
- Scheduling: The
schedulelibrary runsrun_checks()every N minutes as defined in the config.
Deploying the Monitor in Production
Running as a Background Service
On Linux, you can use systemd to keep the script alive across reboots:
[Unit]
Description=Python Website Uptime Monitor
After=network.target
[Service]
User=youruser
WorkingDirectory=/path/to/uptime_monitor
ExecStart=/usr/bin/python3 monitor.py
Restart=always
[Install]
WantedBy=multi-user.target
Save this as /etc/systemd/system/uptime-monitor.service, then enable it with systemctl enable --now uptime-monitor.
Containerizing with Docker
If you prefer an isolated environment, a minimal Dockerfile does the trick:
FROM python:3.12-slim
WORKDIR /app
COPY . .
RUN pip install --no-cache-dir requests schedule
CMD ["python", "monitor.py"]
Build and run the container, mapping a volume for the logs/ directory so you can access the CSV file from the host.
Extending the Monitor for Advanced Use Cases
- Response Time Thresholds: Add logic to flag sites that respond slowly, not just those that are down.
- Historical Dashboards: Feed the CSV data into Grafana or Power BI for visual uptime charts.
- Multi‑Region Checks: Deploy the script on servers in different geographic locations to detect regional outages.
- HTTPS Certificate Monitoring: Use
sslmodule to verify certificate expiry dates.
Best Practices for Reliable Monitoring
Even the best script can produce false alarms if not tuned correctly. Follow these guidelines to keep your alerts meaningful:
- Set Reasonable Timeouts: A
Leave a Reply