Python Automated Website Uptime Monitor

Written by

in

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:

  1. HTTP request engine – Sends a GET request to each target URL and records the response status.
  2. Scheduler – Triggers the checks at regular intervals (e.g., every minute).
  3. Logging & persistence – Stores results for historical analysis and reporting.
  4. 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.
  • smtplib or 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.AsyncClient with asyncio to 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 .zip or GitHub link

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *