Skip to main content
Already have your URLs in a spreadsheet export or a database dump? Upload the CSV file as it is and point Batch at the columns that hold the URL and your own ID. You skip building a JSON body, and every result comes back tagged with the ID from your file. Uses: Batch CSV upload (POST /job_inputs, then POST /jobs with file_input_id) and zenrows_params

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.

Prepare the CSV

Any CSV works. You tell Batch which column holds the URL and, optionally, which one holds your ID. This recipe uses a file with a header row:
products.csv
Extra columns, like name here, are ignored.

Upload the file and create the job

Three calls do it:
  1. POST /job_inputs with "type": "csv" creates an upload slot. In csv.fields, map url (required) and external_id (optional) to your column names. The response holds a file_input_id and a presigned upload URL.
  2. PUT the file to upload.url, sending the headers listed in upload.headers.
  3. POST /jobs with file_input_id instead of tasks. Scrape settings go in zenrows_params as usual.
The cURL version needs jq to read the slot response. Check progress and read results the same way as any job, see Scrape a list of URLs.

Example output

The Python run:
The POST /job_inputs response, with the presigned link shortened:

Use the SDKs

Both SDKs wrap the slot and the upload in one call, upload_csv in Python and uploadCsv in Node.js, and return the file_input_id:
Output
With use_external_id=True (useExternalId: true in Node.js) each file is named after your sku column: MH09, WJ08, WP07. The Python SDK adds the result type as an extension, for example MH09.markdown.

Customize it

Troubleshooting

  • The upload returns 403: the presigned upload link is no longer fresh. Create a new slot with POST /job_inputs and upload right away.
  • POST /jobs returns 400 with header has no column: the names in fields must match your header row exactly, including case and spaces. Open the file and copy the header names, or switch to column indexes with "header": false.
  • Results have no external_id: add "external_id": "<column>" to fields. Without it, match results by url or task_id.
  • Some rows failed: list them with status=failed and rerun them, see Retry the tasks that failed.

Scrape a list of URLs

Send URLs inline as one Batch job.

Add URLs to a job while it runs

Stream URLs into an open job as you find them.

Download all results of a job at once

Save every page to a folder or one ZIP file.

Retry the tasks that failed

Rerun only the failures and keep the successes.