Build a local Windows setup that watches prices, job listings, appointments, and other website changes, then sends notifications to your phone.

Category: Tutorials | Difficulty: Intermediate | Platform: Windows 10 and Windows 11
Tools: changedetection.io, ntfy, Docker Desktop | Author: Zoran Knežević
Many websites change content without sending an email, publishing an RSS update, or providing any other notification. The change might be a product price, stock status, new job listing, public notice, result, appointment slot, software release, or a single important sentence on a page.
Instead of opening the same page several times a day, you can build a system that will:
- check a URL on a schedule;
- extract only the part of the page you care about;
- compare the new content with the previous version;
- keep a history of changes;
- send a notification to your phone when it detects a relevant difference.
This guide uses two free, open-source tools:
- changedetection.io to check and compare pages;
- ntfy to send notifications to a phone or computer.
The setup runs locally on a Windows PC. You do not need to write a program, build a mobile app, or give each website your email address.
Important: The PC running changedetection.io must be powered on, connected to the internet, and awake when a scheduled check is due. Checks do not run while the computer is shut down or asleep.
What can you monitor?
Almost any publicly accessible text, for example:
- the price of a product;
- the appearance of an “In stock” label;
- the disappearance of “Sold out”;
- a new job listing;
- a public call posted by an institution;
- competition results or a ranking list;
- newly available appointment slots;
- a change to a policy or terms of service;
- a new software release;
- a change to a PDF document;
- a change to a public API's JSON response;
- the appearance of a specific word or name on a page.
changedetection.io supports CSS and XPath selectors, JSON monitoring, text triggers, conditional actions, check schedules, change history, and pages that require JavaScript.
How the system works
changedetection.io fetches a page and saves an initial snapshot.
That first snapshot becomes the baseline and usually does not trigger a notification.
On the next check, the tool creates a new snapshot. If the content has changed, it calculates the difference and checks your filters and conditions. If the change matches your rules, it sends a message through ntfy and your phone displays a notification.
The key is to avoid monitoring the entire page when you do not need to.
Headers, ads, visit counters, recommended products, clocks, cookie notices, and rotating banners may change every time a page loads. We will extract only the price, listing, or other specific element that matters.
What you need
For this guide, you need:
- Windows 10 or Windows 11;
- Docker Desktop;
- a web browser;
- an Android or iPhone;
- the ntfy app or ntfy web app;
- the public URL of the page you want to monitor.
Download Docker Desktop from the official Docker website.
After installing it, start Docker Desktop and wait for the Docker engine to become available.
Check the Docker installation
Open PowerShell and run:
docker version
docker compose version
Both commands should display information about the installed versions.
If PowerShell cannot find docker, check that Docker Desktop is running, then reopen PowerShell.
Create a project directory
Create a dedicated directory in PowerShell:
New-Item -ItemType Directory -Path "C:\changedetection" -Force
Set-Location "C:\changedetection"
We will keep the Docker Compose configuration in this directory.
The application data will live in a separate Docker volume, so it will survive a routine update or container recreation.
Create the Docker Compose configuration
In C:\changedetection, create a file named compose.yaml with this content:
services:
changedetection:
image: ghcr.io/dgtlmoon/changedetection.io:0.60.9
container_name: changedetection
hostname: changedetection
ports:
- "127.0.0.1:5000:5000"
volumes:
- changedetection-data:/datastore
environment:
- TZ=Europe/Belgrade
- PLAYWRIGHT_DRIVER_URL=ws://browser-sockpuppet-chrome:3000
- FETCH_WORKERS=2
- MINIMUM_SECONDS_RECHECK_TIME=60
depends_on:
browser-sockpuppet-chrome:
condition: service_started
restart: unless-stopped
browser-sockpuppet-chrome:
image: dgtlmoon/sockpuppetbrowser:latest
container_name: changedetection-browser
hostname: browser-sockpuppet-chrome
environment:
- SCREEN_WIDTH=1920
- SCREEN_HEIGHT=1080
- SCREEN_DEPTH=16
- MAX_CONCURRENT_CHROME_PROCESSES=2
shm_size: "2gb"
restart: unless-stopped
volumes:
changedetection-data:
name: changedetection-data
The Serbian source guide pinned changedetection.io to version 0.60.2. As of October 17, 2026, the project's official release list shows 0.60.9 as the latest release, so this English example uses that version. Check the official release list before installing or upgrading, since the latest version can change.
Pinning a specific version makes the application version explicit when Docker pulls the image again.
This configuration starts:
- the changedetection.io dashboard;
- a separate Chrome service for JavaScript-heavy pages;
- a persistent volume for settings and history;
- up to two parallel HTTP workers;
- a minimum recheck interval of 60 seconds.
The dashboard is bound to 127.0.0.1, so it is not exposed to other devices on your network or to the public internet.
Do not change the address to 0.0.0.0 unless you have first configured authentication and HTTPS protection.
Validate the configuration
Before starting the containers, check that compose.yaml is valid:
Set-Location "C:\changedetection"
docker compose config
If the command prints the resolved configuration without an error, the YAML structure is valid.
Incorrect indentation is a common cause of errors. YAML uses spaces, not tab characters.
Start the system
Pull the images and start the containers:
docker compose pull
docker compose up -d
Check their status:
docker compose ps
Both services should show a status such as Up or Running.
To view recent log messages:
docker compose logs --tail 100
Then open the dashboard:
Start-Process "http://127.0.0.1:5000"
You can also open it manually at:
http://127.0.0.1:5000
If the changedetection.io dashboard appears, the basic installation is complete.
Keep checks running after a restart or during sleep
The restart: unless-stopped setting starts the containers again when the Docker engine starts. Docker Desktop itself still needs to be running.
In Docker Desktop settings, enable:
Start Docker Desktop when you sign in to your computer
In Windows settings, open:
Settings > System > Power & battery > Screen and sleep
If you want uninterrupted monitoring, configure the PC not to sleep while it is plugged in.
The display can turn off. The computer itself must remain awake.
Configure ntfy notifications
ntfy uses channels called topics.
A message sent to a topic reaches every device subscribed to the same name.
On the public ntfy.sh server, the topic name effectively acts like a secret address. Do not use an obvious name such as:
moje-obavestenje
test
zoran
Generate a hard-to-guess name in PowerShell:
$Topic = "web-alert-" + [guid]::NewGuid().ToString("N")
$Topic
The output will look something like this:
web-alert-7c4593439d994024ad7408fe6d93f1ab
Save the value you generated. Do not use the sample topic shown above.
Subscribe to the topic on your phone
- Install the ntfy app from Google Play, F-Droid, or the App Store.
- Open the app.
- Choose the option to add a subscription.
- Leave the server as
https://ntfy.sh. - Enter the topic you generated.
- Confirm the subscription.
A public topic does not require registration for basic use.
However, a public topic name is not real access control. Anyone who knows the exact name may be able to read messages or publish to it.
Do not send the following through a public topic:
- passwords;
- access codes;
- personal information;
- content from private pages;
- confidential business information.
Send a test notification manually
Replace YOUR_TOPIC in this command with the topic you generated:
Invoke-RestMethod `
-Method Post `
-Uri "https://ntfy.sh/YOUR_TOPIC" `
-Headers @{
Title = "Notification test"
Priority = "high"
Tags = "white_check_mark"
} `
-Body "The connection between the Windows PC and phone is working."
If everything is configured correctly, your phone should display the test message.
If it does not arrive, check:
- that the topic matches exactly on the PC and phone;
- that ntfy is allowed to display notifications;
- whether Android restricts the app from running in the background;
- that both devices have an internet connection.
ntfy messages are ordinary HTTP POST or PUT requests. You can use the same channel later for PowerShell scripts, backup jobs, home servers, and other applications.
Connect changedetection.io to ntfy
In the changedetection.io dashboard, open:
Settings > Notifications
The notification URL for a public ntfy.sh topic looks like this:
ntfy://YOUR_TOPIC
You can set a higher priority and request Markdown formatting:
ntfy://YOUR_TOPIC?priority=high&format=markdown
changedetection.io uses the Apprise notification system. For a public ntfy.sh server, the ntfy://topic format is sufficient.
Choose the option to send a test notification.
Save the settings only after the test message arrives on your phone.
Notifications can be configured globally or separately for each watch. Global settings are simpler, while separate topics can provide distinct channels for:
- prices;
- job listings;
- appointments;
- important alerts.
Test a real change
A test notification confirms only the connection to ntfy. It does not confirm that the system can correctly fetch, compare, and process pages.
For a temporary functional test, use this public JSON endpoint:
https://httpbin.org/uuid
It returns a new UUID value each time it is requested.
Follow these steps:
- Add
https://httpbin.org/uuidas a new watch. - Wait for the first check.
- The first value becomes the baseline snapshot.
- Select
Check now. - Wait for the second check to finish.
- Open the Difference view.
- Confirm that the UUID changed.
- Check whether the ntfy notification arrived.
Delete this watch after the test. Its content changes on every check, so it would otherwise keep sending notifications.
If the test succeeds, you have confirmed four parts of the system:
- fetching a page;
- saving the initial snapshot;
- detecting a difference;
- sending an ntfy notification.
Add your first real page
The changedetection.io home page has a field for entering a URL.
- Enter the public page URL.
- Select
Watch. - Wait for the first check to finish.
- Open
Edit. - Check the
Preview. - Set the check interval.
- Save the settings.
For simple pages, start with the faster built-in HTTP fetcher.
For a price or job listing, checking every 30 or 60 minutes is usually enough.
Do not check every few seconds. That can put unnecessary load on a website and may result in temporary blocking.
Monitor a product price
There are two basic ways to monitor a product.
Method A: built-in price detection
Many online stores include structured data in their HTML with the price, currency, and availability status.
changedetection.io may recognize this data and offer a Re-stock & Price detection option.
If the option is available:
- Open
Edit. - Enable price and availability tracking.
- Check the detected currency.
- Check the detected amount.
- Enter a lower or upper price limit.
- Save the settings.
- Select
Check now.
For example:
Send a notification when the price drops below 50,000.
In the Conditions tab, you can select the extracted number and use the less than operator.
Select the option to test the condition. The interface should show which number it extracted and whether the rule currently passes.
Method B: monitor only the price element
If automatic detection does not work:
- Change the fetch method to Chrome or Playwright.
- Save the setting.
- Run a new check.
- Open
Edit. - Select
Visual Filter Selector. - Click directly on the product price.
- Check the
Preview. - Save the selector.
The result should contain only the price, for example:
49.999 RSD
If the preview also contains the title, description, recommendations, and other products, the selector is too broad.
Manual CSS selector
If Visual Selector does not choose the right element, enter a CSS selector manually:
.product-price
Another example:
.product-details .current-price
Manual XPath selector
You can also use XPath:
//span[contains(@class, 'price')]
Class names and HTML structures vary between websites. These example selectors will not automatically work for every store.
Important notes about price tracking
Some stores show different prices depending on:
- location;
- whether you are signed in;
- the selected store;
- cookies;
- loyalty program membership;
- delivery options;
- currency;
- an active coupon.
Check the Preview to confirm that changedetection.io sees the same price you expect.
If an element contains both the old and new price, a condition may extract the wrong number. Narrow the selector to the current price only.
Monitor a new job listing or public call
Do not monitor an institution's entire home page for a job listing. Monitor the page that contains its vacancies, announcements, or public calls.
Follow these steps:
- Add the URL of the listings page.
- Open
Edit. - Use Visual Selector to select only the list of posts.
- Open
Filters & Triggers. - Find
Text filtering. - Enable the relevant change types.
- Add keywords if needed.
- Set the check interval to 30 or 60 minutes.
- Save the settings.
- Check the
Preview.
To receive alerts about new content, enable:
Added lines
Replaced or changed lines
Leave Removed lines disabled if you do not care when old listings are removed.
changedetection.io recommends enabling both added and changed lines because the way a text difference is classified depends on how similar the old and new content is.
If you do not want the same listing to trigger again after its order changes, enable:
Only trigger when unique lines appear
This option checks whether a new line has already appeared in the saved history.
Keywords
You can add phrases such as:
developer
administrator
IT support
remote
public call
job listing
Keyword triggers are case-insensitive.
A notification is sent when both of these conditions are met:
- the page has changed;
- the new extracted content matches a keyword.
The fact that a keyword is already present on the page does not mean a notification will be sent on every check.
Monitor when specific text appears
To get an alert when a phrase appears, add it under Filters & Triggers:
Applications are open
Available
New appointment
Rezultati job listinga
In stock
For a more precise rule, open Conditions and select:
Text contains
Then enter the phrase you want to detect.
The condition could be:
Extracted text contains "In stock".
Use the condition test to confirm whether the rule currently passes.
Monitor when specific text disappears
Set up a disappearance alert differently from an appearance alert.
To get an alert when Sold out disappears, use one of these approaches.
Option A: removed lines
Under Text filtering, enable:
Removed lines
Then use a filter or selector that includes the product status.
This approach is useful when you want to see which text was removed.
Option B: a condition that the current content no longer contains the phrase
In the Conditions tab, select:
Text does not contain
Enter:
Sold out
The notification is sent when the page changes and the current extracted content no longer contains that phrase.
Make sure the monitor includes the correct status element. If the selector does not include Sold out, the condition will appear to pass from the beginning.
Combine multiple conditions
Conditions can use AND or OR logic.
An example using AND:
Text contains "In stock"
Extracted price is less than 50,000
A notification is sent only when both conditions pass.
An example using OR:
Text contains "Job listing"
Text contains "Public call"
Text contains "Job opening"
A notification is sent when at least one condition passes.
Test each condition individually before leaving the watch to run automatically.
JavaScript-driven pages
If the Preview does not show a price or list that you can see in your browser, the website may load that content only after JavaScript runs.
In the page settings, change the fetch method from the fast HTTP request to Chrome or Playwright.
The Chrome method uses the second service in the Compose configuration. It is slower and uses more memory, but it can:
- run JavaScript;
- wait for dynamic content;
- capture screenshots;
- use Visual Selector;
- perform simple browser steps.
Do not use the Chrome method for every watch if the regular HTTP fetcher already returns the content you need.
Cookie notices, location selection, and Browser Steps
Some pages show these before their content:
- a cookie notice;
- country selection;
- store selection;
- language confirmation;
- a button to display results;
- a search field.
You can add steps in the Browser Steps tab, such as:
- click the button to accept cookies;
- select a country;
- enter text in a field;
- click the search button;
- wait for the result to appear.
After the steps run, open Visual Selector and select the resulting content.
Monitoring pages behind a sign-in requires extra care. A saved session may contain account cookies. For sensitive accounts, use the site's official notification or API if one is available.
Reduce false alerts
The most common problem is not missing a change, but receiving too many irrelevant alerts.
If an alert arrives on almost every check, common causes include:
- the current time;
- the date of the last visit;
- an advertisement;
- a randomized product recommendation;
- a view counter;
- a rotating banner;
- shopping cart state;
- a session identifier;
- dynamically reordered results;
- a different cookie notice;
- an automatically generated parameter.
To reduce noise:
- monitor only the smallest part of the page that matters;
- use Visual Selector;
- use a precise CSS or XPath selector;
- add changing content to
Ignore Text; - ignore whitespace-only changes;
- enable only added and changed lines if removals do not matter;
- inspect the Difference view after each false alert.
A well-configured price monitor should compare only:
49.999 RSD
It should not compare the complete HTML document with hundreds of changing elements.
Final reliability check
For each watch, check that:
Previewshows the exact content you want.- The initial snapshot was saved successfully.
Send test notificationreaches your phone.Check nowcompletes without an error.- The Difference view does not contain ads, dates, or other incidental changes.
- The check interval is not unnecessarily short.
- The fetch method suits the page.
- The topic is identical on your phone and in changedetection.io.
- The text filter watches the relevant change types.
- Each condition passes its individual test.
- Windows does not go to sleep.
- Docker Desktop starts automatically.
Leave a watch running automatically only after these checks pass.
Back up settings and history
Before a major update, it is useful to back up the Docker volume.
Open PowerShell:
Set-Location "C:\changedetection"
docker compose stop
Create an archive of the volume:
docker run --rm `
-v changedetection-data:/source:ro `
-v "${PWD}:/backup" `
alpine:latest `
sh -c "tar -czf /backup/changedetection-backup.tar.gz -C /source ."
Start the services again:
docker compose start
The following file should appear in C:\changedetection:
changedetection-backup.tar.gz
The archive contains settings, the list of monitored pages, and saved history.
Update the application
Because the Compose file specifies a particular version, updates are performed deliberately.
When a newer stable release is available:
- check the official release page;
- create a backup;
- change the version in
compose.yaml; - validate the configuration;
- pull the new image;
- restart the service.
Commands:
Set-Location "C:\changedetection"
docker compose config
docker compose pull
docker compose up -d
docker compose ps
Stop and restart
Temporarily stop the services:
docker compose stop
Start them again:
docker compose start
Restart the services:
docker compose restart
Remove the containers and network:
docker compose down
This command does not remove the named volume.
Do not add the -v option if you want to keep your settings and history.
Common problems
The dashboard does not open
Check:
docker compose ps
docker compose logs --tail 100 changedetection
If port 5000 is already in use, change the port mapping:
ports:
- "127.0.0.1:5050:5000"
Then open the dashboard at:
http://127.0.0.1:5050
The browser container keeps restarting
Check:
docker compose logs --tail 100 browser-sockpuppet-chrome
Then check that Docker Desktop has enough memory and that shm_size is set correctly.
On some platforms, the official configuration notes that the Chrome container may require the additional SYS_ADMIN capability. Do not add it automatically because it gives the container broader privileges. Check the logs and the documentation for your platform first.
The price appears in the browser but not in Preview
Switch the fetch method to Chrome or Playwright.
If the price still does not appear, the page may require:
- accepting cookies;
- selecting a location;
- choosing a store;
- clicking a button;
- a signed-in account.
A notification arrives on every check
Open the Difference view and find the element that keeps changing.
Narrow the selector or add that element to Ignore Text.
The ntfy test works, but real alerts do not arrive
Check:
- whether the notification URL is correct;
- whether notifications are enabled for that watch;
- whether anything changed after the initial snapshot;
- whether the filter accepts that type of change;
- whether the condition passes;
- whether
Previewcontains the expected text; - what the logs show.
To view the main application logs:
docker compose logs --tail 200 changedetection
The first check did not send a notification
That is expected.
The first check creates the initial snapshot. A notification is sent only when a later snapshot contains a relevant change.
The website returns 403, 429, or a CAPTCHA page
The website has rejected or limited the automated request.
Increase the interval and check the site's terms of use.
This guide is not intended to bypass CAPTCHA, authentication, or restrictions set by a website owner.
Notifications arrive late on Android
Check:
- notification permissions;
- battery optimization;
- background activity restrictions;
- Data Saver settings;
- notification cooldown;
- the sound and priority of the ntfy channel.
Privacy and responsible use
With a local installation, the list of monitored pages and change history are stored in a Docker volume on your computer.
When you use the public ntfy.sh service, notification content passes through that service.
Keep messages limited to the information you need, for example:
The product price has changed. Open the monitored page.
Do not include personal information, access codes, or private page content in notifications.
Follow the rules of the website you monitor. The changedetection.io project states that users are responsible for complying with:
- terms of service;
- access policies;
- robots.txt guidance;
- applicable laws.
A reasonable check interval and monitoring only the necessary part of a page are both technically and ethically sound practices.
Conclusion
The combination of changedetection.io and ntfy solves a common problem: important information appears on a website, but the site has no notification system of its own.
Once configured, the system can automatically monitor:
- prices;
- product availability;
- public calls;
- job listings;
- appointments;
- results;
- documents;
- the appearance or disappearance of specific text.
It keeps a history of changes and sends messages directly to your phone.
The most important part is not simply adding a URL. A reliable monitor needs a precise selector, a reasonable interval, correctly configured conditions, and a successful test showing that a real change triggers an alert.
Once everything is set up properly, you no longer need to open the same page several times a day.
Official resources
- changedetection.io project
- changedetection.io release 0.60.2 referenced by the original guide
- changedetection.io release 0.60.9
- Official Docker Compose configuration
- Monitor keywords
- Monitor new website content
- Conditional actions
- ntfy documentation
- Publishing ntfy messages
- Apprise documentation
- Docker Desktop documentation
Share your thoughts, questions, or tips about this article.