Jump to content

PulseWatch

From Pulsed Media Wiki

PulseWatch keeps a running record of the Pulsed Media store on your own machine: whether each product can be ordered, its prices, and every change between checks. It reads the public data feeds, where the product feed lists 112 products with their live stock counters (as of 20 October 2026) and is rebuilt every 15 minutes. It is a community-made, open-source tool by GitHub user HopperHopper; Pulsed Media did not create it and does not maintain it.

What it does

PulseWatch checks the catalog every five minutes and stores one observation per product. From those it keeps a change log of restocks, sell-outs, price drops, price rises and products that leave the catalog. A web page on your machine shows the catalog with filters, sort orders and an availability sparkline per product, a page per product with its history, the change log, and a list of every check. An RSS feed of recent changes and a JSON API serve scripts and other tools.

PulseWatch has no e-mail or push alerts of its own. To hear about a restock as it happens, subscribe to its RSS feed in a reader that notifies on new items. On the main branch as of 20 October 2026 that feed is noisier than its labels: any drop in stock is logged as a sell-out even when units remain, and a product that has left the catalog is logged as removed again at every check. The open pull request (below) fixes both.

It runs on the Python standard library alone, with no packages to install. The data lives in SQLite under ./data/ in the project directory. The project page has screenshots of the catalog and the change log.

How it reads the store

Each check fetches three feeds: the product catalog, the dedicated-server pricing and the product specifications. The catalog comes from https://pulsedmedia.com/data/v1/products.json, which lists the products the store offers, plus some that its category pages no longer show:

  • available says whether the product can be ordered now: it has no stock limit, or its stock is above zero.
  • stock is the store's own stock counter and is sent only when stock_managed is true; otherwise it is null and the product has no stock limit. For a stock-managed product, at 0 or below nothing is on sale, and a negative value is an internal marker, not a count of waiting orders.
  • Prices are in euros, keyed by billing cycle. A few products, such as special offers, are sold only yearly or for longer and have no monthly price.
  • The storefront's "Starting from" price can be higher than the feed's, for products with required options: the store adds the cheapest of them, while the feed publishes the base price.

Categories are not in the feed. PulseWatch learns them from the storefront pages and puts products the storefront does not show into its own "Unlisted" category. Once a day it compares the feed with the storefront and reports the differences on its About page.

When a feed cannot be reached, the project's main branch uses its last saved copy of that feed if the copy is less than 24 hours old, and records the check as successful. Only without such a copy does it fall back to reading the storefront pages. A check that ran on an old copy therefore looks the same as a fresh one; compare the feed timestamp shown at the top of the catalog with the current time.

Running it

PulseWatch needs Python 3.11 or newer. Check first:

python3 --version

Then fetch it into your home directory and run one check, followed by the web page:

cd ~
git clone https://github.com/HopperHopper/PulseWatch.git
cd PulseWatch
python3 -m pmwatch scan
python3 -m pmwatch serve --port 8787

The page answers on http://127.0.0.1:8787 on the same machine. To open it from your desktop when PulseWatch runs on a server, use an SSH tunnel: ssh -L 8787:127.0.0.1:8787 you@your-server, then browse to http://127.0.0.1:8787 on the desktop.

The project's deploy/install.sh sets up three systemd user services. User services stop when you log out unless lingering is enabled for your account (loginctl enable-linger), which on many machines needs an administrator. Where lingering is not available, these crontab lines do the same jobs:

*/5 * * * * cd $HOME/PulseWatch && python3 -m pmwatch scan --min-interval 240 >> data/cron.log 2>&1
@reboot cd $HOME/PulseWatch && python3 -m pmwatch serve --host 127.0.0.1 --port 8787 --interval 300 >> data/web.log 2>&1
17 4 * * * cd $HOME/PulseWatch && python3 -m pmwatch verify >> data/verify.log 2>&1

The first line is the five-minute check, the second starts the web page after a reboot, and the third is the daily comparison. --min-interval 240 makes a check skip itself when the previous successful one ran less than four minutes earlier. Started with --interval 300, the web page also runs a check of its own when none has happened for a few minutes, and the same guard keeps the two from doubling the cadence.

To update, run git pull in the project directory and restart the web page: with systemd, systemctl --user restart its service; with cron, stop the running pmwatch serve process and start it again with the command from the @reboot line. git log -1 shows which version you have.

On a seedbox

A Pulsed Media seedbox can run PulseWatch from your own account with the crontab lines above, provided its python3 --version shows 3.11 or newer. A seedbox is a shared server: anything listening on 127.0.0.1 there can be reached by the other accounts on it, and port 8787 may already be taken. Pick an unused port above 1024 (ss -tlnp lists the ones in use) and pass it with --port. Self-Hosted Apps on PMSS explains the same loopback rules for other programs.

Treat the page as visible to the other users of that server. Until the fixes below are in the version you run, any of them can also start the daily comparison on your instance whenever they like, and each run fetches the feeds and eight store pages from your account. To avoid that, keep only the five-minute check line in the crontab and start the web page by hand when you want to look at it.

Using it safely

What Details
Reads The public data feeds and, as a fallback and for the daily comparison, the public storefront pages. No login is used and nothing is ordered
Stores on its own machine Its SQLite database, logs, cached copies of the feeds and a generated token under ./data/
Serves The web page, the RSS feed and the JSON API on 127.0.0.1, port 8787 by default
Publishes, only if you choose it With install.sh --with-tunnel, the whole site and API on a public Cloudflare quick-tunnel address, with no login
  • Do not publish it with --with-tunnel for now. As of 20 October 2026 the project's main branch can be made to run script in the catalog page through a crafted address, and lets anyone who can reach it start a comparison run that fetches the store pages from your machine. The tunnel has no login, so it hands both to the whole internet. Keep PulseWatch on 127.0.0.1 and open it through an SSH tunnel.
  • Do not open PulseWatch links that other people send you. The crafted-address weakness also works on 127.0.0.1, through your own browser.
  • A web page in your browser can reach it too. Pages you visit can send requests to 127.0.0.1, so on the main branch they can start comparison runs. Start the web page only while you use it if that matters to you.
  • Store links carry a referral id by default. Links from PulseWatch to the store go through a hand-off page that credits the project's default referral id (7350) under the Pulsed Media Affiliate Program, so the owner of that id earns commission on orders placed through those links. For personal use, start PulseWatch with PMWATCH_AFFILIATE_ID= (set but empty) so no referral is credited; on the main branch the hand-off page still appears, with an empty first link, so use its second link to go to the product. Your own affiliate number only makes sense on an instance other people use: orders you place through your own id are self-referrals and earn nothing.
  • Leave the check frequency at five minutes. Each check already sees every feed rebuild; checking more often fetches the same data again.

The fixes for the crafted-address script and the open comparison run are in an open pull request (below). The tunnel still has no login after them. If the author merges it, git pull brings the fixes in; check the pull request's status first.

Troubleshooting

The web page does not start and the log shows "Address already in use". Another program has the port. Start it with another --port.

python3 --version shows a version older than 3.11. PulseWatch does not support it. Run it on a machine with a newer Python.

The page stops updating after you log out. The systemd user services stopped. Enable lingering or use the crontab lines above.

The catalog looks current but the feed timestamp at the top is hours old. The feeds could not be reached and PulseWatch is running on its saved copy. Check that the machine can reach pulsedmedia.com; the next successful check brings the catalog up to date.

License and source

PulseWatch is released under the MIT License. Source and the issue tracker are at github.com/HopperHopper/PulseWatch. Report bugs and feature requests there, not to Pulsed Media support.

At Pulsed Media

The feeds PulseWatch reads need no key or account. They come without an availability guarantee, and their contents may change; the feeds page describes every feed and its fields. Feed responses carry ETag and Last-Modified headers, so a client can ask whether a feed changed and get a short "not modified" answer when it did not.

Fixes submitted by Pulsed Media

On 20 October 2026 Pulsed Media read the project's source and submitted fixes as pull request #1. The changes users notice most:

  • the catalog's page links are escaped, and the manual comparison run needs a token and has a cooldown;
  • a check that ran on a stale feed is marked as such;
  • negative stock is no longer shown as a backorder count, and the storefront's "Starting from" price is explained;
  • products without a monthly price get a price history;
  • store links land on the product's order form.

The pull request also adds conditional feed requests and tests that run the real code. As of 20 October 2026 it is open. Pulsed Media has not run PulseWatch on its own machines; the fixes were tested by the project's own CI on a fork. Submitting fixes is not an endorsement.

AI credits for tools like this

Pulsed Media accounts with an active service earn AI credits from the invoices they pay, and can buy more on the Virsilipas page. One million credits is 1 € of allowance. Among the models, DeepSeek-V4.1-Flash (alias alt) charges a fifth of the default model's rate for cached input, as of October 2026, which suits coding tools that resend a long conversation with every request. virsilipas.mcx.fi shows live usage across all customer keys, and Using Pulsed Media AI Credits on Any Linux Server shows how to connect a tool to your key.

Seedbox plans are listed on the seedbox page; live stock and current prices for every product are on pulsedmedia.com, which is what PulseWatch reads.

See also