Skip to main content
A scheduled job stores your URLs and scrape settings once, and Zenrows runs them on your schedule: every few hours, at set times on chosen days, or once at a future date. Each fire creates a new run with its own results, so you get fresh prices, listings or pages with no cron server to keep alive. Uses: Batch scheduled jobs ("type": "scheduled" with rate, calendar or at), PUT /jobs/{id}/schedule and POST /jobs/{id}/schedule/state

Ask your AI agent

Paste this prompt into a coding agent such as Claude Code or Cursor, with the Zenrows docs connected. The agent looks up the details and writes the calls.

Create a scheduled job

Set "type": "scheduled" and add a schedule. This one runs at 09:00 every day, New York time, and extracts the catalog page as JSON:
GET /jobs/{job_id} then shows the stored schedule, the URLs as template_tasks, schedule_state and next_scheduled_run in UTC:

Example output

Creating the job with the Python SDK prints the job ID and the first run time in UTC:

Pick a schedule

Send one of rate, calendar or at. calendar and at take an IANA timezone, such as Europe/Berlin, so runs follow local time through daylight saving changes. Times of day are on the hour, in HH:00 form. rate runs every 60 minutes or more, in minute, hour or day units. Write at without a Z or offset: the timezone sets the zone.

Read the latest run’s results

Each fire creates a run. GET /jobs/{job_id} returns the newest one as latest_run, and GET /jobs/{job_id}/results lists that run’s results:
After a rerun, the script prints:
GET /jobs/{job_id}/runs lists every run, newest first, to compare one run with the next. To hear about each run as it ends, add a webhook to the job.

Change, pause or resume the schedule

Replace the schedule with PUT /jobs/{job_id}/schedule, and pause or resume it with POST /jobs/{job_id}/schedule/state. Pausing stops new runs from firing; the job, its URLs and past runs stay as they are.
A paused job reads "schedule_state": "paused" and fires no new runs. Its next_scheduled_run keeps showing the slot that fires once you resume. job.schedule.* acts on the schedule. job.run.pause() and job.run.stop() act on the run in progress, which is a different control.

Run it now or delete it

Start a run right away, outside the schedule, with POST /jobs/{job_id}/rerun. Delete the job, its schedule, runs and results with DELETE /jobs/{job_id}:
cURL

Customize it

Troubleshooting

  • 400 with invalid_argument on the schedule: the detail names the field. Use HH:00 times, an IANA timezone, and a rate of every 60 minutes or more.
  • A run is failed with a failure_reason: scheduled runs check credits and credit caps when they start. Fix the account or key, then let the next run fire or start one with rerun.
  • No run fired at the expected time: check schedule_state and next_scheduled_run (UTC) on the job. A paused schedule reads paused.

Get notified when a Batch job finishes

Receive a signed webhook after every run.

Scrape a list of URLs

One-time Batch jobs from every surface.

Get structured JSON from any page

What extract=auto returns on each run.

Extract real estate listings and property data

Re-extract listings on a schedule.