Python Automated Website Uptime Monitor

Written by

in

Keeping a website online 24/7 is no longer a luxury—it’s a business requirement. Even a few minutes of downtime can cost you visitors, revenue, and credibility. Fortunately, with just a few lines of Python you can build an automated uptime monitor that checks your sites, records response times, and sends instant alerts the moment something goes wrong. In this guide we’ll explore why uptime matters, break down the core concepts of monitoring, walk through a complete Python script, and show you how to scale the solution for dozens or hundreds of URLs—all while staying SEO‑friendly and easy to maintain.

Why Website Uptime Matters

Business Impact

Every second your site is unavailable, you risk:

  • Lost sales – e‑commerce sites see a direct hit to revenue.
  • Damaged brand reputation – users remember downtime more than they remember a fast page load.
  • Reduced SEO rankings – search engines penalize sites with frequent outages.

Technical Reasons

Beyond the business side, uptime is a key indicator of:

  • Server health and resource usage.
  • Network reliability and DNS configuration.
  • Application stability after deployments.

Core Concepts of an Automated Uptime Monitor

Ping vs. HTTP Check

A simple ping tells you whether a server is reachable at the network layer, but it won’t verify that your web application is serving content correctly. An HTTP check performs a real request to a URL, validates the status code, and can even inspect the response body for expected keywords.

Response Time Metrics

Uptime is binary—up or down—but performance matters too. Recording the latency of each request lets you spot slowdowns before they become full outages. Over time you can build a baseline and set alerts for deviations.

Building a Simple Python Uptime Monitor

Prerequisites

  • Python 3.8+ installed on your server or workstation.
  • The requests library for HTTP calls (pip install requests).
  • Optional: smtplib for email alerts, json for configuration.

Step‑by‑Step Code Walkthrough

Below is a minimal yet functional script that checks a list of URLs, logs the result, and sends an email when a site is down.

import json
import smtplib
import time
from email.mime.text import MIMEText
from pathlib import Path

import requests

# ------------------- Configuration -------------------
CONFIG_PATH = Path('sites.json')   # JSON file with URLs to monitor
LOG_PATH = Path('uptime.log')      # Simple text log
CHECK_INTERVAL = 60                # seconds between checks
TIMEOUT = 10                       # request timeout in seconds

SMTP_SERVER = 'smtp.example.com'
SMTP_PORT = 587
SMTP_USER = 'alert@example.com'
SMTP_PASS = 'yourpassword'
ALERT_RECIPIENT = 'admin@example.com'
# ----------------------------------------------------


def load_sites():
    """Load the list of URLs from a JSON file."""
    if not CONFIG_PATH.exists():
        raise FileNotFoundError(f'Config file {CONFIG_PATH} not found')
    with CONFIG_PATH.open() as f:
        return json.load(f)


def log_result(url, status, latency):
    """Append a timestamped entry to the log file."""
    timestamp = time.strftime('%Y-%m-%d %H:%M:%S')
    LOG_PATH.write_text('', encoding='utf-8')  # ensure file exists
    with LOG_PATH.open('a') as log:
        log.write(f'{timestamp} | {url} | {status} | {latency:.2f}s\\n')


def send_alert(url, error):
    """Send a simple email alert when a site is down."""
    subject = f'⚠️ Uptime Alert: {url} is DOWN'
    body = f'''The monitor detected a problem with {url}.

Error: {error}
Time: {time.strftime('%Y-%m-%d %H:%M:%S')}

Please investigate immediately.'''
    msg = MIMEText(body)
    msg['Subject'] = subject
    msg['From'] = SMTP_USER
    msg['To'] = ALERT_RECIPIENT

    with smtplib.SMTP(SMTP_SERVER, SMTP_PORT) as server:
        server.starttls()
        server.login(SMTP_USER, SMTP_PASS)
        server.send_message(msg)


def check_site(url):
    """Perform an HTTP GET request and return status & latency."""
    start = time.time()
    try:
        response = requests.get(url, timeout=TIMEOUT)
        latency = time.time() - start
        status = 'UP' if response.status_code == 200 else f'DOWN ({response.status_code})'
        return status, latency
    except requests.RequestException as e:
        latency = time.time() - start
        return f'DOWN ({e.__class__.__name__})', latency


def main():
    sites = load_sites()
    while True:
        for url in sites:
            status, latency = check_site(url)
            log_result(url, status, latency)
            if not status.startswith('UP'):
                send_alert(url, status)
        time.sleep(CHECK_INTERVAL)


if __name__ == '__main__':
    main()

Save the above as monitor.py and create a sites.json file with a simple array of URLs, e.g., ["https://example.com", "https://api.example.com/health"]. The script logs every check to uptime.log and emails you whenever a site returns a non‑200 status or raises an exception.

Adding Alerts and Notifications

Email via SMTP

The built‑in smtplib example works for most providers, but you may want to use a service like SendGrid or Amazon SES for higher deliverability. Just replace the SMTP block with the provider’s API call.

Slack Webhook Integration

For teams that live in Slack, a quick webhook post can replace email:

import requests

SLACK_WEBHOOK = 'https://hooks.slack.com/services/XXXXX/XXXXX/XXXXX'

def send_slack_alert(url, error):
    payload = {
        "text": f":warning: *Uptime Alert*: {url} is down – {error}"
    }
    requests.post(SLACK_WEBHOOK, json=payload)

Call send_slack_alert() inside check_site() whenever a failure occurs.

SMS with Twilio

If you need instant mobile alerts, Twilio’s REST API is straightforward:

from twilio.rest import Client

TWILIO_SID = 'ACXXXXXXXXXXXXXXXXX'
TWILIO_TOKEN = 'your_auth_token'
FROM_NUMBER = '+1234567890'
TO_NUMBER = '+1987654321'

client = Client(TWILIO_SID, TWILIO_TOKEN)

def send_sms_alert(url, error):
    message = f'Uptime Alert: {url} is down – {error}'
    client.messages.create(body=message, from_=FROM_NUMBER, to=TO_NUMBER)

Running the Monitor Continuously

Using cron

If you prefer a simple approach, schedule the script to run every minute with a cron entry:

* * * * * /usr/bin/python3 /path/to/monitor.py >> /var/log/uptime_monitor.log 2>&1

This method spawns a new process each minute, which is fine for small lists but can become inefficient at scale.

Using systemd Service

For a more robust solution, create a systemd service that keeps the script alive, restarts on failure, and writes logs to journalctl:

[Unit]
Description=Python Website Uptime Monitor
After=network.target

[Service]
ExecStart=/usr/bin/python3 /opt/monitor/monitor.py
Restart=always
User=monitor
Group=monitor
Environment=PYTHONUNBUFFERED=1

[Install]
WantedBy=multi-user.target

Enable and start with:

sudo systemctl enable uptime-monitor.service
sudo systemctl start uptime-monitor.service

Scaling Up: From One Site to Hundreds

Configuration File

Instead of a flat JSON array, use a richer structure that includes expected status codes, custom headers, and alert thresholds:

[
{
"url": "https://example.com",
"expected_status": 200,
"max_latency": 2.5,
"notify": ["email", "slack"]
},
{
"url": "https://api.example.com

Comments

Leave a Reply

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