← Back to posts
comparison guide self-hosted · · 11 min read

Best Self-Hosted Website Change Monitors: Changedetection.io vs Alternatives 2026

Compare the best self-hosted website change monitoring tools in 2026. Replace Distill.io and Visualping with changedetection.io and open-source alternatives for price tracking, inventory alerts, and content monitoring.

OS
Editorial Team

Every day, millions of people rely on website change monitoring to track price drops, watch for job postings, monitor competitor websites, and catch breaking news the moment it happens. Commercial services like Distill.io, Visualping, and ChangeTower offer this capability — but they come with limitations: URL caps on free tiers, slow check intervals, and your monitoring data living on someone else’s servers.

In 2026, self-hosted website monitoring has never been easier. This guide covers the best open-source tools for tracking web page changes, with a deep focus on changedetection.io, the most popular self-hosted option, along with several alternatives for different use cases.

Why Self-Host Your Website Change Monitor?

Before diving into the tools, let’s look at why running your own monitoring solution makes sense:

  • No URL limits — Monitor hundreds or thousands of pages without paying per-watch
  • Faster check intervals — Check every 30 seconds instead of every hour or day
  • Complete privacy — Your monitored URLs, extracted data, and notifications stay on your server
  • Custom filters — Use CSS selectors, XPath, regex, and JavaScript to watch exactly what matters
  • Unlimited notifications — Send alerts to any channel: email, Discord, Slack, Telegram, webhooks, and more
  • Full history — Keep a complete archive of every change, forever
  • No vendor lock-in — Your data, your rules, your server

Whether you’re a developer tracking API documentation changes, a bargain hunter monitoring e-commerce prices, or a journalist watching government websites for policy updates, a self-hosted solution gives you the flexibility that commercial services can’t match.

Top Self-Hosted Website Change Monitoring Tools

1. changedetection.io

GitHub: dgtlmoon/changedetection.io Stars: 18,000+ Language: Python Best for: General-purpose website monitoring with an intuitive web UI

Changedetection.io is the gold standard for self-hosted website change monitoring. It features a clean web interface, supports visual CSS selectors, handles JavaScript-rendered pages, and integrates with dozens of notification services. Its strength lies in combining power with simplicity — you can set up a watch in under a minute.

Key features:

  • Visual selector tool for targeting specific page regions
  • Built-in browser for JavaScript-rendered pages (Playwright support)
  • Regex, substring, and JSON path filtering
  • Scheduled checks with custom intervals
  • Proxy rotation support to avoid IP bans
  • REST API for programmatic watch management
  • Export/import watch configurations
  • Multi-user support with watch sharing

2. Huginn

GitHub: huginn/huginn Stars: 43,000+ Language: Ruby Best for: Advanced users who want to build complex monitoring pipelines

Huginn is more than a change monitor — it’s a full automation platform. You create “agents” that perform actions, and connect them into workflows. A WebsiteAgent can scrape pages, extract data with XPath or CSS selectors, and trigger downstream agents when changes are detected. The learning curve is steeper, but the flexibility is unmatched.

Key features:

  • Visual workflow builder for complex monitoring chains
  • Agents for scraping, API calls, email parsing, RSS generation, and more
  • Scheduled execution with cron-like syntax
  • Data transformation with Liquid templating
  • Can create your own APIs from websites that don’t offer them

3. URLWatch

GitHub: thp/urlwatch Stars: 3,000+ Language: Python Best for: Terminal-first users who prefer YAML configuration

URLWatch is a lightweight, CLI-driven tool perfect for developers who want to manage their watches through version-controlled YAML files. It supports hooks for custom processing and integrates cleanly with cron for scheduling. While it lacks a web UI, its simplicity and scriptability make it a favorite among sysadmins.

Key features:

  • YAML-based watch configuration
  • Shell hooks for pre/post-processing
  • Supports HTTP, HTTPS, FTP, local files, and shell commands
  • JSONPath and CSS selector filtering
  • Email, stdout, and custom notification outputs

Comparison Table

Featurechangedetection.ioHuginnURLWatch
Web UIYesYesNo (CLI only)
Ease of SetupEasyModerateEasy
JavaScript RenderingYes (Playwright)YesNo
Visual SelectorYesNoNo
YAML ConfigOptionalNoYes (primary)
REST APIYesYesNo
Notification Channels40+20+Email, custom hooks
Multi-UserYesYesNo
Proxy SupportYesYesYes
Resource UsageLowModedockerighMinimal
Docker SupportExcellentGoodGood
Active DevelopmentVery ActiveModerateActive

Getting Started with changedetection.io

The fastest way to get started is with Docker. This sets up changedetection.io with persistent storage and automatic restart:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# Create a data directory for persistent storage
mkdir -p ~/changedetection/data

# Run the container
docker run -d \
  --name changedetection \
  -p 5000:5000 \
  -v ~/changedetection/data:/datastore \
  -e PLAYWRIGHT_DRIVER_URL=ws://playwright:3000/ \
  --restart unless-stopped \
  ghcr.io/dgtlmoon/changedetection.io:latest

For JavaScript-heavy sites (SPAs, dynamic content), add the Playwright browser container:

1
2
3
4
5
docker run -d \
  --name playwright \
  --network host \
  -e PORT=3000 \
  browserless/chrome:latest

Docker Compose Setup

For production deployments, Docker Compose is the recommended approach. Create a docker-compose.yml file:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
version: '3.8'

services:
  changedetection:
    image: ghcr.io/dgtlmoon/changedetection.io:latest
    container_name: changedetection
    restart: unless-stopped
    ports:
      - "5000:5000"
    volumes:
      - changedetection-data:/datastore
    environment:
      - PLAYWRIGHT_DRIVER_URL=ws://playwright:3000/
      - FETCH_WORKERS=4
      - BASE_URL=http://localhost:5000
    depends_on:
      - playwright

  playwright:
    image: browserless/chrome:latest
    container_name: playwright
    restart: unless-stopped
    environment:
      - PORT=3000
      - MAX_CONCURRENT_SESSIONS=4

volumes:
  changedetection-data:
    driver: local

Start the stack:

1
docker compose up -d

Access the web interface at http://localhost:5000. No login is required by default — ynginxould set one up immediately in Settings.

Nginx Reverse Proxy

Put changedetection.io behind Nginx for HTTPS and basic auth:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
server {
    listen 443 ssl http2;
    server_name monitor.example.com;

    ssl_certificate /etc/letsencrypt/live/monitor.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/monitor.example.com/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:5000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        
        # WebSocket support for live notifications
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

Generate the certificate with Certbot:

1
certbot --nginx -d monitor.example.com

Configuring Your First Watch

Basic Text Change Detection

  1. Click Create in the web UI
  2. Enter the URL you want to monitor
  3. Leave filters empty for full-page monitoring
  4. Set check interval (e.g., 60 seconds for fast monitoring)
  5. Choose a notification method
  6. Click Save

Monitoring Specific Page Regions

To track only the price on a product page, use CSS selectors:

1
2
3
4
5
6
7
8
/* Target a price element */
.product-price .current-price

/* Target a specific table cell */
table.inventory tr.in-stock td:nth-child(3)

/* Exclude navigation and footer noise */
body > main article.content

Changedetection.io includes a Visual Selector tool that lets you click on the page to auto-generate the correct CSS selector — no coding required.

JSON API Monitoring

For tracking API responses, changedetection.io supports JSONPath filters:

1
2
3
$.data.items[?(@.status=="active")].name
$.results[0].price
$.meta.last_updated

This is especially useful for monitoring REST APIs, GitHub repository stats, or any service that returns structured data.

Setting Up Notifications

Discord Webhook

Changedetection.io natively supports Discord notifications:

1
2
# In the Notifications settings, enter your Discord webhook URL:
discord://webhook-id/webhook-token

You can customize the message format:

1
2
3
4
🔔 **Website Change Detected**
📄 {{ watch_url }}
🕐 {{ current_time }}
📝 {{ preview }}

Email Notifications (SMTP)

Configure SMTP for email alerts:

1
mailto://user:password@gmail.com

For self-hosted email with Mailrise or Gotify:

1
gotify://hostname/token

Telegram Bot

  1. Create a bot via @BotFather on Telegram
  2. Get your chat ID by messaging @userinfobot
  3. Configure in changedetection.io:
1
tgram://bot-token/chat-id/

Slack Integration

1
slack://workspace-token-A/workspace-token-B/workspace-token-C/channel

Advanced Use Cases

Price Tracking with Threshold Alerts

Monitor a product price and only get notified when it drops below a threshold:

  1. Set up a watch with a CSS selector targeting the price element
  2. Enable Trigger a wait with a text filter:
    1
    2
    
    Filter: Regex
    Pattern: \$([0-9]+\.[0-9]+)
    
  3. In a notification script, parse the extracted price and compare against your threshold

For more sophisticated price tracking, combine with a custom webhook receiver:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
from flask import Flask, request
import json

app = Flask(__name__)

THRESHOLDS = {
    "https://example.com/product-a": 29.99,
    "https://example.com/product-b": 49.99,
}

@app.route("/webhook", methods=["POST"])
def price_alert():
    data = request.json
    url = data.get("watch_url", "")
    body = data.get("current_snapshot", "")
    
    # Extract price (simplified)
    for line in body.split("\n"):
        if "$" in line:
            try:
                price = float(line.split("$")[1].strip())
                threshold = THRESHOLDS.get(url, 0)
                if price <= threshold and threshold > 0:
                    print(f"ALERT: {url} dropped to ${price}!")
                    # Send notification here
            except ValueError:
                pass
    
    return "OK", 200

if __name__ == "__main__":
    app.run(port=8080)

Job Board Monitoring

Track new postings on job boards by monitoring the first page of search results:

  1. Create a watch with the search URL (e.g., a filtered GitHub Jobs or company careers page)
  2. Use a CSS selector to target only job listing elements:
    1
    
    .job-listing a.job-title
    
  3. Set check interval to 300 seconds (5 minutes)
  4. Configure notifications to Discord or email
  5. Enable Extract text to get the full job title and link in alerts

Government and Policy Monitoring

Stay updated on regulation changes by monitoring official websites:

  1. Set up watches on government policy pages
  2. Use the Subtract/Ignore text filter to remove dynamic elements like timestamps, ads, and navigation
  3. Enable Detect text changes only to ignore cosmetic/layout updates
  4. Set a longer check interval (3600 seconds) since government sites change slowly

Example ignore patterns:

1
2
3
Last updated:.*
© 2026.*
<script.*</script>

Competitor Price Intelligence

Monitor multiple competitor product pages simultaneously:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# Bulk import file (YAML format)
watches:
  - url: "https://competitor-a.com/product/widget-pro"
    css_filter: ".price-final"
    check_interval: 3600
    
  - url: "https://competitor-b.com/widgets/pro-widget"
    css_filter: ".product-price"
    check_interval: 3600
    
  - url: "https://competitor-c.com/shop/widget-pro"
    css_filter: "#price-display"
    check_interval: 7200

Import through the web UI’s Import/Export feature to set up dozens of watches at once.

Using the REST API

Changedetection.io exposes a REST API for programmatic management. This is useful for integrating monitoring into existing tools or building custom dashboards.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
# List all watches
curl http://localhost:5000/api/v1/watch

# Create a new watch
curl -X POST http://localhost:5000/api/v1/watch \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/pricing",
    "css_filter": ".price",
    "check_interval": 300,
    "notification_urls": "discord://webhook/token"
  }'

# Get watch details
curl http://localhost:5000/api/v1/watch/{uuid}

# Trigger an immediate check
curl -X POST http://localhost:5000/api/v1/watch/{uuid}/check-now

# Delete a watch
curl -X DELETE http://localhost:5000/api/v1/watch/{uuid}

Scaling for Large Deployments

If you’re monitoring hundreds of pages, consider these optimization strategies:

Increase Worker Threads

1
2
3
4
docker run -d \
  -e FETCH_WORKERS=8 \
  -e MINIMUM_SECONDS_RECHECK_TIME=15 \
  ghcr.io/dgtlmoon/changedetection.io:latest

Use Proxy Rotation

Avoid IP-based rate limiting by configuring proxies:

1
2
3
4
# In settings, add proxy configuration
# Format: protocol://user:pass@host:port
http://user:pass@proxy1.example.com:8080
http://user:pass@proxy2.example.com:8080

Or via environment variable for Docker:

1
2
3
environment:
  - PROXY_LIST=http://proxy1:8080,http://proxy2:8080
  - PROXY_MODE=rotate

Distributed Monitoring with Multiple Instances

For very large deployments (1000+ watches), run multiple instances with URL-based sharding:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# Instance 1: A-M URLs
services:
  changedetection-a:
    image: ghcr.io/dgtlmoon/changedetection.io:latest
    environment:
      - FETCH_WORKERS=4
    volumes:
      - data-a:/datastore

  # Instance 2: N-Z URLs
  changedetection-b:
    image: ghcr.io/dgtlmoon/changedetection.io:latest
    environment:
      - FETCH_WORKERS=4
    volumes:
      - data-b:/datastore

Backup and Migration

Changedetection.io stores all data as JSON files in the datastore directory. Backing up is straightforward:

1
2
3
4
5
# Create a backup
tar -czf changedetection-backup-$(date +%Y%m%d).tar.gz ~/changedetection/data/

# Restore on a new server
tar -xzf changedetection-backup-20260415.tar.gz -C ~/changedetection/data/

For automated backups, add a cron job:

1
2
# Daily backup at 2 AM
0 2 * * * tar -czf /backups/changedetection-$(date +\%Y\%m\%d).tar.gz /root/changedetection/data/ && find /backups/ -name "changedetection-*.tar.gz" -mtime +30 -delete

Troubleshooting Common Issues

“Page is empty” or no content detected

  • Enable Playwright/JavaScript rendering in the watch settings
  • Increase the fetch timeout: set FETCH_TIMEOUT=120 environment variable
  • Check if the site blocks bots — try adding a custom User-Agent header

Too many false positives

  • Enable Detect only text changes to ignore layout shifts
  • Use Subtract/Ignore text to filter out dynamic elements (dates, ads, counters)
  • Narrow your CSS selector to target only the relevant content

Rate limiting / IP blocked

  • Increase check intervals to reduce request frequency
  • Configure proxy rotation as described above
  • Add Accept and User-Agent headers to appear as a regular browser
  • Enable Fetch via Playwright which uses a real browser fingerprint

Memory issues with Playwright

  • Limit concurrent sessions: MAX_CONCURRENT_SESSIONS=2 in the Playwright container
  • Set PLAYWRIGHT_DRIVER_URL to use a shared browser instance
  • Consider using the lightweight HTML fetcher for simple pages that don’t need JavaScript

Conclusion

Self-hosted website change monitoring puts you in full control of your data, check intervals, and notification workflows. Changedetection.io stands out as the best all-around choice with its intuitive interface, broad notification support, and active development. For advanced automation scenarios, Huginn offers unmatched flexibility, while URLWatch appeals to terminal-first users who prefer YAML-driven configuration.

The beauty of these self-hosted tools is that they cost nothing to run beyond your server — no per-watch fees, no tiered pricing, no data caps. Set up monitoring for 10 pages or 10,000, and the experience is the same. Whether you’re tracking prices, watching for job postings, or monitoring regulatory changes, a self-hosted website monitor is a tool that pays for itself the first time it catches a change you would have otherwise missed.

Frequently Asked Questions (FAQ)

Which one should I choose in 2026?

The best choice depends on your specific requirements:

  • For beginners: Start with the simplest option that covers your core use case
  • For production: Choose the solution with the most active community and documentation
  • For teams: Look for collaboration features and user management
  • For privacy: Prefer fully open-source, self-hosted options with no telemetry

Refer to the comparison table above for detailed feature breakdowns.

Can I migrate between these tools?

Most tools support data import/export. Always:

  1. Backup your current data
  2. Test the migration on a staging environment
  3. Check official migration guides in the documentation

Are there free versions available?

All tools in this guide offer free, open-source editions. Some also provide paid plans with additional features, priority support, or managed hosting.

How do I get started?

  1. Review the comparison table to identify your requirements
  2. Visit the official documentation (links provided above)
  3. Start with a Docker Compose setup for easy testing
  4. Join the community forums for troubleshooting
Advertise here