Skip to main content

Monitor web pages for changes from your terminal

Project description

pagemon

Monitor web pages for changes from your terminal.

PyPI version Python versions License: MIT CI

Why pagemon?

  • CLI-first -- designed for developers who live in the terminal
  • Lightweight -- pure Python, no Docker, no browser engine, no background daemon
  • Smart diffing -- strips HTML noise (scripts, nav, timestamps) so you only see real content changes
  • CSS selectors -- watch a specific element instead of the whole page
  • Webhook notifications -- POST JSON to Slack, Discord, or any HTTP endpoint when something changes
  • Zero config -- works out of the box with sensible defaults and a local SQLite database

Features

  • Add, remove, and list monitored URLs
  • Check one or all targets for changes on demand
  • CSS selector support to monitor specific page elements
  • Colored unified diffs in the terminal (via Rich)
  • Snapshot history with content hashes
  • Smart noise filtering (whitespace, timestamps, dates)
  • Webhook notifications on change (Slack, Discord, custom)
  • JSON and CSV export
  • JSON output mode for scripting (--json)
  • Python API for programmatic use
  • SQLite storage -- single file, no server needed

Installation

pip install pagemon

Requires Python 3.10+.

Quick Start

Add a page to monitor:

$ pagemon add https://example.com/pricing --name "Pricing Page" --interval 60
Added: https://example.com/pricing
  Selector: -
  Interval: every 60m

Monitor a specific element with a CSS selector:

$ pagemon add https://example.com/status --name "Status" --selector "div.status-banner"
Added: https://example.com/status
  Selector: div.status-banner
  Interval: every 30m

Check all targets for changes:

$ pagemon check --all
  NEW      Pricing Page
  NEW      Status

After subsequent checks, changed pages show a diff:

$ pagemon check --all
  OK       Pricing Page
  CHANGED  Status
--- previous
+++ current
@@ -1,3 +1,3 @@
-All systems operational
+Degraded performance on API endpoints

List monitored pages:

$ pagemon ls
        Monitored Pages
┌────┬──────────────┬────────────────────┬──────────┐
│ ID │ Name / URL   │ Selector           │ Interval │
├────┼──────────────┼────────────────────┼──────────┤
│  1 │ Pricing Page │ -                  │      60m │
│  2 │ Status       │ div.status-banner  │      30m │
└────┴──────────────┴────────────────────┴──────────┘

View snapshot history:

$ pagemon history https://example.com/status --limit 5
           History: https://example.com/status
┌────┬─────────────────────┬──────────────┬────────┬───────┐
│ ID │ Timestamp           │ Hash         │ Status │  Size │
├────┼─────────────────────┼──────────────┼────────┼───────┤
│  3 │ 2026-03-29T14:30:00 │ a1b2c3d4e5f6 │    200 │   482 │
│  2 │ 2026-03-29T14:00:00 │ f6e5d4c3b2a1 │    200 │   471 │
│  1 │ 2026-03-29T13:30:00 │ 9e8d7c6b5a4f │    200 │   471 │
└────┴─────────────────────┴──────────────┴────────┴───────┘

CLI Reference

pagemon [OPTIONS] COMMAND [ARGS]

pagemon add URL

Add a URL to monitor.

Option Short Default Description
--name -n -- Friendly name for display
--selector -s -- CSS selector to watch a specific element
--interval -i 30 Check interval in minutes

pagemon rm URL

Remove a URL from monitoring.

pagemon ls

List all monitored URLs.

Option Description
--json Output as JSON

pagemon check [URL]

Check for changes. Checks a single URL, or all targets if no URL is given.

Option Short Description
--all -- Check all targets
--json -- Output as JSON
--webhook -w Webhook URL for notifications (or set PAGEMON_WEBHOOK)

pagemon diff URL

Show the latest diff between the two most recent snapshots for a URL.

pagemon history URL

Show snapshot history for a URL.

Option Short Default Description
--limit -l 10 Number of snapshots to show

pagemon export

Export all targets and their latest snapshots.

Option Default Description
--format json Output format: json or csv

pagemon --version

Print the installed version.

Python API

from pathlib import Path
from pagemon.core import PageMon

# Initialize with defaults (SQLite at ~/.pagemon/pagemon.db)
mon = PageMon()

# Or with custom settings
mon = PageMon(
    db_path=Path("/tmp/my-monitor.db"),
    webhook_url="https://hooks.slack.com/services/T.../B.../xxx",
    timeout=15.0,
)

# Add a target
target = mon.add(
    "https://example.com/pricing",
    name="Pricing",
    selector="div.pricing-table",
    interval=60,
)

# Check all targets
results = mon.check_all()
for result in results:
    print(f"{result.target.url}: {result.status.value}")
    if result.diff_text:
        print(result.diff_text)

# Check a single target
result = mon.check(target)

# Get snapshot history
snapshots = mon.get_history("https://example.com/pricing", limit=5)

# Get the latest diff
diff = mon.get_diff("https://example.com/pricing")

# List all targets
targets = mon.list_targets()

# Remove a target
mon.remove("https://example.com/pricing")

# Always close when done
mon.close()

Configuration

pagemon works with zero configuration. All settings can be overridden via environment variables or CLI options.

Variable CLI Option Default Description
PAGEMON_DB --db ~/.pagemon/pagemon.db Path to the SQLite database
PAGEMON_WEBHOOK --webhook / -w -- Webhook URL for POST notifications

The webhook sends a JSON payload on every detected change:

{
  "url": "https://example.com/status",
  "name": "Status",
  "status": "changed",
  "diff": "--- previous\n+++ current\n@@ ...",
  "timestamp": "2026-03-29T14:30:00.000000"
}

How It Works

pagemon follows a simple pipeline for each monitored URL:

Fetch --> Extract --> Diff --> Notify
  1. Fetch -- HTTP GET via httpx with configurable timeout and custom headers
  2. Extract -- HTML is parsed with BeautifulSoup; scripts, styles, nav, and footer elements are stripped. If a CSS selector is set, only matching elements are extracted
  3. Diff -- Content is hashed (SHA-256) for fast comparison. If the hash differs, a normalization pass filters out whitespace and timestamp noise. Only meaningful changes produce a unified diff
  4. Notify -- Changed results are sent to the configured webhook (or printed to the console)

All snapshots are stored in a local SQLite database for history and diffing.

Contributing

Contributions are welcome. To get started:

git clone https://github.com/Ltbltbltbltb/pagemon.git
cd pagemon
pip install -e ".[dev]"
pytest
ruff check src/ tests/

Please open an issue before submitting large changes.

License

MIT -- see LICENSE for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pagemon-0.1.0.tar.gz (20.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pagemon-0.1.0-py3-none-any.whl (13.9 kB view details)

Uploaded Python 3

File details

Details for the file pagemon-0.1.0.tar.gz.

File metadata

  • Download URL: pagemon-0.1.0.tar.gz
  • Upload date:
  • Size: 20.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for pagemon-0.1.0.tar.gz
Algorithm Hash digest
SHA256 ceeac846f447091b75f3d2420e12ed270cb6742fad165712681ed591781629f9
MD5 8a4ddbcb7352bc92a2b166c1dc30616b
BLAKE2b-256 ccb931b064194b148d777c8a8465c44f8fc9d51bf338089fda20fcfec8cf531b

See more details on using hashes here.

File details

Details for the file pagemon-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: pagemon-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 13.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for pagemon-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 2182b01d80aafde305fe8647332c8218ec33b0e0ac8b2329f94cff18b23f2ede
MD5 89b3411a1dab4fb9e472f630e2b37552
BLAKE2b-256 9ef8cf7e9ef7475ce60226e80f4cc332b2c9c1708125418ab611de698a5e1fe1

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page