Tutorial2 min readUpdated Mar 22, 2026

Set Up Automated Price Drop Alerts

TL;DR

Check prices on a schedule, compare against your target thresholds, and fire notifications via email (smtplib) or webhook (httpx POST) when a price drops.

How Price Alerts Work

The alert system is simple: maintain a list of products with target prices, check current prices on a schedule via PriceFetch API, and send a notification when the current price drops below the target.

We'll build two notification channels: email (using Python's built-in smtplib) and webhooks (for Slack, Discord, or any HTTP endpoint). You can use either or both.

Try it yourself — 500 free API credits, no credit card required.

Start Free

Defining Alerts

Store your alerts in a JSON file. Each alert has a product URL, a target price, and notification preferences. This keeps the configuration separate from code and easy to update.

json
# alerts.json
{
  "alerts": [
    {
      "url": "https://www.amazon.com/dp/B0CHX3QBCH",
      "name": "Sony WH-1000XM5",
      "target_price": 278.00,
      "notify": ["email", "webhook"]
    },
    {
      "url": "https://www.amazon.com/dp/B0BSHF7WHW",
      "name": "MacBook Air M2",
      "target_price": 949.00,
      "notify": ["webhook"]
    }
  ],
  "email": {
    "smtp_host": "smtp.gmail.com",
    "smtp_port": 587,
    "from": "alerts@yourdomain.com",
    "to": "you@yourdomain.com"
  },
  "webhook_url": "https://hooks.slack.com/services/YOUR/WEBHOOK/URL"
}

Price Checking Logic

The checker loads the alert config, fetches current prices from PriceFetch, and compares against targets. Only in-stock products with prices below the threshold trigger a notification.

We also track which alerts have already fired to avoid spamming. Once an alert triggers, it won't fire again until the price goes back above the target and drops again.

python
import httpx
import json
import os
from pathlib import Path

API_KEY = os.environ["PRICEFETCH_API_KEY"]
FIRED_FILE = Path("fired_alerts.json")

def load_config() -> dict:
    return json.loads(Path("alerts.json").read_text())

def load_fired() -> set:
    if FIRED_FILE.exists():
        return set(json.loads(FIRED_FILE.read_text()))
    return set()

def save_fired(fired: set) -> None:
    FIRED_FILE.write_text(json.dumps(list(fired)))

def check_alerts() -> None:
    config = load_config()
    fired = load_fired()

    for alert in config["alerts"]:
        url = alert["url"]
        resp = httpx.get(
            "https://api.pricefetch.dev/v1/price",
            params={"url": url},
            headers={"X-API-Key": API_KEY},
            timeout=15.0,
        )
        data = resp.json()
        if not data["success"]:
            continue

        price = data["data"]["price"]
        in_stock = data["data"]["in_stock"]
        currency = data["data"]["currency"]

        if in_stock and price <= alert["target_price"] and url not in fired:
            print(f"ALERT: {alert['name']} is {currency} {price:.2f} (target: {alert['target_price']})")
            if "email" in alert["notify"]:
                send_email_alert(config["email"], alert, price, currency)
            if "webhook" in alert["notify"]:
                send_webhook_alert(config["webhook_url"], alert, price, currency)
            fired.add(url)
        elif price > alert["target_price"] and url in fired:
            # Price went back up, reset alert
            fired.discard(url)

    save_fired(fired)

Sending Notifications

Two notification channels: email for personal alerts, webhooks for team channels. The email function uses Python's smtplib — no external dependencies. The webhook function posts a JSON payload that works with Slack, Discord (with minor formatting changes), or any custom endpoint.

python
import smtplib
from email.message import EmailMessage

def send_email_alert(email_config: dict, alert: dict, price: float, currency: str) -> None:
    msg = EmailMessage()
    msg["Subject"] = f"Price Drop: {alert['name']} is now {currency} {price:.2f}"
    msg["From"] = email_config["from"]
    msg["To"] = email_config["to"]
    msg.set_content(
        f"{alert['name']} dropped to {currency} {price:.2f}\n"
        f"Your target: {currency} {alert['target_price']:.2f}\n"
        f"Link: {alert['url']}"
    )
    with smtplib.SMTP(email_config["smtp_host"], email_config["smtp_port"]) as server:
        server.starttls()
        server.login(email_config["from"], os.environ["SMTP_PASSWORD"])
        server.send_message(msg)

def send_webhook_alert(webhook_url: str, alert: dict, price: float, currency: str) -> None:
    payload = {
        "text": (
            f"*Price Drop Alert*\n"
            f"*{alert['name']}* is now *{currency} {price:.2f}* "
            f"(target: {currency} {alert['target_price']:.2f})\n"
            f"<{alert['url']}|View product>"
        )
    }
    httpx.post(webhook_url, json=payload, timeout=10.0)

Running on a Schedule

Add a cron job to run the alert checker. Every 2-4 hours is a good balance between catching deals and conserving credits. For flash sales or time-sensitive deals, hourly checks are better.

With 5 products checked every 4 hours, you'll use about 30 credits per day. The 500 free credits you get on signup will last over two weeks of monitoring.

bash
# Check every 4 hours
0 */4 * * * cd /path/to/alerts && source .env && python alert_checker.py

# Or use systemd timer for more reliability
# /etc/systemd/system/price-alerts.timer

Frequently asked questions

Start fetching prices — 500 free credits

Sign up in 30 seconds. No credit card required. One credit per successful API call.