@zenrows/cli 1.7.0 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +64 -9
- package/agent-plugin/skills/batch-jobs/SKILL.md +16 -3
- package/dist/src/adapters/batch.js +237 -59
- package/dist/src/cli/commands/batch.js +665 -126
- package/dist/src/cli/commands/crawl.js +1 -1
- package/dist/src/core/batch-api.js +398 -145
- package/dist/src/core/config.js +1 -1
- package/dist/src/core/errors.js +6 -0
- package/dist/src/core/policy.js +13 -6
- package/package.json +1 -1
- package/recipes/batch-estimate/RECIPE.md +6 -3
- package/skills/batch-jobs/SKILL.md +160 -43
- package/skills/crawl/SKILL.md +1 -1
- package/skills/trace-debug/SKILL.md +17 -2
- package/skills/zenrows/SKILL.md +3 -2
- package/templates/batch-jsonl-pipeline/README.md +10 -5
package/dist/src/core/config.js
CHANGED
|
@@ -14,7 +14,7 @@ export const CONFIG_VERSION = "0.1.0";
|
|
|
14
14
|
* entrypoint) so core modules — telemetry, signup provenance — can read it
|
|
15
15
|
* without an import cycle. `VERSION` in `cli/index.ts` re-exports this.
|
|
16
16
|
*/
|
|
17
|
-
export const CLI_VERSION = "1.
|
|
17
|
+
export const CLI_VERSION = "1.8.0"; // x-release-please-version
|
|
18
18
|
/** The User-Agent on every request to a Zenrows API. The gateway reads the version from it. */
|
|
19
19
|
export const CLI_USER_AGENT = `zenrows-cli/${CLI_VERSION}`;
|
|
20
20
|
/** Env var to override the Fetch and Extract API base (local/staging testing). */
|
package/dist/src/core/errors.js
CHANGED
|
@@ -13,6 +13,8 @@ export class ToolkitError extends Error {
|
|
|
13
13
|
suggested_commands;
|
|
14
14
|
server_code;
|
|
15
15
|
crawl_id;
|
|
16
|
+
job_id;
|
|
17
|
+
idempotency_key;
|
|
16
18
|
retry_after;
|
|
17
19
|
constructor(shape) {
|
|
18
20
|
super(shape.message);
|
|
@@ -23,6 +25,8 @@ export class ToolkitError extends Error {
|
|
|
23
25
|
this.suggested_commands = shape.suggested_commands ?? [];
|
|
24
26
|
this.server_code = shape.server_code;
|
|
25
27
|
this.crawl_id = shape.crawl_id;
|
|
28
|
+
this.job_id = shape.job_id;
|
|
29
|
+
this.idempotency_key = shape.idempotency_key;
|
|
26
30
|
this.retry_after = shape.retry_after;
|
|
27
31
|
}
|
|
28
32
|
toJSON() {
|
|
@@ -34,6 +38,8 @@ export class ToolkitError extends Error {
|
|
|
34
38
|
suggested_commands: this.suggested_commands,
|
|
35
39
|
...(this.server_code ? { server_code: this.server_code } : {}),
|
|
36
40
|
...(this.crawl_id ? { crawl_id: this.crawl_id } : {}),
|
|
41
|
+
...(this.job_id ? { job_id: this.job_id } : {}),
|
|
42
|
+
...(this.idempotency_key ? { idempotency_key: this.idempotency_key } : {}),
|
|
37
43
|
...(this.retry_after !== undefined ? { retry_after: this.retry_after } : {}),
|
|
38
44
|
};
|
|
39
45
|
}
|
package/dist/src/core/policy.js
CHANGED
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
import { ToolkitError } from "./errors.js";
|
|
2
2
|
import { findWorkspace, readJson, workspacePaths, writeJson } from "./workspace.js";
|
|
3
|
+
/**
|
|
4
|
+
* Safe defaults. The per-run caps let a default run submit up to 10,000 URLs
|
|
5
|
+
* in any mode: an Adaptive Stealth Mode task is estimated at its 25-credit
|
|
6
|
+
* upper bound, so 10,000 of them estimate at 250,000 credits. Larger runs
|
|
7
|
+
* (the Batch API takes up to 100,000 tasks per job) need the caps raised
|
|
8
|
+
* explicitly with `zenrows policy set`.
|
|
9
|
+
*/
|
|
3
10
|
export function defaultPolicy() {
|
|
4
11
|
return {
|
|
5
|
-
max_credits_per_run:
|
|
6
|
-
max_pages_per_run:
|
|
12
|
+
max_credits_per_run: 250_000,
|
|
13
|
+
max_pages_per_run: 10_000,
|
|
7
14
|
max_concurrency: 20,
|
|
8
15
|
allow_browser: true,
|
|
9
16
|
allow_experimental: false,
|
|
@@ -94,8 +101,8 @@ export function assertWithinLimits(requested, policy, context = "run") {
|
|
|
94
101
|
code: "POLICY_LIMIT_EXCEEDED",
|
|
95
102
|
message: `This ${context} submits ${requested.pages} page(s), over the policy cap of ${policy.max_pages_per_run}.`,
|
|
96
103
|
likely_cause: "policy.max_pages_per_run bounds how many URLs a single run may submit.",
|
|
97
|
-
next_action: `Split the job into runs of
|
|
98
|
-
suggested_commands: ["zenrows policy show"],
|
|
104
|
+
next_action: `Split the job into runs of at most ${policy.max_pages_per_run} page(s), or raise the cap: \`zenrows policy set max_pages_per_run ${requested.pages}\` (default ${defaultPolicy().max_pages_per_run}).`,
|
|
105
|
+
suggested_commands: [`zenrows policy set max_pages_per_run ${requested.pages}`, "zenrows policy show"],
|
|
99
106
|
});
|
|
100
107
|
}
|
|
101
108
|
if (requested.credits !== undefined && requested.credits > policy.max_credits_per_run) {
|
|
@@ -103,8 +110,8 @@ export function assertWithinLimits(requested, policy, context = "run") {
|
|
|
103
110
|
code: "POLICY_LIMIT_EXCEEDED",
|
|
104
111
|
message: `This ${context} is estimated at ${requested.credits} credit(s), over the policy cap of ${policy.max_credits_per_run}.`,
|
|
105
112
|
likely_cause: "policy.max_credits_per_run bounds the estimated credit cost of a single run.",
|
|
106
|
-
next_action:
|
|
107
|
-
suggested_commands: ["zenrows policy show"],
|
|
113
|
+
next_action: `Reduce the job size or per-task cost (e.g. drop premium_proxy/js_render), or raise the cap: \`zenrows policy set max_credits_per_run ${requested.credits}\` (default ${defaultPolicy().max_credits_per_run}). The estimate is an upper bound: an Adaptive Stealth Mode task counts 25 credits, and is billed 1 to 25.`,
|
|
114
|
+
suggested_commands: [`zenrows policy set max_credits_per_run ${requested.credits}`, "zenrows policy show"],
|
|
108
115
|
});
|
|
109
116
|
}
|
|
110
117
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zenrows/cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.0",
|
|
4
4
|
"description": "Open-source CLI, MCP, skills, templates, workflows, recipes, and evals layer for giving AI agents reliable access to protected web data through Zenrows cloud infrastructure.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -23,11 +23,14 @@ zenrows batch estimate jobs.jsonl
|
|
|
23
23
|
```
|
|
24
24
|
|
|
25
25
|
Swap `jobs.jsonl` for your own spec. Per-line keys (`js_render`,
|
|
26
|
-
`premium_proxy`, `proxy_country`, `mode`, `autoparse`, `external_id
|
|
27
|
-
URL; cost multipliers are basic 1x / JS
|
|
26
|
+
`premium_proxy`, `proxy_country`, `mode`, `autoparse`, `external_id`,
|
|
27
|
+
`metadata`, `method`, `body`) tune each URL; cost multipliers are basic 1x / JS
|
|
28
|
+
5x / proxy 10x / both 25x, and Adaptive Stealth Mode costs 1x to 25x. Pass
|
|
29
|
+
`create`'s job-level flags (`--premium-proxy`, `--js-render`, `--manual`) to
|
|
30
|
+
`estimate` to price the same request.
|
|
28
31
|
|
|
29
32
|
Once the spec is clean, submit it:
|
|
30
33
|
```
|
|
31
|
-
zenrows batch create jobs.jsonl --
|
|
34
|
+
zenrows batch create jobs.jsonl --follow
|
|
32
35
|
```
|
|
33
36
|
See [[batch-jobs]] for the full cloud flow.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: batch-jobs
|
|
3
|
-
description: Scale protected fetch/extract over many URLs via Batch. Cloud create/status/results/cancel/
|
|
3
|
+
description: "Scale protected fetch/extract over many URLs via Batch. Cloud create/list/status/wait/results/content/cancel/pause/resume/rerun/delete work with an API key; estimate/validate run locally with no key."
|
|
4
4
|
version: 0.1.0
|
|
5
5
|
requires_backend_capabilities: [batch]
|
|
6
6
|
---
|
|
@@ -8,22 +8,41 @@ requires_backend_capabilities: [batch]
|
|
|
8
8
|
# Batch Jobs
|
|
9
9
|
|
|
10
10
|
Process large workloads reliably and asynchronously. Batch is where Zenrows'
|
|
11
|
-
high-scale anti-bot advantage becomes obvious
|
|
12
|
-
|
|
11
|
+
high-scale anti-bot advantage becomes obvious: thousands to 100,000 URLs per
|
|
12
|
+
job, at Fetch's prices.
|
|
13
13
|
|
|
14
14
|
> Zenrows **Batch** runs on a separate host (`async.api.zenrows.com/v1`) and
|
|
15
|
-
>
|
|
16
|
-
>
|
|
17
|
-
> cloud
|
|
15
|
+
> costs the same credits as Fetch (1 basic, 5 js_render, 10 premium_proxy, 25
|
|
16
|
+
> both; Adaptive Stealth Mode 1 to 25). Failed tasks are not billed, except
|
|
17
|
+
> target 404/410 answers, as on Fetch. The cloud subcommands work with any
|
|
18
|
+
> active API key; a 403 maps to `BATCH_ACCESS_DENIED`. The toolkit never fakes
|
|
19
|
+
> a cloud run.
|
|
20
|
+
|
|
21
|
+
## Spec and estimate (local, no key)
|
|
18
22
|
|
|
19
|
-
## Local (no key, always works)
|
|
20
23
|
```
|
|
21
|
-
zenrows batch estimate jobs.jsonl
|
|
24
|
+
zenrows batch estimate jobs.jsonl [--premium-proxy] [--js-render] [--manual]
|
|
22
25
|
```
|
|
23
26
|
|
|
24
|
-
`jobs.jsonl` is one JSON object per line, each with a `url` (
|
|
25
|
-
per-task keys:
|
|
26
|
-
|
|
27
|
+
`jobs.jsonl` is one JSON object per line, each with a `url` (http or https,
|
|
28
|
+
up to 2048 bytes). Optional per-task keys:
|
|
29
|
+
|
|
30
|
+
- `external_id`: up to 128 letters, digits, `.`, `_` or `-`; echoed on each
|
|
31
|
+
result row (it does not have to be unique).
|
|
32
|
+
- `metadata`: up to 20 string-to-string entries; keys 1 to 64 of the same
|
|
33
|
+
characters, values up to 1024 bytes (UTF-8), 4 KiB in total.
|
|
34
|
+
- `method` and `body`: `"method": "POST"` sends `body` (up to 16 KiB): a JSON
|
|
35
|
+
string goes as a form body, any other JSON value as JSON (`"body": null` means
|
|
36
|
+
no body). A POST task cannot
|
|
37
|
+
use `js_render`, `js_instructions` or `json_response`.
|
|
38
|
+
- scrape params, flat (`js_render`, `premium_proxy`, `proxy_country`, `mode`,
|
|
39
|
+
`autoparse`, `extract`, ...) or nested under `zenrows_params`. Booleans are
|
|
40
|
+
`true`/`false` (or `"true"`/`"false"`).
|
|
41
|
+
|
|
42
|
+
`estimate` checks every line against those limits and prices the run the way
|
|
43
|
+
`create` would submit it, job-level flags included, as a range: Adaptive
|
|
44
|
+
Stealth Mode tasks count 1 at the low end and 25 at the upper bound. It exits 1
|
|
45
|
+
on any invalid line.
|
|
27
46
|
|
|
28
47
|
## Extract in Batch
|
|
29
48
|
|
|
@@ -39,42 +58,140 @@ correctly. The result carries two keys: `html` (the
|
|
|
39
58
|
raw page) and `parsed` (the structured data). Validate on a single URL with
|
|
40
59
|
`zenrows extract <url>` before running the full batch.
|
|
41
60
|
|
|
42
|
-
##
|
|
61
|
+
## Create, wait, read
|
|
62
|
+
|
|
43
63
|
```
|
|
44
|
-
zenrows batch create jobs.jsonl
|
|
45
|
-
zenrows batch create jobs.jsonl --manual
|
|
46
|
-
zenrows batch
|
|
47
|
-
zenrows batch results <id>
|
|
48
|
-
zenrows batch
|
|
49
|
-
zenrows batch
|
|
50
|
-
zenrows batch retry-failed <id> # rerun only the failed tasks (new run)
|
|
64
|
+
zenrows batch create jobs.jsonl --follow --json
|
|
65
|
+
zenrows batch create jobs.jsonl --manual --premium-proxy --proxy-country us --output markdown
|
|
66
|
+
zenrows batch create jobs.jsonl --name nightly --external-id run-42 --metadata team=growth
|
|
67
|
+
zenrows batch results <id> --out results.jsonl # every row, as JSONL
|
|
68
|
+
zenrows batch results <id> --download out/ # each result body + _manifest.jsonl
|
|
69
|
+
zenrows batch content <id> <task_id> # one task's body
|
|
51
70
|
```
|
|
52
71
|
|
|
53
|
-
Every task runs in Adaptive Stealth Mode (`mode=auto`) by default, like
|
|
54
|
-
and `extract`: Zenrows enables JS rendering and premium proxies only
|
|
55
|
-
that need them, and bills only the configuration that
|
|
56
|
-
`js_render
|
|
57
|
-
`--js-render` / `--premium-proxy` force that
|
|
58
|
-
`--manual` turns Adaptive Stealth Mode off.
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
`
|
|
62
|
-
`--
|
|
63
|
-
|
|
72
|
+
- Every GET task runs in Adaptive Stealth Mode (`mode=auto`) by default, like
|
|
73
|
+
`fetch` and `extract`: Zenrows enables JS rendering and premium proxies only
|
|
74
|
+
on the pages that need them, and bills only the configuration that
|
|
75
|
+
succeeds. A task that turns on `js_render` or `premium_proxy`, or sets
|
|
76
|
+
`mode`, itself keeps its own settings; `--js-render` / `--premium-proxy` force that
|
|
77
|
+
configuration on every task; `--manual` turns Adaptive Stealth Mode off.
|
|
78
|
+
Outside Adaptive Stealth Mode, `--proxy-country` needs `--premium-proxy`.
|
|
79
|
+
- Job-level flags apply to every task; per-task keys override them.
|
|
80
|
+
- `--follow` (alias `--wait`) waits until the run ends, the run is paused, or
|
|
81
|
+
`--timeout` runs out (default 10 minutes; `30s`, `5m`, `1h`; a bare number
|
|
82
|
+
is milliseconds). A wait that runs out exits 0 and prints the run with a
|
|
83
|
+
`note` and `next: zenrows batch wait <id>`; the job keeps running. Ctrl-C
|
|
84
|
+
stops the wait, not the job, and exits 130.
|
|
85
|
+
- A submit of 10,000 tasks or more answers 202 with `ingest_status: pending`
|
|
86
|
+
while the API still receives the tasks; results stay partial until `done`.
|
|
87
|
+
- `create` and `rerun` send an `Idempotency-Key` (generated, or
|
|
88
|
+
`--idempotency-key`) and retry network errors and 502/503/504 under it.
|
|
89
|
+
When the outcome stays unknown, the error carries `idempotency_key` and the
|
|
90
|
+
exact command that repeats the request safely (the API keeps a key 24 hours
|
|
91
|
+
and answers a repeat with the original job). Never repeat with a new key.
|
|
92
|
+
- Results are kept 14 days by default; after that a row reads `expired`, has no
|
|
93
|
+
`result_url`, and `content` answers `BATCH_RESULT_EXPIRED`. `--download`
|
|
94
|
+
skips expired rows and counts them. A row's `result_url` is valid 2 hours:
|
|
95
|
+
list the results again for a fresh one.
|
|
96
|
+
- `results --status successful|failed|processing|all`, `--run <run_id>` for an
|
|
97
|
+
earlier run. On a run still in progress the output has `partial: true`.
|
|
98
|
+
|
|
99
|
+
With `--json`, `create`, `status`, `wait`, `cancel`, `pause`, `resume` and
|
|
100
|
+
`rerun` print `{ok, job_id, run_id, status, stats, job}` (plus `jobId`, kept
|
|
101
|
+
for older scripts), with `paused`, `ingest_status`, `accepted_tasks`,
|
|
102
|
+
`rerun_of`, `retried_tasks`, `inherited_tasks`, `failure_reason` and
|
|
103
|
+
`failure_detail` when the API sends them, and `note` when a wait ends early.
|
|
104
|
+
|
|
105
|
+
## While it runs, and after
|
|
64
106
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
107
|
+
```
|
|
108
|
+
zenrows batch list [--status open|closed] [--type regular|scheduled]
|
|
109
|
+
zenrows batch status <id>
|
|
110
|
+
zenrows batch wait <id> --timeout 30m
|
|
111
|
+
zenrows batch pause <id> # no new task is picked up
|
|
112
|
+
zenrows batch resume <id>
|
|
113
|
+
zenrows batch cancel <id> # stop the run; an ended run answers as it ended
|
|
114
|
+
zenrows batch retry-failed <id> # rerun the failed tasks
|
|
115
|
+
zenrows batch retry-failed <id> --include-pending # also the unfinished ones
|
|
116
|
+
zenrows batch rerun <id> # failed + pending tasks; successful ones carry over
|
|
117
|
+
zenrows batch rerun <id> --status failed,pending,processing
|
|
118
|
+
zenrows batch rerun <id> --all # every task (not with --status)
|
|
119
|
+
zenrows batch delete <id> --yes # job, runs and stored results; frees its slot
|
|
120
|
+
```
|
|
75
121
|
|
|
76
|
-
|
|
77
|
-
|
|
122
|
+
A run ends `completed`, `stopped`, `failed` or `deleted`. A paused run is not
|
|
123
|
+
ended: `status` shows `paused: true`, and `wait` returns at once with a note
|
|
124
|
+
to `zenrows batch resume <id>`.
|
|
125
|
+
|
|
126
|
+
`status`, `wait`, `create --follow` and `rerun --follow` exit 1 (`ok: false`)
|
|
127
|
+
only for `failed`. A run fails when an account problem stops it, and the
|
|
128
|
+
error carries the same code and advice as the matching refused request, with
|
|
129
|
+
the run's `failure_reason` as `server_code` and the `job_id`:
|
|
130
|
+
|
|
131
|
+
- `insufficient_credits` → `POLICY_MAX_CREDITS_EXCEEDED`: add credits or claim
|
|
132
|
+
the account (`zenrows usage`).
|
|
133
|
+
- `subscription_inactive` → `AUTH_INVALID`: fix the subscription in Billing.
|
|
134
|
+
- `api_key_cap_reached` → `KEY_CREDIT_CAP_REACHED`: the account still has
|
|
135
|
+
credits and other keys keep working; wait for the cap to reset or raise it.
|
|
136
|
+
- anything else → `BATCH_FAILED`.
|
|
137
|
+
|
|
138
|
+
After any of these, and after a `cancel`, the tasks not yet run stay `pending`
|
|
139
|
+
(some can stay `processing`): fix the cause, then run them with
|
|
140
|
+
`zenrows batch rerun <id> --status failed,pending,processing`. Do not resubmit
|
|
141
|
+
the job. `rerun` with no flag reruns `failed,pending`, never the successful
|
|
142
|
+
tasks. A partial rerun (the default, or `--status`) works for 10 days after the
|
|
143
|
+
run started; after that only a full rerun (`zenrows batch rerun <id> --all`)
|
|
144
|
+
does. Every rerun is
|
|
145
|
+
a new run that answers 202 with `ingest_status: pending`.
|
|
146
|
+
|
|
147
|
+
## Limits
|
|
148
|
+
|
|
149
|
+
- 100,000 tasks per job; 3 active jobs per account, shared with Crawl. A
|
|
150
|
+
closed job frees its slot when its run ends; an open or scheduled job only
|
|
151
|
+
when deleted.
|
|
152
|
+
- The CLI's local policy caps a run at 10,000 URLs and 250,000 estimated
|
|
153
|
+
credits by default (an Adaptive Stealth Mode task counts 25), so a default
|
|
154
|
+
run of up to 10,000 URLs passes in any mode. For more, raise both:
|
|
155
|
+
`zenrows policy set max_pages_per_run 100000` and
|
|
156
|
+
`zenrows policy set max_credits_per_run 2500000`. A workspace created by an
|
|
157
|
+
earlier CLI version keeps the caps in its `policy.json` (1,000 and 10,000);
|
|
158
|
+
`POLICY_LIMIT_EXCEEDED` prints the exact command to raise them.
|
|
159
|
+
- Results 14 days; `result_url` 2 hours; partial reruns 10 days; a task that
|
|
160
|
+
fails transiently is retried automatically up to 3 times.
|
|
161
|
+
|
|
162
|
+
Schedules, webhooks, ZIP exports, CSV inputs, open jobs (add tasks, close),
|
|
163
|
+
the runs list and task history are available through the Batch API and the
|
|
164
|
+
SDKs (Python, Node.js, Go), not this CLI.
|
|
165
|
+
|
|
166
|
+
## Errors
|
|
167
|
+
|
|
168
|
+
Every Batch error carries the API's code as `server_code` (when it sent one)
|
|
169
|
+
and `job_id` on any call about one job. Reads retry 429/502/503/504 and network
|
|
170
|
+
errors up to 3 times; `cancel`, `pause` and `resume` retry 502/503/504; `create`
|
|
171
|
+
and `rerun` retry the same under their Idempotency-Key. The "Retry?" column is
|
|
172
|
+
for errors that remain after these retries.
|
|
173
|
+
|
|
174
|
+
| Code | Meaning | Retry? |
|
|
175
|
+
| --- | --- | --- |
|
|
176
|
+
| `BATCH_ACCESS_DENIED` | 403: Batch is not enabled for this account or key | no |
|
|
177
|
+
| `AUTH_INVALID` | 401: the key was rejected; or the subscription is not active (401 `subscription_inactive`, 402 "Subscription has expired."; fix it in Billing) | no |
|
|
178
|
+
| `POLICY_MAX_CREDITS_EXCEEDED` | 402 `payment_required`: the account is out of credits | after credits renew or are added |
|
|
179
|
+
| `KEY_CREDIT_CAP_REACHED` | 402 `api_key_cap_reached`: this key reached its credit cap | after the cap resets or is raised |
|
|
180
|
+
| `BATCH_QUOTA_EXCEEDED` | 429 `quota_exceeded`: 3 active jobs (shared with Crawl), 5 scheduled jobs, or an open job's 100,000 tasks | after a slot frees (`zenrows batch list`) |
|
|
181
|
+
| `BATCH_NOT_FOUND` | 404: wrong id, deleted, or another account's job | no |
|
|
182
|
+
| `BATCH_RUN_IN_PROGRESS` | 409 `run_not_terminal`: the run is still going (or still receiving tasks) | after `wait` or `cancel` |
|
|
183
|
+
| `BATCH_RUN_ENDED` | 409 `run_not_stoppable`: the run already ended (pause/resume) | no; `rerun` starts a new run |
|
|
184
|
+
| `BATCH_NO_MATCHING_TASKS` | 409 `no_matching_tasks`: no task has the statuses asked for | with `--status failed,pending,processing`, or `rerun --all` |
|
|
185
|
+
| `BATCH_RERUN_WINDOW_EXPIRED` | 409 `partial_rerun_window_expired`: a partial rerun is over 10 days late | with `rerun --all` |
|
|
186
|
+
| `BATCH_REQUEST_IN_FLIGHT` | 409 `idempotency_key_conflict`: the key is in use or was used for another body | same command, same key, a moment later |
|
|
187
|
+
| `BATCH_CONFLICT` | any other 409 (job state, key no longer valid, concurrent change) | read the cause |
|
|
188
|
+
| `BATCH_TASK_NOT_READY` | 409 `task_not_ready` on `content`: the task has not finished | after `wait` |
|
|
189
|
+
| `BATCH_TASK_FAILED` | 422 on `content`: the task failed | after `retry-failed` |
|
|
190
|
+
| `BATCH_RESULT_EXPIRED` | 410 `result_expired`: past the 14-day visibility window | after `rerun --all` |
|
|
191
|
+
| `BATCH_FAILED` | the run ended `failed` for another reason; a 400 (fix the flagged tasks) or 5xx | 5xx: yes |
|
|
192
|
+
| `POLICY_LIMIT_EXCEEDED` | the local policy caps (see Limits) | after raising the cap |
|
|
193
|
+
| `BACKEND_UNAVAILABLE` | the API could not be reached | yes |
|
|
78
194
|
|
|
79
195
|
Rules: **never batch before validating** the workflow on a single page
|
|
80
|
-
([[extract]]). Mind the cost multipliers ([[cost-control]]).
|
|
196
|
+
([[extract]]). Mind the cost multipliers ([[cost-control]]). Read errors with
|
|
197
|
+
[[trace-debug]].
|
package/skills/crawl/SKILL.md
CHANGED
|
@@ -34,7 +34,7 @@ zenrows crawl results <id> --out urls.jsonl # same, as JSONL
|
|
|
34
34
|
a depth has no `depth` field in its output.
|
|
35
35
|
- `--max-items` (kept URLs) and `--max-pages` (fetched pages) cap the crawl;
|
|
36
36
|
both default to 100. `--max-pages` bounds the cost: each page is one fetch.
|
|
37
|
-
The local policy `max_pages_per_run` caps `--max-pages` (default
|
|
37
|
+
The local policy `max_pages_per_run` caps `--max-pages` (default 10000);
|
|
38
38
|
above it the CLI refuses with `POLICY_LIMIT_EXCEEDED` before any request.
|
|
39
39
|
- `--include-patterns` / `--exclude-patterns` are substring matches on the
|
|
40
40
|
normalized URL and repeat:
|
|
@@ -43,8 +43,23 @@ zenrows trace export <run-id> # JSON for sharing
|
|
|
43
43
|
local policy credit limit was hit). Do not retry-loop; `zenrows usage` shows
|
|
44
44
|
when credits renew. Top up or upgrade, or claim the account if it is an
|
|
45
45
|
auto-created Free plan.
|
|
46
|
-
- `BATCH_FAILED` → the batch run ended `failed
|
|
47
|
-
|
|
46
|
+
- `BATCH_FAILED` → the batch run ended `failed` for a reason other than
|
|
47
|
+
credits, subscription or key cap (those get `POLICY_MAX_CREDITS_EXCEEDED`,
|
|
48
|
+
`AUTH_INVALID` or `KEY_CREDIT_CAP_REACHED`, with the run's `failure_reason`
|
|
49
|
+
as `server_code` and its `job_id`); `failure_detail` in
|
|
50
|
+
`zenrows batch status <id> --json` says why. Once fixed, run the unfinished
|
|
51
|
+
tasks with `zenrows batch rerun <id> --status failed,pending,processing`;
|
|
52
|
+
do not resubmit. Also a 400 (fix the flagged tasks) or a 5xx (retry).
|
|
53
|
+
- `BATCH_QUOTA_EXCEEDED` → 429: 3 active jobs (shared with Crawl), 5 scheduled
|
|
54
|
+
jobs, or an open job's task cap. Nothing was created; free a slot (see
|
|
55
|
+
`zenrows batch list` and `zenrows crawl list`).
|
|
56
|
+
- `BATCH_ACCESS_DENIED` / `BATCH_NOT_FOUND` → 403 Batch not enabled, or 404
|
|
57
|
+
wrong or deleted job id. Do not retry.
|
|
58
|
+
- `BATCH_RUN_IN_PROGRESS`, `BATCH_RUN_ENDED`, `BATCH_NO_MATCHING_TASKS`,
|
|
59
|
+
`BATCH_RERUN_WINDOW_EXPIRED`, `BATCH_REQUEST_IN_FLIGHT`, `BATCH_CONFLICT`,
|
|
60
|
+
`BATCH_TASK_NOT_READY`, `BATCH_TASK_FAILED`, `BATCH_RESULT_EXPIRED` → the
|
|
61
|
+
Batch API's 409/410/422 answers; `server_code` names the case and
|
|
62
|
+
`next_action` the fix. See [[batch-jobs]].
|
|
48
63
|
- `CRAWL_NOT_ENABLED` → the API answered 403 `REQS008`: Crawl is not
|
|
49
64
|
enabled for this account. Do not retry; ask Zenrows support for access.
|
|
50
65
|
- `CRAWL_INSUFFICIENT_CREDITS` / `CRAWL_KEY_CAP_REACHED` → Crawl's 402: the
|
package/skills/zenrows/SKILL.md
CHANGED
|
@@ -43,7 +43,8 @@ If the user has a start page (listing, index, section) but not the item URLs:
|
|
|
43
43
|
If the user has many URLs (bulk):
|
|
44
44
|
→ Use Batch. (validate one page with fetch/extract first,
|
|
45
45
|
then `zenrows batch create <jobs.jsonl>`)
|
|
46
|
-
Batch is the
|
|
46
|
+
Batch is the reliable path at scale, at
|
|
47
|
+
Fetch's prices. Do NOT
|
|
47
48
|
fan out fetch/extract per URL for bulk work.
|
|
48
49
|
|
|
49
50
|
If the user needs login, clicks, forms, sessions, or persistent state:
|
|
@@ -81,7 +82,7 @@ Run `zenrows status` for the live capability matrix. As of this toolkit:
|
|
|
81
82
|
| MCP | `zenrows mcp` | **available**: `https://mcp.zenrows.com/mcp` |
|
|
82
83
|
|
|
83
84
|
- Extract: `extract=auto` falls back to Autoparse on a domain not prepared yet.
|
|
84
|
-
- Batch: the
|
|
85
|
+
- Batch: the reliable path at scale, at Fetch's prices (create, list, status, wait, results, content, pause, resume, rerun, delete). Estimate specs locally with no key.
|
|
85
86
|
- Crawl: collects the URLs behind one start page, optionally with each page's HTML.
|
|
86
87
|
- Browser: escalation-only, for pages Fetch can't handle; same backend as the MCP `browser_*` tools.
|
|
87
88
|
|
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
Scaffold for a high-scale workload expressed as a JSONL job spec, run on the
|
|
4
4
|
Zenrows **Batch**. One JSON object per line, each with a `url` (plus
|
|
5
5
|
optional per-line overrides like `js_render`, `premium_proxy`, `proxy_country`,
|
|
6
|
-
`mode`, `autoparse`, `extract`,
|
|
7
|
-
|
|
6
|
+
`mode`, `autoparse`, `extract`, an `external_id` echoed back on each result,
|
|
7
|
+
string `metadata`, and `"method": "POST"` with a `body`). `batch estimate`
|
|
8
|
+
checks every line against the API's limits.
|
|
8
9
|
|
|
9
10
|
Set `"extract": "auto"` on a line to run that URL through Extract — structured
|
|
10
11
|
data instead of raw HTML, at the same credit cost as a regular task. Extract
|
|
@@ -18,17 +19,21 @@ zenrows batch estimate jobs.example.jsonl # validate the spec + estimate cred
|
|
|
18
19
|
|
|
19
20
|
## Cloud (needs a key)
|
|
20
21
|
|
|
21
|
-
The cloud subcommands run with any active API key and
|
|
22
|
+
The cloud subcommands run with any active API key and cost the same credits
|
|
22
23
|
as Fetch.
|
|
23
24
|
|
|
24
25
|
```bash
|
|
25
|
-
zenrows batch create jobs.example.jsonl --
|
|
26
|
+
zenrows batch create jobs.example.jsonl --follow # submit + wait for the run to finish
|
|
26
27
|
zenrows batch status <job-id> # run status + progress stats
|
|
27
28
|
zenrows batch results <job-id> --out results.jsonl # collect results (paginated)
|
|
28
|
-
zenrows batch retry-failed <job-id>
|
|
29
|
+
zenrows batch retry-failed <job-id> --include-pending # rerun what did not succeed
|
|
29
30
|
zenrows batch cancel <job-id> # stop an in-flight run
|
|
30
31
|
```
|
|
31
32
|
|
|
33
|
+
The local policy caps a run at 10,000 URLs and 250,000 estimated credits by
|
|
34
|
+
default; raise them with `zenrows policy set max_pages_per_run <n>` and
|
|
35
|
+
`zenrows policy set max_credits_per_run <n>`.
|
|
36
|
+
|
|
32
37
|
Tasks use Adaptive Stealth Mode (`mode=auto`) by default. Job-level scrape
|
|
33
38
|
options come from flags (`--js-render`, `--premium-proxy`, `--proxy-country`,
|
|
34
39
|
`--output`, or `--manual` to turn Adaptive Stealth Mode off); per-line keys
|