Site-Shot

Tutorial ·Apr 2, 2026 ·3 min read

How to Automate Website Monitoring with Screenshots

Visual monitoring catches problems that traditional uptime checks miss. A website can return HTTP 200 while displaying a broken layout, missing images, or an error message in the page body. Automated screenshot monitoring captures what users actually see.

Why Monitor with Screenshots?

  • Visual regression detection — catch CSS breaks, missing images, and layout shifts that don't trigger HTTP errors.
  • Content verification — confirm that pricing, product listings, or legal pages display the correct information.
  • Competitor tracking — monitor competitor websites for design changes, new features, or pricing updates.
  • Compliance records — maintain timestamped visual records of web pages for legal or regulatory purposes.
  • Downtime evidence — screenshot captures provide visual proof of outages beyond simple ping checks.

Basic Monitoring Script (Python)

Here's a Python script that captures a screenshot and saves it with a timestamp:

import os
from datetime import datetime

import requests

API_URL = "https://api.site-shot.com/"
API_KEY = "YOUR_API_KEY"
OUTPUT_DIR = "screenshots"


def capture(url, label="site"):
    os.makedirs(OUTPUT_DIR, exist_ok=True)
    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    filename = f"{label}_{timestamp}.png"
    filepath = os.path.join(OUTPUT_DIR, filename)

    response = requests.get(API_URL, params={
        "url": url,
        "userkey": API_KEY,
        "width": 1280,
        "height": 1024,
        "format": "png",
        "no_ads": 1,
        "no_cookie_popup": 1,
    }, timeout=70)

    if response.status_code == 200:
        with open(filepath, "wb") as f:
            f.write(response.content)
        print(f"Captured: {filepath}")
    else:
        print(f"Error: HTTP {response.status_code}")


if __name__ == "__main__":
    capture("https://your-website.com", label="homepage")
    capture("https://your-website.com/pricing", label="pricing")

Scheduling Captures

With cron (Linux/macOS)

Run the script every hour:

0 * * * * /usr/bin/python3 /path/to/monitor.py

With Task Scheduler (Windows)

Create a scheduled task that runs python monitor.py at your desired interval.

With GitHub Actions

name: Screenshot Monitor
on:
  schedule:
    - cron: '0 */6 * * *'  # Every 6 hours

jobs:
  capture:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: '3.12'
      - run: pip install requests
      - run: python monitor.py
      - uses: actions/upload-artifact@v4
        with:
          name: screenshots-${{ github.run_number }}
          path: screenshots/

Monitoring Multiple Pages

PAGES = [
    ("https://your-site.com/", "homepage"),
    ("https://your-site.com/pricing", "pricing"),
    ("https://your-site.com/docs", "docs"),
    ("https://competitor.com/", "competitor"),
]

for url, label in PAGES:
    capture(url, label=label)

Detecting Visual Changes

Compare consecutive screenshots using image diffing. A simple pixel-comparison approach:

from PIL import Image
import numpy as np

def images_differ(path_a, path_b, threshold=0.01):
    """Return True if more than `threshold` fraction of pixels differ."""
    img_a = np.array(Image.open(path_a))
    img_b = np.array(Image.open(path_b))

    if img_a.shape != img_b.shape:
        return True

    diff_pixels = np.sum(img_a != img_b) / img_a.size
    return diff_pixels > threshold

When a change is detected, send an alert via email, Slack, or your preferred notification channel.

Tips for Reliable Monitoring

  • Use no_ads=1 and no_cookie_popup=1 to remove dynamic elements that change between captures and create false positives.
  • Set a consistent viewport (e.g., 1280×1024) so screenshots are always comparable.
  • Use delay_time=3000 for pages with heavy JavaScript rendering to ensure all content is loaded.
  • Capture from a fixed country using the country parameter to avoid geo-based content variations.
  • Store screenshots with timestamps for audit trails and historical comparison.

Full Page Monitoring

For pages where content below the fold matters (e.g., long pricing pages), use full page capture:

response = requests.get(API_URL, params={
    "url": url,
    "userkey": API_KEY,
    "full_size": 1,
    "max_height": 10000,
    "format": "jpeg",  # JPEG for smaller files in archives
    "no_ads": 1,
    "no_cookie_popup": 1,
}, timeout=70)

Next Steps

  • Set up the Site-Shot API with your API key
  • Create a monitoring script for your key pages
  • Schedule it with cron, GitHub Actions, or your CI/CD pipeline
  • Add image diffing and alerting for automated change detection

← All articles