Watching a page for changes
A script that scans a page on a schedule, compares it with the last capture, and says so only when it changed.
Page Scanner has no watcher of its own, and needs none: scan writes the page's text, diff
compares two captures and exits 1 when they differ, and cron or launchd runs the two on a
schedule. The script below joins them. It keeps the last capture, and a dated copy of the page and
of what changed each time it does change.
#!/bin/sh# watch-page.sh <address> <folder> [heading]# Scans the page, compares it with the last capture, and keeps the new one only when it changed.url=$1dir=$2section=$3mkdir -p "$dir" || exit 2
page-scanner scan --url "$url" --markdown only --main-content --hide all \ --out "$dir/new.md" --wait 120 > /dev/null || exit 2
if [ ! -f "$dir/last.md" ]; then mv "$dir/new.md" "$dir/last.md" exit 0fi
if [ -n "$section" ]; then page-scanner diff "$dir/last.md" "$dir/new.md" --section "$section" > "$dir/changes.diff"else page-scanner diff "$dir/last.md" "$dir/new.md" > "$dir/changes.diff"fistatus=$?
if [ "$status" -eq 1 ]; then stamp=$(date +%Y%m%d-%H%M) cp "$dir/new.md" "$dir/$stamp.md" mv "$dir/changes.diff" "$dir/$stamp.diff" mv "$dir/new.md" "$dir/last.md" echo "$url changed, see $dir/$stamp.diff"else rm -f "$dir/new.md" "$dir/changes.diff"fiexit "$status"Save it as watch-page.sh, chmod +x watch-page.sh, and try it by hand twice:
./watch-page.sh https://example.com/pricing ~/Watch/pricing "Plans > Pro"The first run keeps the capture as last.md. Each run after that exits 0 and leaves nothing
behind when the page is the same, or exits 1, prints one line and writes
20260930-0800.md and 20260930-0800.diff beside it when it changed. It exits 2 when the scan
failed or the two captures could not be compared, and last.md is left as it was.
Keeping out what moves on its own
A page that shows a clock, a visitor count or a "latest posts" rail changes on every load, and a watch on the whole of it reports a change every time. Three things in the script keep that out.
- The heading. The third argument is passed to
diff --section, which compares only the section under that heading, down to the next heading of the same level or higher. A path such as"Plans > Pro"picks a heading under another. On a page with live counters at the top, a whole-page comparison changed on every run and the same two captures compared by one section under them did not. The section is found by its words, not by the page's markup, so a redesign that keeps the heading keeps the watch. --main-contentwrites only the page's main content, leaving out navigation, sidebars and the footer. Ifdiffthen says neither capture has your heading, the heading sits outside what it found: take the flag out of the script.--hide allhides ads, cookie banners, chat widgets and pop-ups before the capture, whatever the extension's settings say, so a rotating ad is not a change.
What none of them can drop is a part that changes on every load inside the section you watch, such
as a label an ad script writes into a table's caption. Pick a heading further down, around less.
Which changes matter is left to you: the .diff is the whole of the answer.
Running it on a schedule
The scheduler is your system's, set up as in On a schedule: Chrome running in the profile you connected, and on the older port-and-token path the daemon started at login. Each run opens the page in a background tab of that Chrome and shows the debugger bar for the length of the scan, so a page you are signed in to is watched signed in.
The script prints one line on stdout when the page changed and nothing when it did not; what
scan and diff say along the way goes to stderr. So whatever runs it can pass that one line on.
cron, every hour at minute 5. cron mails a job's output to MAILTO, and with stderr sent to a
log that output is the one line, only when the page changed:
PATH=/usr/local/bin:/opt/homebrew/bin:/usr/bin:/binMAILTO=you@example.com5 * * * * ~/bin/watch-page.sh https://example.com/pricing ~/Watch/pricing "Plans > Pro" 2>> ~/Watch/watch.logThat needs a computer that can send mail. Without one, add a notification after the echo
instead: osascript -e 'display notification "The pricing page changed" with title "Page Scanner"'
on macOS, notify-send on Linux.
launchd runs it every hour with StartInterval set to 3600 in place of
StartCalendarInterval, and ProgramArguments running ~/bin/watch-page.sh with its arguments
through zsh -lc, as in the morning scan's agent.
Several pages
Give each page its own folder and its own line in the crontab. A folder holds one page's
last.md, so two pages sharing one would be compared with each other.