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.
No Code Required: Scheduled Captures
If you don't want to run a script at all, Site-Shot now does the scheduling for you: create a schedule in the browser — URL, capture settings, cadence — and it captures the page daily (or weekdays, or weekly), files every shot in your library, and keeps a ledger of every run including failures and skips. It's included with any paid plan. See the walkthrough in How to Automatically Screenshot a Website Every Day.
Schedules do both halves: they capture and file every run, and they compare each capture with the one before it — measuring how much of the page moved and emailing you when it crosses a threshold you set. What they don't do is tell you which words or elements changed: that is a visual measurement, not a text diff. Alerts arrive by email, at most one per schedule per day, and the soonest you can hear about anything is the schedule's own cadence. If you need element-level diffs, alerts in Slack, or captures wired into your own pipeline and storage, the API route below is still the right one — and the rest of this guide covers it.
Basic Monitoring Script (Python)
Install requests (pip install requests) and set SITESHOT_API_KEY in the environment that runs the script. This example saves each screenshot with a timestamp:
import os
from datetime import datetime
import requests
API_URL = "https://api.site-shot.com/"
API_KEY = os.environ["SITESHOT_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)
response.raise_for_status()
if not response.headers.get("Content-Type", "").lower().startswith("image/"):
raise RuntimeError(response.text)
with open(filepath, "wb") as f:
f.write(response.content)
print(f"Captured: {filepath}")
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, using the Python environment where you installed requests. Set the job's working directory so the relative screenshots/ output path is predictable:
0 * * * * cd /path/to/project && /path/to/project/.venv/bin/python monitor.py
With Task Scheduler (Windows)
Create a scheduled task that runs python monitor.py at your desired interval, with the project directory as its working directory and SITESHOT_API_KEY available to the task.
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
env:
SITESHOT_API_KEY: ${{ secrets.SITESHOT_API_KEY }}
- uses: actions/upload-artifact@v4
with:
name: screenshots-${{ github.run_number }}
path: screenshots/
Where this runs, and the catch: each run executes on a fresh, newly-provisioned GitHub-hosted VM, so nothing persists on the machine between runs — the screenshots survive only because upload-artifact attaches them to the workflow run, where you download them from the run's page. Three limits matter (GitHub's schedule rules and artifact retention, checked September 2026): artifacts are deleted after 90 days by default; the schedule trigger is best-effort — runs can be delayed at busy times and occasionally dropped; and in a public repository scheduled workflows are switched off automatically after 60 days without repo activity. Keep the API key in an Actions secret (as above), never in the file. In short: GitHub Actions is a decent scheduler but a poor archive — if you want a history that keeps itself, that's what scheduled captures are for.
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. Install pillow and numpy for this simple pixel-comparison example:
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).convert("RGB"))
img_b = np.array(Image.open(path_b).convert("RGB"))
if img_a.shape != img_b.shape:
return True
diff_pixels = np.any(img_a != img_b, axis=2).mean()
return diff_pixels > threshold
This function only detects a change; call it after each capture and add your own notification code for email, Slack, or another channel.
Tips for Reliable Monitoring
- Use
no_ads=1andno_cookie_popup=1to 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=3000to give JavaScript-rendered content three more seconds to load; a fixed delay cannot guarantee that every page is ready. - Capture from a fixed country using the
countryparameter (ISO code, e.g.country=US) to avoid geo-based content variations — see how country capture works. - 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)
FAQ
Can Site-Shot detect page changes for me?
Yes. Each scheduled capture is compared with the previous one, and Site-Shot measures how much of the shared image area moved. Turn on change alerts for a schedule, set your threshold, and it emails you when a capture crosses it — with a link that opens the two captures side by side. Two bounds worth knowing: it measures how much changed, not what changed (there is no text or element diff), and alerts go to email only, at most one per schedule per day. Alerts stay off until you switch them on. For element-level diffs or alerts routed somewhere else, use the API route in this guide.
Do I need to write code to monitor a website with screenshots?
Not for the capture part. Site-Shot's built-in scheduled captures run from the browser: pick a URL, capture settings, and a cadence, and every shot lands in your library with a ledger of every run — included with any paid plan. Code is only needed for the custom parts: your own storage, element-level diffing, or routing alerts somewhere other than email.
How often should I capture a page for monitoring?
Match the cadence to how fast the page changes. With your own cron you can run the script hourly or more often, within your plan's capture volume. Site-Shot's built-in schedules are designed for daily, weekday, or weekly cadences — the right fit for pricing pages, landing pages, and compliance records.
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 — or skip the script and use scheduled captures
- Prefer a visual builder? The same monitoring loop is three nodes in n8n or three modules in Make, and a single code step in Pipedream
- Add image diffing and alerting for automated change detection
Try the free no-signup screenshot tool, read what the built-in scheduled screenshots do and do not do, or compare API plans on the pricing page.