Why Self-Hosted Monitoring Beats the Cloud Alternative
Most website monitoring services charge a monthly fee, cap how often they check your pages, and store your alert data on servers you have no control over. Changedetection.io flips that model entirely. It runs on your own hardware, checks pages as frequently as every minute if you want, and keeps everything – your watched URLs, your change history, your notification settings – on your own machine. No subscription tier, no data leaving your network unless you choose to send it.
The tool is built around a simple idea: give it a URL, tell it what to watch for, and get notified when something changes. That sounds narrow, but the use cases are broad. Price tracking on e-commerce pages, monitoring government portals for regulatory updates, watching competitor product pages, keeping tabs on job listings – any page that updates on its own schedule becomes something you can follow without manually checking it.
Setup takes under fifteen minutes if Docker is already on your machine.

Getting Changedetection.io Running with Docker
The fastest path to a working instance is Docker Compose. Create a directory for the project, then drop a docker-compose.yml file into it. The official image is ghcr.io/dgtlmoon/changedetection.io, and you only need a handful of lines to get a functional container. Map port 5000 on the host to port 5000 in the container, set a volume to persist your data, and optionally set the BASE_URL environment variable to your server’s address or domain if you plan to access it remotely. Here is a minimal working example:
version: "3"
services:
changedetection:
image: ghcr.io/dgtlmoon/changedetection.io
container_name: changedetection
restart: unless-stopped
ports:
- "5000:5000"
volumes:
- ./datastore:/datastore
environment:
- BASE_URL=http://your-server-ip:5000
Run docker compose up -d from that directory and the container starts in the background. Open a browser and go to http://your-server-ip:5000 and you will see the main interface. By default there is no login required, which is fine on a private network, but if the port is exposed to the internet you should set a password immediately. Go to Settings, then the Security tab, and enter a username and password. That basic auth gate applies to the entire interface.
For users running a reverse proxy like Nginx Proxy Manager or Caddy, you can map a subdomain such as monitor.yourdomain.com to port 5000 and add SSL termination at the proxy layer. Changedetection.io itself does not handle certificates, so the reverse proxy approach is the right way to get HTTPS. If your homelab already runs a zero-trust network overlay like Netbird, you can restrict access to authenticated peers without exposing the port publicly at all.
Adding Pages and Configuring What to Watch
Adding a URL is the first thing you do after logging in. Paste the address into the field on the home screen and click Watch. Changedetection.io immediately queues a first fetch, which becomes the baseline. On the next check cycle, it compares the new page content against that baseline and flags any differences. By default, it compares the full visible text of the page, stripping out HTML tags and focusing on what a reader would actually see. That default works well for most static or lightly dynamic pages.

Where the tool gets more precise is in its filtering options. Open any watched URL by clicking its name, then go to the Edit tab. Under the Filters and Triggers section, you can supply a CSS selector or XPath expression to watch only a specific part of the page. If you are tracking a product price, you would inspect the page element containing the price and paste that selector into the filter field. From that point on, changes to the page header, navigation, or footer are ignored entirely – only the targeted element triggers a notification. You can also set text to ignore, which is useful for pages that include timestamps or ad content that updates constantly and would otherwise generate false alerts.
Check frequency is set per-URL or globally. The global default is under Settings > General, where you can set the interval in minutes or hours. Individual URLs can override that setting on their own Edit tab, so a high-priority page can check every five minutes while a slower-moving one checks daily. Keep in mind that aggressive check intervals on public websites can look like bot traffic to the server. Staying above a five-minute interval and using the built-in request headers to identify your instance politely is a reasonable practice.
Setting Up Notifications So Alerts Actually Reach You
Changedetection.io uses the Apprise library for notifications, which means it can send alerts to a wide range of services including email via SMTP, Slack, Telegram, Discord, Gotify, Ntfy, Pushover, and many others. All of these are configured through a single notification URL format inside Settings > Notifications. For example, a Telegram notification URL follows the format tgram://bot-token/chat-id, and an Ntfy URL looks like ntfy://your-ntfy-server/topic-name. You can add multiple notification endpoints and every watched URL will alert all of them by default, or you can override notifications per URL to route specific pages to specific channels.
The notification message itself is customizable. Changedetection.io supports a templating system where you can include the page title, the URL, a preview of what changed, and a direct link to the diff view inside your instance. That diff view is where the real value shows up – it displays a side-by-side or inline comparison of what was removed and what was added, highlighted in red and green, so you can see exactly what shifted on the page without visiting it yourself. Previews of recent changes are also stored in your datastore volume, so you have a rolling history of what each page looked like at previous check points.
For pages that require JavaScript rendering – single-page applications, React-heavy storefronts, anything that loads content dynamically after the initial HTML response – the standard fetch mode will not capture the real content. Changedetection.io supports connecting to a Playwright-based browser instance via the playwright-chrome container. Add that container to your Docker Compose file, set the PLAYWRIGHT_DRIVER_URL environment variable to point at it, and switch any affected URL’s fetch mode to Chrome/JS under its edit settings. The container handles the headless browser session and returns the fully rendered page for comparison.

At the point where your instance is running, your pages are filtered, and your notifications are routing to the right place, Changedetection.io is doing the kind of continuous monitoring that would cost real money through a SaaS service – and it is doing it on hardware you already own, at check intervals you set, with no cap on how many URLs you can watch.





