response_type=markdown or css_extractor, Batch scheduled jobs
How it works
- Fetch reads the page. Fetch with
mode=autoreturns either the whole page as markdown, or only the fields you name in acss_extractor. Watching fields ignores changes elsewhere on the page, such as ads or timestamps. - Your code hashes and diffs. The script hashes the content and compares it with the hash stored in
snapshots.json. When they differ, it builds a line-by-line diff. - The alert goes out. The diff goes to a Slack incoming webhook when
SLACK_WEBHOOK_URLis set, and to the console otherwise. - A schedule repeats it. Run the script from cron, or let a scheduled Batch job fetch the pages and run the same diff on its 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.Watch pages for changes
List what to watch inWATCHES. An entry with a css_extractor watches those fields. An entry without one watches the whole page as markdown. Save this as watch.py and run python watch.py: the first run saves a baseline, every later run compares against it.
Python (Requests)
SLACK_WEBHOOK_URL. The same {"text": ...} payload works with Microsoft Teams workflows, Discord (as content) and most chat tools.
Run it on a schedule
With cron. Check every hour from your own server:zenrows_params, so one job mixes field watches and full-page watches. Run this once to create the job (pip install zenrows):
Python (SDK)
run.completed event to the webhook after each run. Call this function from your webhook handler (or from cron, after the scheduled time) to diff the run’s results against your snapshots:
Python (SDK)
X-ZenRows-Event-Id header. To verify that deliveries come from Zenrows, enable signed webhooks, see Verify signed webhooks.
Example output
Output ofwatch.py: the first run, then a second run with no changes:
snapshots.json to simulate a change. The field watch shows the changed field, the markdown watch shows the changed line:
Customize it
Troubleshooting
- Every run reports a change: the page includes content that changes on each load, such as a timestamp, a session token or rotating ads. Switch that watch to a
css_extractorwith only the fields you care about. - The diff is empty but a change was reported: the content changed only in whitespace or line order. Normalize the content before hashing, for example
" ".join(content.split()). - A field comes back empty: the selector no longer matches. Inspect the element in your browser and update the
css_extractor. - Webhook events arrive twice: deliveries are at least once. Store each
X-ZenRows-Event-Idyou process and skip repeats.
Related recipes
Build a price monitor
Store price history and alert on drops.
Run a Batch job on a schedule
Every schedule option for Batch jobs.
Get notified when a Batch job finishes
Receive and verify Batch webhooks.
Turn any web page into LLM-ready markdown
More on
response_type=markdown.