You keep manually refreshing a page to see if the site is down, if a price moved, or if an API metric crossed a line — and you still miss the moment it happens.
watchtower does the watching for you: declare what to check, and it polls on a schedule, detects when something actually changes, and alerts you once per change — not on every poll, and not at 3am for something that's been the same for an hour. Website uptime, page-content changes, and JSON/API fields. Dependency-free core, one YAML file.
checks (http / content / json) ─► detect change ─► dedup ─► notify (console / telegram / webhook)
| Check | Use it for |
|---|---|
| http | Uptime, status code, and latency of a URL. Alerts on down / wrong code / too slow. |
| content | A page's content changing — docs, pricing, stock, listings. Watch the whole page or just a region via a regex extract. |
| json | One field in a JSON API. Alert on any change, on a mismatch vs an expected value, or when a number crosses a threshold. |
- Alert dedup — one alert when a site goes down, not one per poll for the hour it stays down. Plus a recovery alert when it comes back.
- Persistent state — remembers last values across restarts (atomic JSON write, never corrupts).
- Pluggable notifiers — console (default), Telegram, or any webhook (Slack/Discord-compatible).
- Dependency-free core — HTTP via the standard library. PyYAML is optional (JSON config works without it).
- Won't die on one bad check — a failing check is reported as an error; the rest keep running.
See it work offline, no setup:
git clone https://github.com/YuuGR1337/watchtower
cd watchtower
python examples/quickstart.py--- cycle 3 ---
🔔 [CHANGED] demo-price — price 100 -> 80
...
Notice: an alert fired only on the CHANGE (cycle 3), not every cycle.
Edit a config and run it:
python -m watchtower --config examples/watchtower.example.yml # loop
python -m watchtower --config examples/watchtower.example.yml --once # one pass (cron)interval: 60
state_file: watchtower-state.json
notifiers:
- type: console
- type: telegram
bot_token: "123:abc"
chat_id: "456"
checks:
- type: http
name: homepage
url: https://example.com
max_latency_ms: 3000
- type: content
name: pricing
url: https://example.com/pricing
extract: '<main[^>]*>(.*?)</main>' # watch only this region
- type: json
name: error-rate
url: https://api.example.com/health
field: metrics.error_rate
threshold: 0.05
comparison: lt*/5 * * * * cd /path/to/watchtower && python -m watchtower -c watchtower.yml --oncefrom watchtower import Watchtower, HttpCheck, ContentChangeCheck, StateStore
from watchtower import ConsoleNotifier, TelegramNotifier
wt = Watchtower(
checks=[
HttpCheck("homepage", "https://example.com", max_latency_ms=3000),
ContentChangeCheck("pricing", "https://example.com/pricing"),
],
notifiers=[ConsoleNotifier(), TelegramNotifier(bot_token="...", chat_id="...")],
state=StateStore("state.json"),
interval=60,
)
wt.run_once() # one pass — good for cron
# wt.run_forever() # long-running loopAdd your own check by writing a class with a name and a run(previous_value) method that returns a CheckResult. Same for notifiers (send(alert)).
pip install pytest
pytestThe suite runs fully offline (fake checks) and covers alert dedup, recovery, state persistence, threshold comparison, nested JSON extraction, and crash isolation.
watchtower is a good fit if you need to:
- monitor website uptime and get a Telegram/Slack alert the moment a site goes down
- track a price or stock change on a product page and be notified when it moves
- detect website content changes — docs, pricing, listings, job boards
- monitor a JSON/REST API field and alert when a metric crosses a threshold
- run a self-hosted, zero-dependency uptime monitor instead of a paid SaaS
- add scheduled health checks via cron to a server or VPS with one config file
A lightweight, self-hosted alternative to website-monitoring and change-detection services — you own it, it runs anywhere Python runs.
- More checks: TCP port, DNS record, SSL-cert expiry, keyword-present/absent
- More notifiers: email (SMTP), PagerDuty
- Optional concurrency for large check sets
MIT — see LICENSE.