How to Build a Price Alert System Without Writing a Scraper
Most tutorials on this topic open with a Python script. They show you how to install requests and BeautifulSoup, parse an HTML element, store the result in SQLite, and fire an email with smtplib. It feels like good engineering until you actually run it in production.
The selector breaks when the site redesigns. Cloudflare blocks you. The cron job drifts. The SQLite file needs to be somewhere. The SMTP credentials rotate. Suddenly you are debugging infrastructure on a Sunday afternoon instead of acting on the pricing intelligence you were supposed to have.
This guide takes a different approach. You will end up with a fully working price alert system by the end. But you will not write a scraper, run a scheduler, or manage a database.
Why DIY Scrapers Fail at This Job
A price alert system has five distinct concerns: fetching, parsing, scheduling, diffing, and delivering. Most tutorials collapse all five into one Python file and call it done. That is the problem.
Fetching is actually three different jobs. Static pages need a simple HTTP client. JavaScript-rendered pages need a headless browser. Bot-protected pages need a rotating proxy. A production monitoring stack needs all three, with logic to escalate between them automatically.
Parsing means maintaining CSS selectors or XPath expressions. Sites redesign. Class names change. A selector that worked last month stops returning anything, silently, and you find out when someone asks why the alerts stopped.
Scheduling needs to be durable. A while True loop with time.sleep fails the moment the process restarts. A cron job is better but still gives you no retry logic, no dead-letter handling, and no visibility.
Diffing requires storing state. You need to remember the previous price, compare it to the current one, and decide whether the change is significant. That is a small but real data layer to maintain.
Delivering with reliability means retries, backoff, and a fallback when the endpoint is down.
When you write a scraper for price alerts, you are signing up to maintain all five layers. The typical engineering cost before the first alert fires is several days. The ongoing cost of keeping it working against real production sites is a part-time job.
What a Price Alert System Actually Needs
Strip away the implementation details and the requirements are simple:
- Watch a URL on a schedule
- Extract the specific field you care about (price, stock status, or both)
- Compare it to the last known value
- Fire a notification only when a meaningful change happens, not on every byte-level difference
- Deliver the before/after values somewhere useful
The hard part is not the logic. It is the infrastructure to make it reliable. That is the part worth delegating.
A Better Approach: Monitoring API Over Scraper
The pattern you want is not a scraper. It is a monitoring loop as a service.
You define what to watch, how to extract it, and when to fire. The infrastructure runs the loop, handles bot protection, stores state, evaluates your rules, and delivers the diff. You write configuration, not infrastructure.
Verid is built exactly for this. It is a developer-first web change detection API that runs a five-stage loop: fetch, extract, diff, predicate, deliver. You send one POST request to create a monitor. Verid handles everything else.
The key distinction from scraping APIs like ScrapingBee or Apify is scope. Those tools return HTML or structured data and then stop. You still have to schedule, store state, diff, and alert yourself. Verid closes the loop.
How Verid Fits the Price Alert Use Case
Verid has a concept called predicates that is central to why it works well for price alerts.
A predicate is a rule that decides whether a delivery fires. The loop runs on a schedule, extracts your fields, and diffs them. Then the predicate is evaluated. If it returns true, your webhook gets the notification. If it returns false, the run is logged and nothing is sent.
This is the difference between "the page changed" and "the price dropped by more than 5%." Screenshot-based monitoring tools fire on cookie banner changes, ad rotations, and timestamp updates. Verid fires when your rule says so.
The built-in predicate types relevant to price monitoring are:
| Predicate | When it fires |
|---|---|
field_decreases_by_percent | Price dropped by at least N% |
field_increases_by_percent | Price increased by at least N% |
field_decreases_by_absolute | Price dropped by at least N units |
field_equals | Field matches a literal value (e.g. "In Stock") |
field_matches_regex | Field matches a pattern |
composite | AND / OR combination of the above |
You can combine them. "Fire when price drops by 10% AND the item is in stock" is a single composite predicate.
Step-by-Step Implementation
1. Get an API Key
Sign up at verid.dev. Free plan gives you 5 monitors with daily checks and no credit card required.
export VERID_API_KEY="vrd_your_key_here"2. Create a Price Drop Monitor
This example monitors a product page using a CSS selector to extract the price, then fires when it drops by 5% or more.
curl -X POST https://api.verid.dev/v1/monitors \
-H "Authorization: Bearer $VERID_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Competitor Laptop Price Alert",
"url": "https://example-store.com/products/laptop-pro",
"schedule_interval_seconds": 3600,
"extract_config": {
"method": "css",
"fields": {
"price": "[data-test=product-price]",
"availability": ".stock-status"
}
},
"diff_predicate": {
"type": "field_decreases_by_percent",
"field": "price",
"threshold": 5
},
"deliveries": [
{ "type": "webhook", "url": "https://your-app.com/hooks/price-drop" }
]
}'A note from the Verid docs: the field_decreases_by_percent predicate requires a numeric value. If your CSS selector returns "$49.99" (with a currency symbol), Verid will try to parse it but it is more reliable to target a site that returns a raw number, or use JSONPath against the site's product API, or switch to LLM extraction to normalize the value.
The first run establishes a baseline. No alert fires on the first run. Every run after that compares against the previous successful value.
3. Add a Composite Predicate for Restock + Price Drop
If you want to catch both a price drop and a stock return in one monitor:
{
"diff_predicate": {
"type": "composite",
"operator": "OR",
"conditions": [
{
"type": "field_decreases_by_percent",
"field": "price",
"threshold": 10
},
{
"type": "field_equals",
"field": "availability",
"value": "In Stock"
}
]
}
}This fires when either condition is true. You can use AND instead if you only want alerts when the price drops on an item that is currently in stock.
4. Receive and Verify the Webhook
When the predicate fires, Verid sends a signed POST to your endpoint with the before/after diff:
{
"monitor_id": "uuid",
"fired_at": "2026-05-08T14:00:00Z",
"diff": {
"fields_changed": ["price"],
"before": { "price": "299.00", "availability": "In Stock" },
"after": { "price": "249.00", "availability": "In Stock" }
}
}Every webhook is HMAC-signed. Verify the Verid-Signature header before processing the payload:
import { createHmac, timingSafeEqual } from 'crypto';
function verifySignature(header: string, rawBody: string, secret: string): boolean {
const parts = Object.fromEntries(header.split(',').map(p => p.split('=')));
const ts = parseInt(parts['t'] ?? '0', 10);
const sig = parts['v1'];
if (!ts || !sig) return false;
// Reject payloads older than 5 minutes
if (Math.abs(Date.now() / 1000 - ts) > 300) return false;
const expected = createHmac('sha256', secret)
.update(`${ts}.${rawBody}`)
.digest('hex');
return timingSafeEqual(Buffer.from(expected, 'hex'), Buffer.from(sig, 'hex'));
}
app.post('/hooks/price-drop', (req, res) => {
const valid = verifySignature(
req.headers['verid-signature'] as string,
req.rawBody,
process.env.WEBHOOK_SECRET!
);
if (!valid) return res.status(401).send('Bad signature');
const { diff } = req.body;
console.log('Price changed:', diff.before.price, '->', diff.after.price);
// trigger your repricing workflow here
res.sendStatus(200);
});Full verification examples in Python, Ruby, Go, and PHP are in the Verid webhook docs.
5. Using the Node.js SDK
If you prefer not to manage raw HTTP calls, install the official SDK:
npm install @verid.dev/sdkimport { VeridClient } from '@verid.dev/sdk';
const client = new VeridClient({ apiKey: process.env.VERID_API_KEY! });
const monitor = await client.monitors.create({
name: 'Competitor Laptop Price Alert',
url: 'https://example-store.com/products/laptop-pro',
schedule_interval_seconds: 3600,
extract_config: {
method: 'css',
fields: { price: '[data-test=product-price]' },
},
diff_predicate: {
type: 'field_decreases_by_percent',
field: 'price',
threshold: 5,
},
deliveries: [{ type: 'webhook', url: 'https://your-app.com/hooks/price-drop' }],
});
// Trigger a manual run to validate extraction immediately
await client.monitors.runNow(monitor.id);Comparing Approaches
| DIY scraper | Scraping API (e.g. ScrapingBee) | Verid | |
|---|---|---|---|
| Fetch static pages | You write it | Yes | Yes |
| Handle JS / bot protection | You add headless browser + proxies | Yes | Auto-escalates |
| Scheduling | You manage cron | You manage cron | Built in |
| State / diffing | You store it | You store it | Built in |
| Predicate logic | You write it | You write it | 8 predicate types + composites |
| Webhook delivery with retries | You write it | You write it | HMAC-signed, 6x backoff, DLQ |
| Time to first alert | Days | Hours | Minutes |
Best Practices
Target numeric fields when possible. CSS selectors often return prices with currency symbols. If the site has a product API or a JSON endpoint embedded in the page, use method: "json_path" instead. JSONPath extraction returns clean numbers that work reliably with percent-based predicates.
Set a threshold that matches your use case. A 1% threshold on a frequently discounted category generates noise. A 10% threshold on a stable product category is meaningful. Tune it per monitor.
Use the LLM extractor as a fallback. Verid supports AI extraction where you describe the field in plain English. This is useful when the CSS structure is inconsistent or when you want to extract "the current price excluding tax" as a normalized value. You switch extraction methods with a config change, no code deploy needed.
Verify signatures. Always validate the Verid-Signature header. Replay attacks and spoofed payloads are a real threat on public webhook endpoints.
Use composite predicates to reduce false positives. "Price dropped by 10%" alone will fire even when an item is out of stock. Combine it with an availability check to make the alert actionable.
Common Mistakes
Ignoring the numeric parsing requirement. The percent-based predicates need numbers. If you get silent non-fires on a price monitor, the extracted value is probably a string like "$299.00". Check via a manual run or switch to a cleaner extraction source.
Monitoring the wrong URL. Many ecommerce sites load prices via XHR after the initial page load. A static CSS selector on the product page URL may return nothing if the price is injected by JavaScript. Check whether the site has a public JSON endpoint (often findable in browser DevTools under Network) and use JSONPath against that instead.
Setting the schedule too aggressively on the free plan. The free tier allows daily checks (86400 second intervals). Hourly checks require the Starter plan. Plan your monitor frequency against the expected rate of change before scaling up.
Forgetting the first-run baseline. The first run never fires. Trigger a manual run with runNow after creating a monitor if you want to validate that extraction is working correctly before waiting for the scheduled run.
When a Full Scraping Pipeline Still Makes Sense
Verid is the right choice for field-level change detection with predicate-driven delivery. There are scenarios where you need something different.
If you need to scrape thousands of product SKUs across many pages in a single bulk job, or if you need to own the raw HTML for downstream parsing that goes beyond field extraction, a scraping API like Apify or ScrapingBee makes more sense. You buy the fetch and proxy layer and build the rest yourself.
For most price alert use cases, Verid covers the full loop and removes the infrastructure cost entirely.
Conclusion
A price alert system is fundamentally a monitoring loop: fetch, extract, diff, evaluate, deliver. Writing that loop from scratch is straightforward. Keeping it working in production against real ecommerce sites is the expensive part.
Verid handles the infrastructure and gives you the configuration surface. You define what to watch, which field to evaluate, and what rule constitutes a meaningful change. One API call creates the monitor. The webhook fires when your condition is true, with the before/after values and a signed payload.
The free plan is a reasonable starting point for five monitors with daily checks. Get your API key and have the first alert working in under ten minutes.
Frequently Asked Questions
What is the best way to build a price alert system without writing a scraper?
Use a monitoring API that handles the full loop: scheduled fetching, field extraction, state diffing, predicate evaluation, and webhook delivery. Verid is purpose-built for this. You create a monitor via a single API call with a CSS, XPath, or JSONPath extractor, define a predicate like field_decreases_by_percent, and receive a signed webhook when the rule fires.
How do I track competitor prices on JavaScript-heavy ecommerce sites?
Verid automatically escalates through three fetch layers: static HTTP, headless browser, and residential proxy. You do not configure this manually. If a site requires JavaScript rendering or has bot protection, the monitor adapts without any change to your configuration.
How do I avoid alert fatigue from price monitoring?
Set meaningful thresholds and use composite predicates. A field_decreases_by_percent predicate with a threshold of 5 or 10 only fires on material price changes, not on rounding adjustments or display formatting changes. Combining it with an availability check via composite with AND ensures alerts only fire when the item is actionable.
Does Verid work for monitoring JSON APIs, not just HTML pages?
Yes. The json_path extraction method lets you target any JSON field using JSONPath syntax. This is ideal for product APIs, crypto price feeds, and any endpoint that returns structured data. See the JSONPath guide and the crypto price alert recipe for working examples.
Track competitor prices automatically
Set up a competitor price-drop monitor in 60 seconds — 5 monitors free, no credit card.
Related posts
Best Competitor Pricing Tools in 2026: Compared for Developers and Growth Teams
Compared: the best competitor price tracking software and tools for 2026 — features, pricing, and the API-first pick for developers.
price trackingWalmart Price Tracker: Monitor Price Changes and Get Instant Alerts
Track Walmart product prices automatically. Get instant alerts when prices drop using Verid's web change detection API - no scraping infrastructure needed.
competitor monitoringCompetitor Price Tracking: Tools, Methods & Strategy (2026)
Compare the best competitor price tracking tools—from free monitors to enterprise platforms. Learn how to track competitor prices without a six-figure budget.
Keyword TrackingHow to Monitor a Website for Keyword Appearances (Regex Monitoring)
Learn how to monitor any webpage for keyword appearances using regex extraction and predicate-driven alerts. No false positives, no screenshot noise.
