Running Changedetection.io: Website Change Alerts

You want to know when a product drops in price, when a job posting appears, when a government page updates, or when your competitor changes their pricing. You could check manually every day. Or you could let a self-hosted tool do it for you.

Changedetection.io monitors any webpage and alerts you when something changes. It’s like Google Alerts, but for the actual visual content of any page — not just search results.

What It Does

  • Monitor any URL for changes (text, HTML, visual)
  • Filter changes — only alert on specific parts of a page
  • Notification channels — Email, Telegram, Discord, Slack, webhooks, and 80+ more
  • Visual diff — See exactly what changed, highlighted
  • Scheduling — Check every minute, hour, day, or custom interval
  • JavaScript rendering — Handle SPAs and dynamic sites via built-in browser
  • CSS/XPath selectors — Watch specific elements, ignore the rest
  • API — Integrate with other tools

Use Cases

  • Price tracking — Alert when an item drops below your target price
  • Job boards — Know instantly when new positions are posted
  • Government/regulatory — Track policy changes, permit updates
  • Competitor monitoring — Pricing changes, new features, blog posts
  • Stock/availability — Get notified when out-of-stock items return
  • News/blog monitoring — Follow sites that don’t have RSS feeds
  • Legal/compliance — Track Terms of Service changes
  • Real estate — New listings matching your criteria

Prerequisites

  • Docker and Docker Compose
  • ~256 MB RAM (lightweight without browser)
  • ~512 MB RAM (with Playwright browser for JavaScript sites)

Installation

Basic Setup (No JavaScript Rendering)

Good for static sites, blogs, product pages with server-rendered content.

mkdir -p ~/changedetection
cd ~/changedetection
# docker-compose.yml
services:
  changedetection:
    image: ghcr.io/dgtlmoon/changedetection.io:latest
    container_name: changedetection
    ports:
      - "5000:5000"
    volumes:
      - ./data:/datastore
    environment:
      - TZ=America/New_York
      - BASE_URL=http://localhost:5000
    restart: unless-stopped
docker compose up -d

Open http://your-server-ip:5000.

Full Setup (With JavaScript Browser)

For sites that load content dynamically (SPAs, React apps, pages requiring JavaScript):

# docker-compose.yml
services:
  changedetection:
    image: ghcr.io/dgtlmoon/changedetection.io:latest
    container_name: changedetection
    ports:
      - "5000:5000"
    volumes:
      - ./data:/datastore
    environment:
      - TZ=America/New_York
      - BASE_URL=http://localhost:5000
      - PLAYWRIGHT_DRIVER_URL=ws://playwright-chrome:3000
    depends_on:
      - playwright-chrome
    restart: unless-stopped

  playwright-chrome:
    image: dgtlmoon/sockpuppetbrowser:latest
    container_name: playwright-chrome
    restart: unless-stopped
    environment:
      - SCREEN_WIDTH=1920
      - SCREEN_HEIGHT=1080
      - MAX_CONCURRENT_CHROME_PROCESSES=5
docker compose up -d

The Playwright browser runs headless Chrome to render JavaScript before checking for changes.

Adding Your First Watch

  1. Click Add Watch (or paste a URL into the quick-add bar)
  2. Enter the URL you want to monitor
  3. Set the check interval (default: every 3 hours)
  4. Click Watch

The first check establishes a baseline. You’ll get alerts starting from the second check when changes are detected.

Filtering: Watch Only What Matters

Most pages have noise — ads, timestamps, random elements. Filters let you focus on what you care about.

CSS Selector Filter

Watch only a specific part of the page:

/* Product price */
.product-price

/* Job listings container */
#job-results .job-card

/* Main content, ignore sidebar */
article.main-content

Enter selectors in the watch settings under CSS/JSON/XPath Filter.

XPath Filter

More powerful for complex selections:

//div[@class="price-current"]
//table[@id="results"]//tr
//h2[contains(text(), "Available")]

Text Filtering

Ignore lines matching patterns (useful for removing timestamps, ad content):

Ignore text: Add regex patterns for lines to exclude:

\L\dad{s+2t}v:ui\peddw{as2t}e:d.d{2}#T##im"VeLisaetswatmcpuospudnatteerds"lines

Trigger Keywords

Only alert when specific words appear in the change:

Trigger text:

ipnnreiwsctepoocrskeidtuicoend

This is powerful — monitor a page but only get alerted when relevant keywords appear in the diff.

Setting Up Notifications

Go to SettingsNotification URLs.

Telegram

tgram://BOT_TOKEN/CHAT_ID

Get your bot token from @BotFather and chat ID from @userinfobot.

Discord

discord://WEBHOOK_ID/WEBHOOK_TOKEN

Create a webhook in your Discord server settings → Integrations → Webhooks.

Email (SMTP)

mailto://user:password@smtp.gmail.com?to=you@example.com

Slack

slack://TokenA/TokenB/TokenC/#channel

Gotify

gotify://your-gotify-server/token

Full Notification Format

You can customize the notification message with variables:

{TDwiiatftlfce:h:_{u{drwilaf}tfc_hhua_rstli}cthlaen}ged!

Changedetection supports 80+ notification services via Apprise.

Practical Examples

Price Drop Alert

URL: https://amazon.com/dp/B0xxxxx
CSS Filter: #priceblock_ourprice, .a-price .a-offscreen
Trigger text: (leave empty — any price change triggers)
Check interval: Every 6 hours

Job Board Monitoring

URL: https://company.com/careers
CSS Filter: .job-listing
Trigger text: engineer, developer, remote
Check interval: Every 1 hour

Out-of-Stock Alerts

URL: https://store.com/product-page
CSS Filter: .availability, .stock-status
Trigger text: in stock, available, add to cart
Check interval: Every 30 minutes

Terms of Service Changes

URL: https://service.com/terms
CSS Filter: main, article, .content (skip headers/footers)
Check interval: Every 24 hours

Blog Without RSS

URL: https://blog-with-no-rss.com
CSS Filter: .post-list, article:first-of-type
Check interval: Every 6 hours

Visual Diff Mode

By default, Changedetection shows text diffs. With the Playwright browser, you can also enable visual diff — actual screenshots compared side by side.

Enable per-watch: EditRequestFetch MethodChrome/Playwright

This catches changes that text-based detection misses (layout changes, image swaps, visual redesigns).

API Usage

Changedetection has a REST API for automation:

# List all watches
curl http://localhost:5000/api/v1/watch

# Add a new watch
curl -X POST http://localhost:5000/api/v1/watch \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com", "title": "Example Watch"}'

# Trigger a recheck
curl -X POST http://localhost:5000/api/v1/watch/UUID/trigger-check

Combine with n8n or cron for advanced automation workflows.

Proxy Support

If you’re monitoring sites that might block your IP:

environment:
  - HTTP_PROXY=http://proxy:8080
  - HTTPS_PROXY=http://proxy:8080

Or set per-watch proxies for specific sites that need different IPs.

Backup

Your watches and history are stored in ./data/. Back up with compose-backup:

compose-backup --only changedetection

Troubleshooting

“No change detected” on Dynamic Sites

Switch to the Playwright browser:

  • Edit watch → RequestFetch method → Chrome/Playwright
  • Make sure playwright-chrome container is running

Too Many False Alerts

  • Add CSS selectors to focus on relevant content
  • Use Ignore text to filter out timestamps, counters, ads
  • Increase check interval (some sites have minor fluctuations)

Playwright Container Crashes

# Check memory — Playwright needs ~512MB
docker stats playwright-chrome

# Limit concurrent browsers if low on RAM
environment:
  - MAX_CONCURRENT_CHROME_PROCESSES=2

Can’t Access Behind Login

Changedetection supports:

  • Basic auth — Enter credentials in watch settings
  • Cookie injection — Paste cookies from your browser session
  • Custom headers — Add Authorization or session headers

Slow Checks

  • Reduce MAX_CONCURRENT_CHROME_PROCESSES if memory is tight
  • Use text-based fetching (not Playwright) for static sites
  • Increase check intervals for non-urgent monitors

Resource Usage

SetupRAMCPUStorage
Basic (no browser)~100 MBMinimal~50 MB + history
With Playwright~500 MBLight~100 MB + history
100+ watches~800 MBModerate~500 MB

Very lightweight for what it does.

Comparison with Alternatives

FeatureChangedetectionHuginnVisualpingDistill.io
Self-hosted
FreeFreemiumFreemium
Visual diff
JS rendering
Ease of setupEasyComplexN/AN/A
Notifications80+ManyLimitedLimited

Changedetection hits the sweet spot: powerful enough for complex monitoring, simple enough to set up in 5 minutes.

Conclusion

Changedetection.io replaces a dozen browser tabs you check manually. Set it up once, add your URLs, configure alerts, and forget about it. When something changes, you’ll know.

Especially useful for price tracking, job hunting, and monitoring anything that doesn’t offer proper notifications or RSS feeds.


More self-hosting guides at selfhostsetup.com. Check server health with selfhost-doctor.