Check a Web Page for Changes#
Watch a page and get told when it changes. This job fetches the page, compares it with the copy it saw last time, and only alerts on a difference, so you are not pinged on every run.
The Script#
// watch-page.js
import fs from "fs";
const target = "https://example.com/";
const stateFile = "/watch-page.txt";
// djb2: a small, fast string hash. It walks the text one character at a
// time, mixing each into a 32-bit accumulator, and returns a short hex
// fingerprint. Deterministic (same input, same output) but not
// cryptographic: good for spotting changes, not for security.
function hash(text) {
let h = 5381; // Seed. Any odd starting value works.
for (let i = 0; i < text.length; i++) {
// Multiply by 33 and mix in the next character code.
h = (h * 33) ^ text.charCodeAt(i);
}
// Coerce to an unsigned 32-bit integer, then render it as hex.
return (h >>> 0).toString(16);
}
const res = await fetch(target);
const html = await res.text();
const current = hash(html);
let previous = null;
try {
previous = await fs.readTextFile(stateFile);
} catch {
// First run: nothing stored yet.
}
if (previous === null) {
console.log("Baseline stored for the first time");
} else if (previous !== current) {
console.log("The page changed");
} else {
console.log("No change");
}
await fs.writeTextFile(stateFile, current);
How It Works#
- Instead of storing the whole page, the job stores a short hash of it. That keeps the state file tiny and the memory use flat.
- The
hashfunction is the classic djb2 algorithm. It starts from a seed and folds each character into a 32-bit accumulator, so any length of input becomes a short, fixed-size fingerprint. - It is deterministic: the same page always produces the same hash, which is what makes comparison possible. It is also fast, and it uses only basic arithmetic.
- It is not cryptographic. Different pages can, in principle, collide to the same hash, and the output says nothing about the input. That is fine here: the job only needs to answer “did this change”, not to secure anything.
- The first run records a baseline and stays quiet; later runs compare against it.
- To add a notification, post to a webhook in the “changed” branch, as in Monitor an Endpoint’s Uptime.
Setup#
Change target to the page you want to watch, then schedule the job.
Once a day (0 9 * * *) is a good default for most pages.