Building an Amazon product monitor that tracks prices, Best Sellers Rank, and review counts gives sellers and analysts a continuous pulse on product performance without manual checks. Direct Amazon scraping is unreliable at scale due to aggressive bot detection and constantly shifting page layouts. The Scavio search API returns structured Amazon product data including current price, BSR, rating, and review count for any ASIN query. This tutorial builds a complete monitor that polls ASINs on a schedule, stores historical data points in a local JSON database, and prints alerts when key metrics cross thresholds.
Prerequisites
- Python 3.8 or higher installed
- requests library installed (pip install requests)
- A Scavio API key from scavio.dev
- One or more Amazon ASINs to track
Walkthrough
Step 1: Configure ASINs and alert thresholds
Define the ASINs to monitor along with thresholds for price drops, BSR jumps, and review count milestones. These thresholds control when the monitor prints alerts.
ASINS = {
'B09G9FPHY6': {
'name': 'Echo Dot 5th Gen',
'price_floor': 30.00,
'bsr_alert_jump': 5000,
'review_milestone': 1000
},
'B07FZ8S74R': {
'name': 'Fire TV Stick 4K',
'price_floor': 25.00,
'bsr_alert_jump': 3000,
'review_milestone': 5000
}
}Step 2: Fetch Amazon product data from Scavio
POST to the Scavio endpoint with the amazon platform and ASIN as the query. Extract the product object containing price, BSR, rating, and review count.
import requests
import os
API_KEY = os.environ.get('SCAVIO_API_KEY', 'your_scavio_api_key')
def fetch_product(asin: str) -> dict:
response = requests.post(
'https://api.scavio.dev/api/v1/search',
headers={'x-api-key': API_KEY},
json={'platform': 'amazon', 'query': asin, 'marketplace': 'US'}
)
response.raise_for_status()
data = response.json()
product = data.get('product', {})
return {
'asin': asin,
'title': product.get('title', ''),
'price': product.get('price', ''),
'bsr': product.get('best_sellers_rank', 0),
'rating': product.get('rating', 0),
'reviews': product.get('reviews_count', 0)
}Step 3: Store historical data points
Append each data fetch to a JSON-based history file keyed by ASIN and timestamp. This creates a time-series that can be used for trend analysis or charting.
import json
from pathlib import Path
from datetime import datetime
HISTORY_FILE = Path('amazon_monitor_history.json')
def append_history(asin: str, data_point: dict) -> None:
history = json.loads(HISTORY_FILE.read_text()) if HISTORY_FILE.exists() else {}
if asin not in history:
history[asin] = []
data_point['timestamp'] = datetime.now().isoformat()
history[asin].append(data_point)
HISTORY_FILE.write_text(json.dumps(history, indent=2))Step 4: Check thresholds and generate alerts
Compare the current data point against thresholds and the previous data point. Generate alerts for price drops below floor, large BSR jumps, and review milestones.
def check_alerts(asin: str, current: dict, config: dict, history: list) -> None:
price_val = current.get('price', '')
if price_val:
price_num = float(str(price_val).replace('$', '').replace(',', ''))
if price_num <= config['price_floor']:
print(f' PRICE ALERT: {config["name"]} at ${price_num:.2f} (floor: ${config["price_floor"]})')
if len(history) >= 2:
prev_bsr = history[-2].get('bsr', 0)
curr_bsr = current.get('bsr', 0)
if prev_bsr and curr_bsr and abs(curr_bsr - prev_bsr) > config['bsr_alert_jump']:
direction = 'dropped' if curr_bsr > prev_bsr else 'improved'
print(f' BSR ALERT: {config["name"]} {direction} from {prev_bsr} to {curr_bsr}')
if current.get('reviews', 0) >= config['review_milestone']:
print(f' MILESTONE: {config["name"]} has {current["reviews"]} reviews')Step 5: Run the monitor and print a summary table
Iterate all ASINs, fetch data, store history, check alerts, and print a summary table. Schedule this script with cron for hourly or daily runs.
def run_monitor():
history = json.loads(HISTORY_FILE.read_text()) if HISTORY_FILE.exists() else {}
print(f'Amazon Product Monitor - {datetime.now().strftime("%Y-%m-%d %H:%M")}')
print(f'{"ASIN":<14} {"Product":<25} {"Price":<10} {"BSR":<10} {"Reviews"}')
print('-' * 70)
for asin, config in ASINS.items():
product = fetch_product(asin)
append_history(asin, product)
updated_history = json.loads(HISTORY_FILE.read_text())
check_alerts(asin, product, config, updated_history.get(asin, []))
print(f'{asin:<14} {config["name"]:<25} {product["price"]:<10} {product["bsr"]:<10} {product["reviews"]}')
run_monitor()Python Example
import os
import json
import requests
from pathlib import Path
from datetime import datetime
API_KEY = os.environ.get('SCAVIO_API_KEY', 'your_scavio_api_key')
ENDPOINT = 'https://api.scavio.dev/api/v1/search'
HISTORY_FILE = Path('amazon_monitor_history.json')
ASINS = {
'B09G9FPHY6': {'name': 'Echo Dot 5th Gen', 'price_floor': 30.00, 'bsr_alert_jump': 5000, 'review_milestone': 1000},
'B07FZ8S74R': {'name': 'Fire TV Stick 4K', 'price_floor': 25.00, 'bsr_alert_jump': 3000, 'review_milestone': 5000}
}
def fetch_product(asin: str) -> dict:
response = requests.post(
ENDPOINT,
headers={'x-api-key': API_KEY},
json={'platform': 'amazon', 'query': asin, 'marketplace': 'US'}
)
response.raise_for_status()
product = response.json().get('product', {})
return {
'asin': asin,
'title': product.get('title', ''),
'price': product.get('price', ''),
'bsr': product.get('best_sellers_rank', 0),
'rating': product.get('rating', 0),
'reviews': product.get('reviews_count', 0)
}
def append_history(asin: str, data_point: dict) -> None:
history = json.loads(HISTORY_FILE.read_text()) if HISTORY_FILE.exists() else {}
if asin not in history:
history[asin] = []
data_point['timestamp'] = datetime.now().isoformat()
history[asin].append(data_point)
HISTORY_FILE.write_text(json.dumps(history, indent=2))
def check_alerts(asin: str, current: dict, config: dict, history: list) -> None:
price_val = current.get('price', '')
if price_val:
price_num = float(str(price_val).replace('$', '').replace(',', ''))
if price_num <= config['price_floor']:
print(f' PRICE ALERT: {config["name"]} at ${price_num:.2f} (floor: ${config["price_floor"]})')
if len(history) >= 2:
prev_bsr = history[-2].get('bsr', 0)
curr_bsr = current.get('bsr', 0)
if prev_bsr and curr_bsr and abs(curr_bsr - prev_bsr) > config['bsr_alert_jump']:
direction = 'dropped' if curr_bsr > prev_bsr else 'improved'
print(f' BSR ALERT: {config["name"]} {direction} from {prev_bsr} to {curr_bsr}')
if current.get('reviews', 0) >= config['review_milestone']:
print(f' MILESTONE: {config["name"]} has {current["reviews"]} reviews')
def run_monitor():
history = json.loads(HISTORY_FILE.read_text()) if HISTORY_FILE.exists() else {}
print(f'Amazon Product Monitor - {datetime.now().strftime("%Y-%m-%d %H:%M")}')
print(f'{"ASIN":<14} {"Product":<25} {"Price":<10} {"BSR":<10} {"Reviews"}')
print('-' * 70)
for asin, config in ASINS.items():
product = fetch_product(asin)
append_history(asin, product)
updated = json.loads(HISTORY_FILE.read_text())
check_alerts(asin, product, config, updated.get(asin, []))
print(f'{asin:<14} {config["name"]:<25} {product["price"]:<10} {product["bsr"]:<10} {product["reviews"]}')
if __name__ == '__main__':
run_monitor()JavaScript Example
const API_KEY = process.env.SCAVIO_API_KEY || 'your_scavio_api_key';
const ENDPOINT = 'https://api.scavio.dev/api/v1/search';
const fs = require('fs');
const HISTORY_FILE = 'amazon_monitor_history.json';
const ASINS = {
B09G9FPHY6: { name: 'Echo Dot 5th Gen', priceFloor: 30.0, bsrAlertJump: 5000 },
B07FZ8S74R: { name: 'Fire TV Stick 4K', priceFloor: 25.0, bsrAlertJump: 3000 }
};
async function fetchProduct(asin) {
const response = await fetch(ENDPOINT, {
method: 'POST',
headers: { 'x-api-key': API_KEY, 'Content-Type': 'application/json' },
body: JSON.stringify({ platform: 'amazon', query: asin, marketplace: 'US' })
});
if (!response.ok) throw new Error('HTTP ' + response.status);
const data = await response.json();
const product = data.product || {};
return {
asin,
title: product.title || '',
price: product.price || '',
bsr: product.best_sellers_rank || 0,
rating: product.rating || 0,
reviews: product.reviews_count || 0
};
}
async function main() {
const history = fs.existsSync(HISTORY_FILE) ? JSON.parse(fs.readFileSync(HISTORY_FILE, 'utf-8')) : {};
console.log('Amazon Product Monitor - ' + new Date().toISOString().slice(0, 16));
for (const [asin, config] of Object.entries(ASINS)) {
const product = await fetchProduct(asin);
if (!history[asin]) history[asin] = [];
product.timestamp = new Date().toISOString();
history[asin].push(product);
const priceNum = parseFloat(String(product.price).replace(/[$,]/g, ''));
if (priceNum && priceNum <= config.priceFloor) {
console.log(' PRICE ALERT: ' + config.name + ' at $' + priceNum.toFixed(2));
}
console.log(asin + ' | ' + config.name + ' | ' + product.price + ' | BSR: ' + product.bsr + ' | Reviews: ' + product.reviews);
}
fs.writeFileSync(HISTORY_FILE, JSON.stringify(history, null, 2));
console.log('History saved');
}
main().catch(console.error);Expected Output
Amazon Product Monitor - 2026-05-12 14:30
ASIN Product Price BSR Reviews
----------------------------------------------------------------------
B09G9FPHY6 Echo Dot 5th Gen $29.99 1234 45678
PRICE ALERT: Echo Dot 5th Gen at $29.99 (floor: $30.0)
MILESTONE: Echo Dot 5th Gen has 45678 reviews
B07FZ8S74R Fire TV Stick 4K $34.99 892 98321
MILESTONE: Fire TV Stick 4K has 98321 reviews
History saved