Skip to main content
Quick answers to the questions teams ask most when they start with the Batch Scraper API. For step-by-step code, see the developer guide. For error-specific help, see Troubleshooting.

Getting Started

Not yet. The Batch Scraper API is in private beta, so access is granted per account. Once your account is invited, you can start submitting jobs right away with your existing API key.
No. The Batch Scraper API uses the same API key as your Universal Scraper API. There’s nothing extra to generate.
All REST requests go to https://async.api.zenrows.com/v1. Send your key in the X-API-Key header on every request.
The Batch Scraper API is a REST API, so you can call it from any language with an HTTP client. The developer guide shows a dependency-free pattern using Node’s fetch that translates directly to Python, Go, PHP, Java, and more.

How It Works

A job is the template: your URLs and configuration. A run is one execution of that job, where each rerun or scheduled fire creates a new run. A task is a single URL within a run, with its own status and result.
A rerun replays every task in the job as a fresh run. Retry failed re-executes only the tasks that failed (and optionally those that never started), carrying over the successful results so you only pay to re-scrape what failed. Both create a new run on the same job.
Two ways: attach a webhook and the API sends a run.completed event when the run finishes, or poll the job and watch the stats counters (completed === successful + failed). Webhooks are a convenience; the run state remains the source of truth.
No. POST /jobs returns 201 Created for submissions under 10,000 tasks and 202 Accepted for larger ones (10,000+ tasks or a CSV input). The response body is identical and you track completion the same way, so treat both the same. For a large 202, GET /jobs/{id}/results may return partial pages for a few seconds while the task list finishes writing, but stats.total is correct from the start.
Yes. Open a job, add tasks in batches over time (up to 10,000 per add-tasks call), then close it with last_batch: true. See open jobs. Note that open (queue-mode) jobs are still being finalized during the private beta.
During the private beta, an account can have 3 active jobs concurrently. Submitting a 4th returns 429 quota_exceeded. Wait for a job to finish before submitting the next, or contact ZenRows if you need a higher limit.

Scraping Options

The same zenrows_params as the Universal Scraper API, including js_render, premium_proxy, proxy_country, wait_for, wait, css_extractor, autoparse, json_response, custom_headers, and more. Set them once on the job, and override any of them per URL.
Yes. Options set on the job apply to every URL; options set on an individual URL override the job-level ones for that URL. This lets you configure the common case once and tune the exceptions (for example, a different proxy_country for a handful of URLs).
Yes. A job is just a list of URLs plus the options to apply to them, so you can mix targets in a single job and use per-URL overrides where a specific site needs different handling.
Raw HTML, parsed JSON, Markdown, plain text, and PDF. The API derives the output format from your options (for example response_type: markdown) and records it on each result.

Results and Limits

Up to 100,000 URLs per job submit. On an open job, each add-tasks call accepts up to 10,000 URLs, and CSV uploads support up to 50 MB / 100,000 rows. Results page at ~1,000 per page.
Attach an external_id to each URL. The API returns it unchanged on every result, so you can correlate results to your records without tracking the API’s task IDs. It doesn’t need to be unique.
Yes. Start a bulk export to bundle a run’s result bodies into a single ZIP. Exports expire 12 hours after creation, and a run whose combined results exceed 1 GiB can’t be exported as one archive. Page through the results instead.

Scheduling

Yes. Schedule a job as one-shot (a single future time), interval (every N minutes, hours, or days), or calendar (specific times on specific days). Schedules are timezone-aware using IANA names. You can pause and resume any time without losing the schedule.
Times of day must be full hours: use "09:00", not "09:30". Also provide exactly one schedule type (at, rate, or calendar) and a valid IANA timezone for at and calendar.

Pricing

Pricing is identical to the Universal Scraper API: you’re billed in usage, per successful request. The usage cost depends on the scraping tier each URL uses.
ConfigurationUsage per successful request
Base (no special options)1
JavaScript rendering5
Premium proxy10
JavaScript rendering + premium proxy25
Adaptive Stealth Mode (mode=auto)Dynamic, 1–25
No. Only successful requests cost usage. A run with failures costs less than its up-front estimate.
Yes. Because the rate card is small and stable, you can estimate usage client-side with no API call, then show your users an accurate range up front. After a run finishes, you can also read the actual usage it consumed. See Estimate cost and Check actual cost.
Use Adaptive Stealth Mode (mode=auto). It starts each request with the cheapest viable setup and escalates to JavaScript rendering or premium proxies only when a site actually needs them, so you pay for the lightest configuration that succeeds.

Reliability and Security

The API retries transient failures automatically, so a page that’s briefly unavailable still has a strong chance of being fetched. Requests are also paced to stay polite to the sites you scrape.
An idempotency key guards against accidentally creating duplicate jobs. Each key can be used once: the first submit with a given key creates the job, and any later submit reusing that key returns 409 idempotency_key_conflict, whether or not the body is identical. The API does not replay the original response. Because of this, an idempotency key is not a safe-retry token. If a submit fails midway, don’t resend with the same key. First check whether the job was created (list your recent jobs), then reuse its job_id or submit again with a new key.
Set signature: true when you attach the webhook. The API then HMAC-signs each delivery, and your receiver verifies the X-Signature header against the raw request body using your organization’s active key. See Manage HMAC keys.

Didn’t Find Your Answer?

Check the Troubleshooting page for error-specific guidance, or reach out to support with your job_id, the request body (API key redacted), and the exact error code and detail.