include_patterns and depth, and the download endpoint
How it works
- Crawl lists the section. A URL crawl (no
output_format) follows the links from your start URL and keeps the URLs that matchinclude_patterns. Each page Crawl opens is one Fetch request. - Your script diffs the URL sets. It compares the URLs with the set saved in
known_urls.json: URLs only in the new set are new pages, URLs only in the old set are removed pages. - The alert goes out. New and removed pages go to a Slack incoming webhook when
SLACK_WEBHOOK_URLis set, and to the console otherwise. - A schedule repeats it. cron, a CI scheduler or any job runner starts the script every hour or every day.
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 a section for new pages
Set the section inCRAWL and save this as new_pages.py. The first run saves a baseline; every later run reports what changed since the previous one.
Python (Requests)
stop_reason reached every matching page, so a missing URL really is gone. When max_items or max_pages ends the crawl first, the script reports new pages only and keeps the URLs it did not reach.
To send alerts to Slack, create an incoming webhook and export its URL as SLACK_WEBHOOK_URL. The same {"text": ...} payload works with Microsoft Teams workflows and most chat tools.
Run it on a schedule
Start the script from cron. This checks every morning at 08:00:schedule workflow, a Kubernetes CronJob or your task queue. Keep known_urls.json somewhere that persists between runs.
Watch from the CLI
The same job as a shell script, with the Zenrows CLI,jq and comm. --follow waits until the crawl ends and --json prints the crawl_id:
CLI
Example output
The first run ofnew_pages.py saves the baseline:
known_urls.json before the second run: remove the Aeon Capri URL and add a made-up Zeppelin Yoga Pant URL. The second run reports one new page and one removed page:
+ .../aeon-capri/ and - .../zeppelin-yoga-pant/, after the same simulated edit of known.txt. With depth: 1, each run opens one page, the start page, and costs one Fetch request.
Customize it
Troubleshooting
- Pages show up as new that existed before: the earlier crawl ended on
max_itemsormax_pagesbefore reaching them. Raise both values so the crawl finishes without astop_reason. - Every run reports the same URLs as new and removed: the URLs carry a parameter that changes per visit, such as a session ID. Add that parameter to
exclude_patterns, or strip it before comparing. - The crawl keeps fewer URLs than the section holds:
include_patternsalso decides which links Crawl opens. Add the path of the listing or pagination pages that lead to the items. 429withtoo_many_crawls: other Crawl and Batch jobs on your account are still running. Wait the number of seconds in theRetry-Afterheader, then start the crawl again.
Related recipes
Map every URL on a website
Build the full URL inventory of a site.
Detect changes on any page and get alerted
Diff the content of known pages on a schedule.
Find broken links on a website
Crawl a site and check every link it holds.
Crawl a website from a start URL
Get every matching page with its HTML.