I lost a deal last month.
Prospect told me my competitor had dropped
their pricing two weeks earlier. Found out
during a live demo. Looked completely
unprepared.
Started looking for a tool to automate this.
Found Visualping, alerts on every pixel
change, completely noisy. Found enterprise
tools at $500+/year. Nothing in between.
So I built one.
The stack
- Next.js 16 (App Router)
- Playwright for scraping
- Supabase for storage
- Resend for emails
- vercel for hosting and cron worker
The hardest part: signal vs noise
Generic page monitoring is easy. Meaningful
change detection is hard.
A pricing page changes constantly, rotating
banners, timestamps, cookie notices, ad content.
If you alert on every pixel diff you're just
building a noise machine.
I built a classification engine that categorizes
changes before deciding whether to alert:
- PRICE_CHANGE — dollar amounts moving
- PLAN_CHANGE — plans appearing or disappearing
- FEATURE_CHANGE — features shifting between tiers
- COSMETIC — everything else (ignored)
The key insight: normalize the text before diffing. Strip dates, times, navigation text, cookie notices, social handles. Then run a line-by-line diff on what's left.
Only PRICE_CHANGE, PLAN_CHANGE, and FEATURE_CHANGE trigger an email.
Why Playwright over Puppeteer
Pricing pages are almost always JS-heavy SPAs. Puppeteer struggles with modern React apps,content loads after the initial HTML response.
Playwright with waitUntil: 'networkidle' plus a 2 second additional wait handles even the most aggressive lazy-loading. Worth the slightly heavier dependency.
The cron worker
Runs at 9am daily. Processes monitors sequentially with a 3 second delay between each — not parallel. Parallel scraping gets you rate-limited and blocked fast.
On first run: saves a baseline snapshot. On subsequent runs: diffs against the previous snapshot, classifies the change, sends alert if significant
What I'd do differently
The diff algorithm is the weakest part right now. Line-by-line text diff catches most changes but misses subtle restructuring, when a competitor moves a feature to a different plan section without changing the text, the diff doesn't catch it cleanly.
Next step is extracting structured data (plan name → price → features[]) and diffing the structure instead of raw text.
It's live and free
https://priceblind.vercel.app/
No account, no credit card. Paste a URL, get emailed when pricing changes.
Happy to answer questions about any part of the implementation, the scraping, the diff engine, or the email delivery.
What would you build differently?
This article was originally published by DEV Community and written by Ahmed Errami.
Read original article on DEV Community