zenrows batch runs the same fetch or extract job across a list of URLs as a single, trackable job on Batch: submit once, then check status, collect results, or recover the tasks that didn’t finish whenever you want.
@zenrows/cli 1.8.0 or later. list, content, pause, resume, rerun and delete, the job_id key in --json output and the 10,000 URL default cap arrived in 1.8.0.
jobs.jsonl is one JSON object per line, each with a url and optional per-line overrides: scrape params such as js_render, premium_proxy, proxy_country, mode or extract (flat on the line or in a nested zenrows_params), an external_id, string metadata, and "method": "POST" with a body of up to 16 KiB. "body": null is the same as no body.
Every task uses Adaptive Stealth Mode (mode=auto) by default, like zenrows fetch and zenrows extract. A line that sets js_render, premium_proxy, or mode keeps its own settings. --js-render or --premium-proxy forces that configuration on every task, and --manual turns Adaptive Stealth Mode off.
Local, no key needed
http or https url of up to 2,048 bytes, an external_id of up to 128 letters, digits, ., _ or -, and metadata of up to 20 string entries (4 KiB). It then estimates the credit cost with no cloud call. estimate takes the same --manual, --js-render, --premium-proxy and --proxy-country flags as create, so both price the same request. Adaptive Stealth Mode costs 1 to 25 credits per task, so the estimate is a range whose upper bound is the most the job can cost. Parameter names and values are checked by the API when you submit.
The CLI ships with a local safety policy that caps every run at 10,000 URLs and an estimated 250,000 credits, so a default run of up to 10,000 URLs passes in any mode. Batch takes up to 100,000 tasks per job: for larger jobs, raise the caps with
zenrows policy set max_pages_per_run 100000 and zenrows policy set max_credits_per_run 2500000. A run over a cap stops with POLICY_LIMIT_EXCEEDED before anything is sent, and the error prints the zenrows policy set command to run. A workspace created by an earlier CLI version keeps its old caps (1,000 URLs and 10,000 credits) in policy.json.Cloud
Waiting
create --follow, rerun --follow and wait poll until the run ends, the run is paused, or --timeout runs out. The default timeout is 10 minutes; it takes 30s, 5m or 1h, and a bare number is milliseconds. When the time runs out, or the run is paused, the command exits 0 and prints the run with a note and the next command to run; the job keeps going. Ctrl-C stops the wait, not the job, and exits 130.
Failed runs and recovery
A run that endsfailed stopped for an account reason, and the command exits 1 with the same code a refused request gets: POLICY_MAX_CREDITS_EXCEEDED when the account ran out of credits, AUTH_INVALID for an inactive subscription, KEY_CREDIT_CAP_REACHED for an API key’s credit cap, and BATCH_FAILED otherwise. The error carries the run’s failure_reason as server_code, and the job_id. Fix the cause, then run the unfinished tasks again:
rerun reruns the failed and pending tasks, so successful tasks are never billed again by surprise. retry-failed reruns only the failed ones; --include-pending adds the pending and processing tasks, the same as --status failed,pending,processing. A partial rerun works within 10 days of when the run you retry started; --all always works.
Idempotency and retries
create, rerun and retry-failed send an Idempotency-Key, generated unless you pass --idempotency-key. Network errors and 502, 503 and 504 answers are retried under that key, so a retry can’t start a second job or run. When the outcome stays unknown, the error prints the command that repeats the request with the same key, shell-quoted so you can run it as printed.
Results
A result’sresult_url is valid for 2 hours. Results are kept 14 days by default; after that a successful task reads expired, and results --download skips it. content on an expired task fails with BATCH_RESULT_EXPIRED.
Flags
--json (print structured output) works on every subcommand. With --json, create, status, wait, cancel, pause, resume and rerun print {ok, job_id, run_id, status, stats, job}, plus paused, ingest_status, accepted_tasks, rerun_of, retried_tasks and inherited_tasks when the API sends them. The rest are subcommand-specific: