Skip to main content
Know the moment a competitor lists a new product, a blog publishes a post or a job board adds a role. Each run, Crawl lists every URL in the section you watch, your script compares that list with the one saved last time, and you get an alert with the pages that appeared or went away. Uses: Crawl with include_patterns and depth, and the download endpoint

How it works

  1. Crawl lists the section. A URL crawl (no output_format) follows the links from your start URL and keeps the URLs that match include_patterns. Each page Crawl opens is one Fetch request.
  2. 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.
  3. The alert goes out. New and removed pages go to a Slack incoming webhook when SLACK_WEBHOOK_URL is set, and to the console otherwise.
  4. 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 in CRAWL 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)
A crawl without 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:
Any scheduler works the same way: a GitHub Actions 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 of new_pages.py saves the baseline:
The test site’s catalog stays the same between runs, so to show a change, edit 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:
A run with nothing to report:
The CLI script printed the same change, + .../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_items or max_pages before reaching them. Raise both values so the crawl finishes without a stop_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_patterns also decides which links Crawl opens. Add the path of the listing or pagination pages that lead to the items.
  • 429 with too_many_crawls: other Crawl and Batch jobs on your account are still running. Wait the number of seconds in the Retry-After header, then start the crawl again.

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.