Python Automated Website Uptime Monitor

Written by

in

Keeping a website online is crucial for businesses, bloggers, and anyone who relies on a digital presence. Even a few minutes of downtime can mean lost revenue, damaged reputation, and frustrated users. Fortunately, with a few lines of Python code you can build an automated uptime monitor that checks your site every minute, logs results, and instantly notifies you when something goes wrong. In this guide we’ll explore why uptime monitoring matters, break down the essential components of a Python‑based solution, and walk you through a complete, production‑ready script you can deploy today.

Why Monitor Website Uptime?

Understanding the value of continuous monitoring helps you choose the right tools and set realistic expectations.

  • Customer trust: Visitors expect a site to be available 24/7. Unexpected outages erode confidence.
  • Revenue protection: E‑commerce platforms lose sales the moment a checkout page goes down.
  • SEO impact: Search engines penalize sites with frequent downtime, lowering organic rankings.
  • Rapid incident response: Automated alerts let you react within seconds instead of hours.

Core Components of a Python Uptime Monitor

A reliable monitor consists of four main building blocks that work together seamlessly.

1. HTTP Request Handling

The heart of any uptime check is a request to the target URL. Python’s requests library provides a simple, human‑readable API for sending GET requests and handling timeouts, redirects, and SSL verification.

2. Scheduling Checks

To run checks at regular intervals you can use:

  • time.sleep() in a simple loop for quick scripts.
  • schedule library for readable cron‑like syntax.
  • System‑level cron jobs or Windows Task Scheduler for production deployments.

3. Alerting Mechanisms

When a check fails, the monitor should notify you via one or more channels:

  • Email: SMTP integration with smtplib.
  • SMS/WhatsApp: APIs such as Twilio or Vonage.
  • ChatOps: Slack, Microsoft Teams, or Discord webhooks.
  • Push notifications: Services like Pushover or Pushbullet.

4. Logging and Persistence

Keeping a historical record of uptime and downtime helps you spot patterns and generate reports. Use:

  • Plain text or CSV files for lightweight storage.
  • SQLite or PostgreSQL for structured, queryable logs.
  • Cloud logging services (e.g., AWS CloudWatch) for centralized monitoring.

Step‑by‑Step Guide to Build Your Own Monitor

Below is a complete example that ties all the components together. Feel free to adapt it to your preferred alert channels or data stores.

  1. Install required packages

    pip install requests schedule python-dotenv

    The python-dotenv package lets you keep credentials (SMTP password, API keys) out of the source code.

  2. Create a .env file

    # .env
    TARGET_URL=https://example.com
    CHECK_INTERVAL=5   # minutes
    SMTP_SERVER=smtp.gmail.com
    SMTP_PORT=587
    SMTP_USER=youremail@gmail.com
    SMTP_PASS=your_app_password
    ALERT_RECIPIENT=admin@example.com
  3. Write the monitoring script

    import os
    import smtplib
    import logging
    from email.mime.text import MIMEText
    from datetime import datetime
    from pathlib import Path
    
    import requests
    import schedule
    from dotenv import load_dotenv
    
    # Load environment variables
    load_dotenv()
    
    TARGET_URL = os.getenv('TARGET_URL')
    INTERVAL = int(os.getenv('CHECK_INTERVAL', 5))
    SMTP_SERVER = os.getenv('SMTP_SERVER')
    SMTP_PORT = int(os.getenv('SMTP_PORT', 587))
    SMTP_USER = os.getenv('SMTP_USER')
    SMTP_PASS = os.getenv('SMTP_PASS')
    ALERT_RECIPIENT = os.getenv('ALERT_RECIPIENT')
    
    # Configure logging
    log_file = Path('uptime_log.csv')
    if not log_file.exists():
        log_file.write_text('timestamp,status_code,response_time,remark\n')
    
    logging.basicConfig(level=logging.INFO,
                        format='%(asctime)s %(levelname)s %(message)s',
                        handlers=[logging.StreamHandler()])
    
    
    def send_alert(subject: str, body: str):
        """Send an email alert using SMTP."""
        msg = MIMEText(body)
        msg['Subject'] = subject
        msg['From'] = SMTP_USER
        msg['To'] = ALERT_RECIPIENT
    
        try:
            with smtplib.SMTP(SMTP_SERVER, SMTP_PORT) as server:
                server.starttls()
                server.login(SMTP_USER, SMTP_PASS)
                server.send_message(msg)
            logging.info('Alert sent to %s', ALERT_RECIPIENT)
        except Exception as e:
            logging.error('Failed to send alert: %s', e)
    
    
    def check_website():
        """Perform a single uptime check and log the result."""
        try:
            start = datetime.utcnow()
            response = requests.get(TARGET_URL, timeout=10)
            elapsed = (datetime.utcnow() - start).total_seconds()
            status = response.status_code
            remark = 'OK' if status == 200 else f'Unexpected status {status}'
            logging.info('Checked %s - %s (%.2fs)', TARGET_URL, remark, elapsed)
    
            # Write to CSV log
            with open(log_file, 'a') as f:
                f.write(f'{datetime.utcnow()},{status},{elapsed},{remark}\n')
    
            # Alert on failure
            if status != 200:
                send_alert(
                    subject=f'⚠️ {TARGET_URL} returned {status}',
                    body=f'Checked at {datetime.utcnow()}\\nStatus: {status}\\nResponse time: {elapsed}s'
                )
        except requests.RequestException as exc:
            logging.error('Request error: %s', exc)
            with open(log_file, 'a') as f:
                f.write(f'{datetime.utcnow()},0,0,Exception: {exc}\\n')
            send_alert(
                subject=f'❌ {TARGET_URL} is down',
                body=f'Checked at {datetime.utcnow()}\\nError: {exc}'
            )
    
    
    # Schedule the job
    schedule.every(INTERVAL).minutes.do(check_website)
    
    if __name__ == '__main__':
        logging.info('Starting Python uptime monitor for %s', TARGET_URL)
        # Run an immediate check on start
        check_website()
        while True:
            schedule.run_pending()
            # Sleep a short time to avoid busy‑waiting
            time.sleep(1)

    This script:

    • Loads configuration from .env for security.
    • Uses requests.get() with a 10‑second timeout.
    • Logs each check to uptime_log.csv (timestamp, HTTP status, response time, remark).
    • Sends an email alert when the status is not 200 or when an exception occurs.
    • Runs every INTERVAL minutes using the schedule library.
  4. Deploy the script

    For a production‑grade setup, run the script as a background service:

    • Linux: create a systemd service file.
    • Docker: wrap the script in a lightweight container.
    • Windows: use nssm to register it as a Windows service.
  5. Optional enhancements

    • Integrate slack_sdk to post alerts to a Slack channel.
    • Add exponential back‑off retries for transient network glitches.
    • Store logs in a database and visualize uptime with Grafana or Power BI.
    • Implement TLS certificate expiration checks alongside HTTP status.

Best Practices for Reliable Monitoring

Even the best script can fail if you ignore operational hygiene. Follow these proven practices to keep your monitor trustworthy.

  • Use multiple check locations: Deploy the script on servers in different regions or use a third‑party service (e.g., UptimeRobot) as a secondary source.
  • Set realistic thresholds: A brief 5xx response may be acceptable; configure a grace period before triggering alerts.
  • Secure credentials: Never hard‑code passwords; use environment variables, secret managers, or encrypted vaults.
  • Monitor the monitor: Track the script’s own health (CPU, memory, exit codes) and set up alerts if it crashes.
  • Document downtime: Keep a

Comments

Leave a Reply

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