The real dashboard in live mode: 7 books scraped from real product pages, with price, rating and stock.
The challenge
Online prices change all the time. Checking competitor or supplier pages by hand misses price drops, leaves no history to compare against, and a quick scraping script breaks the first time a page changes or comes back empty.
The solution
I built a price tracking platform in Python. Paste a product URL: it scrapes the price, stock and rating, saves every result as a snapshot in a database, detects each price change (up or down, in %) and charts the full history on a dashboard and through a REST API.
The real run
7 real books scraped live from books.toscrape.com, a public store built for scraping practice: title, price in GBP, stock count, star rating, UPC and category.
A live re-check of an unchanged price logged no false change.
The price chart in the images uses 30 days of demo history from the project's seed, plus that day's live scrape.
Six steps from a product URL to a price history, the real chart (30-day demo history plus a live scrape) and the fields scraped live.
How it works
Fetch: the live page or a saved copy, with a polite delay before each request, timeouts and safe redirects.
Parse: each store is a parser plugin, so adding a new store is one new file.
Normalise: one format for every store and currency.
Store: a snapshot per scrape in SQLite or PostgreSQL, so the history is never overwritten.
Detect: each new price is compared with the last one and logged as a change, up or down, in %.
Analyse: current, lowest-ever, highest, average and off-peak price, on a dashboard, a REST API and a command-line tool.
Allow-listed stores, safe redirects, an API key and rate limits, checked on a live run. 99 tests at 85% coverage.
Security and quality
Store allow-list: only real store hostnames are fetched. On the live run, a lookalike host and a cloud-metadata IP were refused (400).
Safe redirects: every redirect hop is checked again, so a store link cannot reach a private network.
Write key and rate limit: tracking, refresh and delete need an API key (401 without it), with a per-minute budget (429 after it).
No third-party scripts: a strict content policy, and scraped titles and URLs are escaped before they are shown.
Tested on a live run: it found 3 bugs the tests had missed (compressed pages read as empty, an empty read wiped a saved product, and the price chart never drew). Each one is fixed with a test that fails without the fix.
99 automated tests at 85% coverage, plus ruff, mypy, Bandit, pip-audit and CodeQL in CI.
Tech stack: Python, httpx, BeautifulSoup, FastAPI, SQLAlchemy, SQLite or PostgreSQL, Chart.js and Docker Compose.