Why Self-Hosted Web Monitoring Makes Sense
Most website change detection services live in the cloud, charge monthly fees, and quietly log every URL you monitor. If you are tracking competitor pricing, job postings, government notices, or anything you would rather keep private, handing that data to a third-party platform carries real risk. Changedetection.io flips that model entirely – it runs on your own hardware, stores nothing outside your network, and costs nothing beyond electricity and a few minutes of setup time.
The project is open-source, actively maintained, and ships as a Docker container that works on anything from a Raspberry Pi to a full home server. It supports plain text diffing, visual screenshot comparison, browser-rendered pages via Playwright or Puppeteer, and notification delivery through dozens of services including Telegram, Discord, email, and Gotify. This guide walks through getting a fully functional instance running with Docker Compose, configuring your first watches, and connecting notifications.

Prerequisites and System Requirements
You need a Linux host with Docker and Docker Compose installed. Changedetection.io itself is lightweight – the base container runs comfortably on 512 MB of RAM. If you plan to enable the Playwright browser for JavaScript-heavy pages, budget at least 1 GB additional RAM per browser worker, since headless Chromium is not shy about memory. A Debian or Ubuntu server works well, though any Docker-capable host will do. Make sure port 5000 is free on the host, or pick a different host port in the Compose file.
You should also decide upfront whether you need browser rendering. Static HTML pages – think plain news sites, government bulletins, or simple product pages – work fine with the default fetch method and add no overhead. Pages that load prices or listings via JavaScript require the Playwright container. If you are unsure, start without it. You can add the browser container to the Compose stack later without losing any existing watch configurations, since Changedetection.io stores all data in a mounted volume.
Installing With Docker Compose
Create a project directory and open a new docker-compose.yml file inside it. The minimal configuration needs only the Changedetection.io service with a named volume for persistence and a published port for the web interface. The image to use is ghcr.io/dgtlmoon/changedetection.io – pull from the GitHub Container Registry rather than Docker Hub to always get the latest verified build.
Paste the following into your Compose file:
- image: ghcr.io/dgtlmoon/changedetection.io
- container_name: changedetection
- ports: “5000:5000”
- volumes: changedetection-data:/datastore
- restart: unless-stopped
- environment: BASE_URL=http://your-server-ip:5000
Add the named volume block at the bottom of the file, then run docker compose up -d. Docker pulls the image and starts the container in the background. Within thirty seconds the web interface is available at http://your-server-ip:5000. No database to seed, no config file to hand-edit – the application initializes its own datastore on first launch.
To add Playwright browser rendering, append a second service to the same Compose file. Use the image browserless/chrome or the Playwright-specific container listed in the official Changedetection.io documentation. Set the environment variable PLAYWRIGHT_DRIVER_URL in the Changedetection.io service to point at the browser container’s WebSocket endpoint, typically ws://playwright-chrome:3000 if you name the service playwright-chrome. Restart the stack with docker compose up -d –force-recreate and the browser option will appear in each watch’s fetch settings.

Adding Your First Watch
Open the web interface and click Add a new change detection watch. Paste the URL you want to monitor into the URL field. The default check interval is set globally, but you can override it per watch using the Recheck time field measured in seconds. For most use cases, checking every 3600 seconds (one hour) is reasonable and avoids hammering servers that rate-limit aggressive crawlers.
Under the Filters and Triggers tab inside each watch, you can use CSS selectors or XPath expressions to narrow monitoring to a specific part of the page. If you only care whether a price element changes, add its CSS selector in the CSS/XPath filter field. This eliminates false positives from page-wide changes like updated timestamps, cookie banners, or rotating ad content. The filter is the single most useful setting for keeping alerts meaningful rather than noisy.
Configuring Notifications
Changedetection.io uses the Apprise notification library under the hood, which means any service Apprise supports is available without extra plugins. Navigate to Settings > Notifications and add a notification URL. Telegram uses the format tgram://bottoken/chatid, Discord webhooks use discord://webhookid/webhooktoken, and SMTP email follows mailto://user:password@host. You can add multiple notification targets and Changedetection.io will fire all of them simultaneously on a detected change.
Test the notification immediately using the Send test notification button before walking away. A surprising number of setup issues come from typos in bot tokens or incorrect chat IDs, and catching that before you deploy ten watches saves a lot of confusion later. Once confirmed, the notification setting applies globally but can be overridden or disabled on individual watches through the Notifications tab inside each watch’s edit screen.
For users who prefer a browser-based notification loop without external services, Changedetection.io also exposes an RSS feed of all detected changes at /rss on your instance URL. Any RSS reader pointed at that endpoint will surface changes as unread items, giving you a completely self-contained notification chain with no outbound connections required. The feed includes a diff snippet, the timestamp, and a direct link back to the full change view inside the Changedetection.io interface.





