From 7b0571cbd4d226c53d471023d8fdaec9330c16e9 Mon Sep 17 00:00:00 2001 From: tedi Date: Tue, 25 Aug 2026 17:35:23 +0200 Subject: [PATCH] fix(batch): allow per-task zenrows_params, document extract in batch --- README.md | 19 +++++++++++++++++++ src/batch/client.ts | 11 ++++++++++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 1bfacd5..ab15795 100644 --- a/README.md +++ b/README.md @@ -211,6 +211,25 @@ const apiKey = "YOUR-API-KEY"; `client.batch` also exposes `listJobs()`, `deleteJob()`, `stopRun()`, `rerun()`, `listRuns()`, `getRun()`, `deleteRun()`, and `getTaskContent()` (returns the scraped page's raw content as a string, not JSON — the endpoint can return HTML or plain text depending on what the target page served). Scheduling, webhook config, HMAC key rotation, CSV task uploads, and results exports aren't wrapped yet — call the [Batch API](https://docs.zenrows.com) directly for those. +#### Extract in a batch + +Set `extract` in the batch params to run tasks through Extract — structured data instead of raw HTML. It works job-wide or per task, and per-task values win on collision. + +```js +const job = await client.batch.submitRegular( + [ + // Inherits the job-level params below. + { url: "https://example.com/products", external_id: "p1" }, + // Overrides them for this task only. + { url: "https://example.com/raw", zenrows_params: {} }, + ], + undefined, + { zenrowsParams: { extract: "auto" } }, +); +``` + +An Extract task's result carries two keys — `html` (the raw page) and `parsed` (the structured data). It costs the same as a regular task, so `estimateCost` prices it correctly. `extract_fields` is not supported in Batch yet. + The batch client (`ZenRowsBatchClient`) also works standalone, without a `ZenRows` instance — matching the Go and Python SDKs' batch clients: ```javascript diff --git a/src/batch/client.ts b/src/batch/client.ts index c0c2549..1cd3a75 100644 --- a/src/batch/client.ts +++ b/src/batch/client.ts @@ -116,12 +116,21 @@ export interface WaitForRunOptions { maxPollInterval?: number; } -type TaskInput = string | { url: string; external_id?: string; metadata?: Record }; +type TaskInput = + | string + | { + url: string; + external_id?: string; + metadata?: Record; + /** Per-task scrape params, merged over the job-level `zenrowsParams` (task wins). */ + zenrows_params?: Record; + }; function coerceUrl(item: TaskInput): { url: string; external_id?: string; metadata?: Record; + zenrows_params?: Record; } { return typeof item === "string" ? { url: item } : item; }