Skip to main content
Check a list of products every day, store each price with a timestamp, and get an alert when one drops. Prepared retailers such as amazon.com, walmart.com, ebay.com and bestbuy.com need no selectors: Extract returns the price as JSON. Any other store takes a two-line css_extractor. Uses: Extract (extract=auto), Fetch with css_extractor, Batch scheduled jobs

How it works

  1. Extract or Fetch reads each price. Prepared retailers go through extract=auto, which returns the product and its pricing as JSON. Other stores go through Fetch with mode=auto and a css_extractor that names the title and price elements.
  2. SQLite stores the history. Every check adds one row per product: URL, name, price and time.
  3. Your code detects drops. Each new price is compared with the last stored one. A lower price triggers an alert.
  4. The alert goes out. The script posts to a Slack incoming webhook when SLACK_WEBHOOK_URL is set, and prints to the console otherwise.
  5. A schedule runs it daily. Run the script from cron, or let Zenrows run the requests as a scheduled Batch job and read the results.

Ask your AI agent

With the Zenrows MCP server connected to Claude, Cursor or any MCP client, paste this prompt. Your agent picks the right Zenrows tools and settings on its own.

Read one price

Try the request on its own first. On a prepared retailer, extract=auto returns the product in parsed.product and its prices in parsed.pricing. proxy_country=us shows the prices a US shopper sees:
Response (trimmed)
GET https://api.zenrows.com/v1/extract/domains lists every domain Extract covers. To add a new one, see Extract endpoints.

Run the monitor

Save this as monitor.py, set your key, and run python monitor.py. Each run checks every product, stores the prices in prices.db and alerts on drops.
Python (Requests)
Keep your keys out of the code in production: read ZENROWS_API_KEY and SLACK_WEBHOOK_URL from environment variables or a secrets manager. To send alerts to Slack, create an incoming webhook and export its URL as SLACK_WEBHOOK_URL.

Run it every day

With cron. Run the script on your own server once a day, at 08:00:
With a scheduled Batch job. Zenrows runs the requests on its side every day, and your code only reads the results. Install the SDK (pip install zenrows), save this as batch_monitor.py next to monitor.py, and run python batch_monitor.py schedule once:
Python (SDK)
After each daily run, call python batch_monitor.py check <job-id>. A check after setting the tee’s stored price to 30.00 to simulate a drop:
To run the check the moment a run ends, attach a webhook to the job and call check from your webhook handler, see Batch webhooks.

Example output

Output of monitor.py. The first run stores a baseline for each product:
A later run, after setting the jacket’s stored price to 65.00 to simulate a drop:
The history in prices.db (sqlite3 prices.db "SELECT name, price, checked_at FROM prices"):

Customize it

Troubleshooting

  • No price found today: the price element moved or the selector doesn’t match. Open the page, inspect the price, update the css_extractor, and test it with one request.
  • A request returns 422: the page wasn’t retrieved. Keep mode=auto on store requests so Zenrows escalates to JavaScript rendering and premium proxies when a page needs them, see error codes.
  • The script stops with a timeout: set the HTTP client timeout to 180 seconds or more, as in the samples.
  • Every run alerts on the same product: the store shows a different price per visitor or region. Pin the region with proxy_country.

Detect changes on any page and get alerted

Watch any page or field, not only prices.

Turn a whole catalog into a structured dataset

Collect every product of a store to choose what to monitor.

Run a Batch job on a schedule

Every schedule option for Batch jobs.

Move an existing scraper to Zenrows

Keep your parser and swap the request layer.