Freedom Sale
Independence Day Special — Unlock the AI Path 70% off our most popular AI course · Limited time offer
--Days
--Hrs
--Min
--Sec
Claim Your Discount
✦ Beginner ⏱ 25 min

📡 Build a Website Uptime Monitor with Python

🎯 What You'll Build

A script that checks a list of websites every 60 seconds, logs response times, alerts you when a site goes down, and generates an uptime report.

📋 What You'll Need

1

Check a single website

Use requests.get() with a timeout to check if a site is up and measure response time.

import requests, time

def check_site(url):
    try:
        start = time.time()
        r = requests.get(url, timeout=10, allow_redirects=True)
        elapsed = round((time.time() - start) * 1000)  # ms
        return {'url': url, 'status': r.status_code, 'ms': elapsed, 'up': r.status_code < 400}
    except requests.exceptions.Timeout:
        return {'url': url, 'status': 'TIMEOUT', 'ms': None, 'up': False}
    except requests.exceptions.ConnectionError:
        return {'url': url, 'status': 'DOWN', 'ms': None, 'up': False}

print(check_site('https://google.com'))
{'url': 'https://google.com', 'status': 200, 'ms': 143, 'up': True}
2

Monitor multiple sites on a schedule

Loop through all sites every 60 seconds and log results.

import json, datetime

SITES = [
    'https://google.com',
    'https://github.com',
    'https://itexperttraining.com',
]
INTERVAL = 60  # seconds between checks

def monitor():
    print(f"Monitoring {len(SITES)} sites. Press Ctrl+C to stop.\n")
    while True:
        timestamp = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        print(f"[{timestamp}]")
        for url in SITES:
            result = check_site(url)
            icon = '✅' if result['up'] else '🔴'
            ms   = f"{result['ms']}ms" if result['ms'] else str(result['status'])
            print(f"  {icon} {url}  —  {ms}")
            log_result(result, timestamp)
        print()
        time.sleep(INTERVAL)

def log_result(result, timestamp):
    with open('uptime_log.jsonl', 'a') as f:
        f.write(json.dumps({**result, 'time': timestamp}) + '\n')

monitor()
[2026-08-09 14:30:00]
  ✅ https://google.com  —  143ms
  ✅ https://github.com  —  287ms
  🔴 https://itexperttraining.com  —  TIMEOUT
3

Generate an uptime report

Read the log file and calculate uptime percentage and average response time for each site.

def report():
    from collections import defaultdict
    stats = defaultdict(lambda: {'up': 0, 'down': 0, 'times': []})

    with open('uptime_log.jsonl') as f:
        for line in f:
            r = json.loads(line)
            key = r['url']
            if r['up']:
                stats[key]['up'] += 1
                if r['ms']: stats[key]['times'].append(r['ms'])
            else:
                stats[key]['down'] += 1

    print(f"\n{'URL':<40} {'Uptime':>8} {'Avg ms':>8} {'Checks':>7}")
    print('-' * 66)
    for url, s in stats.items():
        total   = s['up'] + s['down']
        uptime  = s['up'] / total * 100 if total else 0
        avg_ms  = round(sum(s['times']) / len(s['times'])) if s['times'] else '-'
        status  = '✅' if uptime == 100 else ('⚠️' if uptime > 90 else '🔴')
        print(f"{status} {url:<38} {uptime:>7.1f}% {str(avg_ms):>7}ms {total:>6}")

report()
URL                                       Uptime   Avg ms  Checks
──────────────────────────────────────────────────────────────────
✅ https://google.com                      100.0%    141ms      24
✅ https://github.com                       99.6%    289ms      24
⚠️  https://itexperttraining.com             91.7%    523ms      24
💡 Tip: To get email alerts when a site goes down, add a call to smtplib inside the monitor loop when result["up"] is False. Only send the alert on the first failure (track last state per URL) to avoid spam.

🎉 You Did It!

Your monitor runs as a background service and produces audit-ready logs. Add it to Windows Task Scheduler or a Linux cron job to start automatically at boot.

Found something wrong?

Spotted a bug, broken code, or something that doesn't look right? Tell us what's off and we'll fix it.