Install Changedetection.io on Docker: Monitor Website Changes and Get Instant Telegram Alerts in Your HomeLab

HomeLab tutorial - IT technology blog
HomeLab tutorial - IT technology blog

The Problem: You Miss Things That Matter

There’s a specific kind of frustration that comes from checking a product page every day for two weeks — manually, in a browser tab — only to discover the item went back in stock and sold out again while you were asleep. Or watching a competitor’s pricing page, a government form, a job listing. At some point, manual monitoring stops being a workflow and starts being a second job.

The root cause isn’t laziness. Websites just don’t notify you when their content changes. RSS feeds are half-dead. Email newsletters are curated for marketing, not for tracking specific page content. Browser extensions that do this tend to be flaky, tied to a single machine, and privacy-questionable.

What you actually need is a self-hosted service running 24/7 in your HomeLab. Something that checks URLs on a schedule, diffs the content, and pushes an alert to wherever you’re already paying attention. That’s exactly what Changedetection.io does, and running it in Docker takes about 10 minutes.

What Changedetection.io Actually Does

Changedetection.io is an open-source web content monitoring tool. It fetches pages at configurable intervals, compares the new content against what it saw last time, and fires off a notification when differences are detected.

Here’s what makes it worth using over a simple browser extension:

  • Browser-based rendering support — via Playwright, it handles JavaScript-heavy SPAs that a plain HTTP fetch would return blank for.
  • XPath/CSS selector filtering — scope monitoring to a specific section of a page, ignoring nav bars and footers that change constantly.
  • Notification integrations — Telegram, Slack, Discord, email, ntfy, Pushover, and more, all via Apprise under the hood.
  • Change history — every detected change is stored with a diff view so you can see exactly what moved.
  • Visual diff — highlights added/removed text directly in the web UI.

Running it via Docker Compose gives you a persistent, always-on monitor. No browser tab left open anywhere.

Setting Up Changedetection.io with Docker Compose

Prerequisites

You need Docker and Docker Compose installed on your HomeLab host. On Ubuntu/Debian:

curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER
newgrp docker

Verify it’s working:

docker compose version

Create the Project Directory

mkdir -p ~/homelab/changedetection/datastore
cd ~/homelab/changedetection

Write the Docker Compose File

Create docker-compose.yml with the content below. This setup bundles in the Playwright browser container for JavaScript-rendered pages. If you’re only monitoring static sites, drop the playwright-chrome service and the PLAYWRIGHT_DRIVER_URL env var — it’ll save you around 300–500MB of RAM.

services:
  changedetection:
    image: ghcr.io/dgtlmoon/changedetection.io
    container_name: changedetection
    hostname: changedetection
    volumes:
      - ./datastore:/datastore
    environment:
      - PORT=5000
      - PLAYWRIGHT_DRIVER_URL=ws://playwright-chrome:3000
    ports:
      - "5000:5000"
    depends_on:
      playwright-chrome:
        condition: service_started
    restart: unless-stopped

  playwright-chrome:
    image: dgtlmoon/sockpuppetbrowser:latest
    container_name: playwright-chrome
    hostname: playwright-chrome
    cap_add:
      - SYS_ADMIN
    restart: unless-stopped
    environment:
      - SCREEN_WIDTH=1920
      - SCREEN_HEIGHT=1024
      - SCREEN_DEPTH=16
      - MAX_CONCURRENT_CHROME_PROCESSES=10

Start the Services

docker compose up -d

Check that both containers are running:

docker compose ps

You should see changedetection and playwright-chrome both in the running state. Open http://<your-homelab-ip>:5000 in your browser.

Add Your First Watch

On the main dashboard, paste any URL into the input field and click Watch. Changedetection.io fetches the page immediately and stores a baseline snapshot. On every subsequent check (default interval: 24 hours, adjustable per-watch), it diffs against that baseline.

To change the interval for a specific watch, click the watch name → Edit → set the Time between checks field. For pricing or stock pages, somewhere between 30 minutes and 2 hours is a reasonable range — frequent enough to catch changes, gentle enough not to hammer the target server.

Configuring Telegram Notifications

Create a Telegram Bot

  1. Open Telegram and search for @BotFather.
  2. Send /newbot, follow the prompts, and copy the HTTP API token it gives you.
  3. Send any message to your new bot to initialize the chat.
  4. Fetch your chat ID by running this in a terminal (replace TOKEN with your actual bot token):
curl -s "https://api.telegram.org/botTOKEN/getUpdates" | python3 -m json.tool

Look for "chat":{"id": 123456789} in the response. That number is your chat ID.

Add the Notification URL in Changedetection.io

Changedetection.io uses Apprise for notifications. The Telegram format is:

tgram://BOT_TOKEN/CHAT_ID

Go to Settings → Notifications in the web UI, paste your Apprise URL, and click Send test notification. A test message should land in Telegram within a few seconds.

You can also set notification URLs per-watch under Edit → Notifications. Handy if you want certain watches to alert a group chat while others go to your personal DMs.

Customize the Notification Message

The default message template works fine out of the box. To tweak it, go to Settings → Notifications → Notification body. The most useful variables:

  • {{watch_url}} — the monitored URL
  • {{watch_title}} — the label you gave the watch
  • {{diff}} — a text diff of what changed
  • {{preview_url}} — link to the diff view in your Changedetection instance

A template that works well for Telegram:

🔔 Change detected: {{watch_title}}

URL: {{watch_url}}

Preview: {{preview_url}}

Hands-On: Monitoring a JavaScript-Rendered Page

Some pages load their actual content after the initial HTML response — React or Vue apps that render in the browser, for example. A plain HTTP fetch returns an empty shell. This is where the Playwright container earns its keep.

When adding or editing a watch, scroll to Request → Fetch backend and switch from Basic fast Fetch to Chrome/Javascript. Changedetection.io routes that watch through the Playwright browser, which fully renders the page before taking a snapshot.

Pair that with a CSS/XPath filter under Filters & Triggers to watch only the element you care about — say, a product price:

css:.product-price

Now everything else on the page is ignored. You won’t get pinged every time an ad rotates or a cookie banner updates. Only when the price itself moves.

Keeping the Data Safe

All watch configurations and change history live in ./datastore on your host. Backing it up is one command:

tar -czf changedetection-backup-$(date +%Y%m%d).tar.gz ./datastore

Moving to a different host is just as easy — copy the datastore directory, bring up the containers, and everything is there: watches, history, notification settings, all of it.

I’ve run this setup for monitoring a handful of vendor pricing pages and internal dashboards. Rock solid. The Playwright container does add memory overhead — budget around 512MB–1GB total depending on concurrent checks — but on any homelab box with 4GB+ RAM, that’s not a concern.

Where to Go From Here

At this point you have a self-hosted monitor that checks URLs on your schedule, handles JavaScript rendering, scopes changes to exactly the content you care about, and pushes Telegram alerts the moment something shifts. No open browser tabs. No missed restocks.

Two natural next steps: first, put a reverse proxy in front of it — Nginx Proxy Manager, Caddy, or Traefik all work — so you can reach the UI over HTTPS without exposing port 5000 directly. Second, add basic authentication if the instance is reachable from outside your home network. Neither is complicated, and both are worth doing before you start monitoring anything sensitive.

Share: