@zenrows/cli 1.7.0 → 1.9.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 +83 -12
- package/agent-plugin/README.md +1 -1
- package/agent-plugin/skills/batch-jobs/SKILL.md +16 -3
- package/agent-plugin/skills/cost-control/SKILL.md +2 -2
- package/agent-plugin/skills/extract/SKILL.md +49 -9
- package/agent-plugin/skills/protected-fetch/SKILL.md +1 -1
- package/agent-plugin/skills/zenrows/SKILL.md +3 -2
- package/dist/src/adapters/batch.js +237 -59
- package/dist/src/adapters/extract.js +18 -19
- package/dist/src/cli/commands/batch.js +665 -126
- package/dist/src/cli/commands/crawl.js +1 -1
- package/dist/src/cli/commands/extract-prepare.js +168 -0
- package/dist/src/cli/commands/extract.js +21 -13
- 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/http.js +78 -20
- package/dist/src/core/policy.js +13 -6
- package/dist/src/core/prepared-domains-api.js +289 -0
- package/evals/extract-smoke/README.md +1 -1
- package/package.json +1 -1
- package/recipes/batch-estimate/RECIPE.md +6 -3
- package/registry/capabilities.json +3 -3
- package/registry/skills.json +2 -2
- package/registry/templates.json +1 -1
- package/skills/batch-jobs/SKILL.md +160 -43
- package/skills/crawl/SKILL.md +1 -1
- package/skills/extract/SKILL.md +50 -6
- package/skills/trace-debug/SKILL.md +17 -2
- package/skills/zenrows/SKILL.md +9 -5
- package/templates/batch-jsonl-pipeline/README.md +10 -5
- package/templates/extract-pricing-pages/README.md +3 -5
- package/workflows/competitor-intelligence/WORKFLOW.md +2 -2
|
@@ -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:
|
package/skills/extract/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: extract
|
|
3
|
-
description: Turn protected pages into structured data with Extract /
|
|
3
|
+
description: Turn protected pages into structured data with Extract / CSS / Markdown (Autoparse is deprecated).
|
|
4
4
|
version: 0.1.0
|
|
5
5
|
requires_backend_capabilities: [extract]
|
|
6
6
|
---
|
|
@@ -12,8 +12,8 @@ access + extraction**, not generic LLM parsing.
|
|
|
12
12
|
|
|
13
13
|
## Methods
|
|
14
14
|
```
|
|
15
|
-
zenrows extract <url> # extract=auto (default)
|
|
16
|
-
zenrows extract <url> --autoparse # general-purpose Autoparse (any domain)
|
|
15
|
+
zenrows extract <url> # extract=auto (default), any prepared domain
|
|
16
|
+
zenrows extract <url> --autoparse # deprecated general-purpose Autoparse (any domain)
|
|
17
17
|
zenrows extract <url> --css '{"title":"h1","price":".price"}' # selector map
|
|
18
18
|
zenrows extract <url> --outputs emails,links # built-in output filters → JSON
|
|
19
19
|
zenrows extract <url> --output markdown # Markdown conversion
|
|
@@ -21,14 +21,58 @@ zenrows extract <url> --validate # fail if not valid JSON
|
|
|
21
21
|
```
|
|
22
22
|
|
|
23
23
|
## When to use which
|
|
24
|
-
- **Extract** (`extract=auto`, default): richest fields; works on any
|
|
25
|
-
|
|
24
|
+
- **Extract** (`extract=auto`, default): richest fields; works on any prepared
|
|
25
|
+
domain (you can prepare one yourself, see below).
|
|
26
|
+
- **Autoparse** (deprecated): only with `--autoparse`. Never automatic; do not
|
|
27
|
+
build new work on it.
|
|
26
28
|
- **CSS**: you know the exact fields/selectors and want determinism.
|
|
27
29
|
- **Markdown/plaintext**: feed clean content to an LLM yourself.
|
|
28
30
|
|
|
31
|
+
## REQS007: prepare the domain, then extract again
|
|
32
|
+
|
|
33
|
+
`extract=auto` works on any prepared domain, and you can prepare one yourself.
|
|
34
|
+
When Extract refuses a page with `403 REQS007`, `zenrows extract` says which
|
|
35
|
+
of three cases it is and prints the next step. It never retries with Autoparse.
|
|
36
|
+
|
|
37
|
+
| Error code | Meaning | Next step |
|
|
38
|
+
| --- | --- | --- |
|
|
39
|
+
| `EXTRACT_DOMAIN_NOT_PREPARED` | The domain is not prepared yet (also the legacy `402 AUTH010`). | Prepare it (below), then extract again. |
|
|
40
|
+
| `EXTRACT_PAGE_NOT_RECOGNISED` | The domain is prepared, but Extract did not recognise this page as one it can extract (a page with nothing to extract, such as a home page, or a transient failure). | Try a product, article or listing page on the same site instead. If this page should work, retry it once in a few minutes; do not retry in a loop. Otherwise use `--css`. Preparing the domain again does not change this. |
|
|
41
|
+
| `EXTRACT_DOMAIN_NOT_ENABLED` | Extract is not enabled for the site. | Use `--css`, or contact Zenrows support to have the site enabled. Preparing does not change this. |
|
|
42
|
+
|
|
43
|
+
Preparing a domain:
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
zenrows extract https://example.com/p/1 # 1. fails: EXTRACT_DOMAIN_NOT_PREPARED
|
|
47
|
+
zenrows extract prepare example.com \
|
|
48
|
+
--url https://example.com/p/1 --url https://example.com/list --wait
|
|
49
|
+
# 2. prepare it and wait until ready (a few minutes)
|
|
50
|
+
zenrows extract https://example.com/p/1 # 3. extract again
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
- `--url`: 1 to 5 real pages you want to extract, one per page kind (for
|
|
54
|
+
example a product page and a listing page).
|
|
55
|
+
- Without `--wait` the command returns at once; then check about every 30
|
|
56
|
+
seconds with `zenrows extract prepare status example.com` until it says
|
|
57
|
+
`ready`. `--wait` polls at the same pace.
|
|
58
|
+
- The domain is the host: `shop.example.com` and `example.com` are prepared
|
|
59
|
+
separately, and a leading `www.` is dropped.
|
|
60
|
+
- Preparing takes a few minutes and costs no credits. Each new domain uses one
|
|
61
|
+
slot of the account's monthly allowance; `prepare status` shows `used` /
|
|
62
|
+
`limit` / `remaining`.
|
|
63
|
+
- `EXTRACT_PREPARE_OUT_OF_ALLOWANCE`: no slots left this month; use `--css`.
|
|
64
|
+
`EXTRACT_PREPARE_UNAVAILABLE`: retry in a few minutes; do not loop.
|
|
65
|
+
A `failed` status prints the next step for its failure code and says whether
|
|
66
|
+
the attempt used an allowance slot.
|
|
67
|
+
- A domain that is already prepared answers `ready` at once
|
|
68
|
+
(`already_prepared`) and uses no slot: run the extract. If it then fails with
|
|
69
|
+
`EXTRACT_PAGE_NOT_RECOGNISED`, follow that row of the table, not `prepare`.
|
|
70
|
+
|
|
29
71
|
## Rules
|
|
30
72
|
- Validate on a single page before scaling across many URLs.
|
|
31
|
-
-
|
|
73
|
+
- Check `empty` in `--json` output: true means every field came back null or
|
|
74
|
+
empty, so the result is not data.
|
|
75
|
+
- If a field is missing, switch to `--css` with explicit selectors. Auto
|
|
32
76
|
mode already renders JS when the target needs it, so reach for
|
|
33
77
|
`--manual --js-render` only after auto mode has returned an incomplete page:
|
|
34
78
|
it costs several times a basic call ([[cost-control]]) and it makes the
|
|
@@ -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
|
@@ -34,7 +34,7 @@ If the user has a known URL and wants page content:
|
|
|
34
34
|
→ Use Protected Fetch. (zenrows fetch <url>)
|
|
35
35
|
|
|
36
36
|
If the user has a known URL and wants structured data:
|
|
37
|
-
→ Use Extract. (zenrows extract <url> | --
|
|
37
|
+
→ Use Extract. (zenrows extract <url> | --css)
|
|
38
38
|
|
|
39
39
|
If the user has a start page (listing, index, section) but not the item URLs:
|
|
40
40
|
→ Use Crawl. (zenrows crawl create <url> --depth 1 --follow,
|
|
@@ -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:
|
|
@@ -74,14 +75,17 @@ Run `zenrows status` for the live capability matrix. As of this toolkit:
|
|
|
74
75
|
| Primitive | Command | Status |
|
|
75
76
|
| --- | --- | --- |
|
|
76
77
|
| Protected Fetch | `zenrows fetch` | **available**: `GET https://api.zenrows.com/v1/` |
|
|
77
|
-
| Extract (`extract=auto`,
|
|
78
|
+
| Extract (`extract=auto`, CSS, Markdown; Autoparse deprecated) | `zenrows extract` | **available**: `GET https://api.zenrows.com/v1/?extract=auto` |
|
|
78
79
|
| Batch | `zenrows batch` | **available**: `POST https://async.api.zenrows.com/v1/jobs` |
|
|
79
80
|
| Crawl (new) | `zenrows crawl` | **available**: `POST https://api.zenrows.com/v1/crawls` |
|
|
80
81
|
| Browser | `zenrows browser` | **available**: `POST https://mcp.zenrows.com/browser/sessions` |
|
|
81
82
|
| MCP | `zenrows mcp` | **available**: `https://mcp.zenrows.com/mcp` |
|
|
82
83
|
|
|
83
|
-
- Extract: `extract=auto`
|
|
84
|
-
|
|
84
|
+
- Extract: `extract=auto` works on any prepared domain. On one not prepared yet
|
|
85
|
+
(`EXTRACT_DOMAIN_NOT_PREPARED`), run `zenrows extract prepare <domain> --url
|
|
86
|
+
<page> --wait`, then extract again. `EXTRACT_PAGE_NOT_RECOGNISED` means the
|
|
87
|
+
domain is prepared but not this page: do not prepare again; see [[extract]].
|
|
88
|
+
- 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
89
|
- Crawl: collects the URLs behind one start page, optionally with each page's HTML.
|
|
86
90
|
- Browser: escalation-only, for pages Fetch can't handle; same backend as the MCP `browser_*` tools.
|
|
87
91
|
|
|
@@ -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
|
|
@@ -3,13 +3,11 @@
|
|
|
3
3
|
Extract structured pricing fields from product pages with Zenrows Extract.
|
|
4
4
|
|
|
5
5
|
```bash
|
|
6
|
-
# Default: extract=auto on
|
|
6
|
+
# Default: extract=auto on a prepared domain (site-tailored JSON).
|
|
7
|
+
# Not prepared yet (EXTRACT_DOMAIN_NOT_PREPARED)? zenrows extract prepare <domain> --url <product-url> --wait
|
|
7
8
|
zenrows extract https://www.owler.com/company/meltwater
|
|
8
9
|
|
|
9
|
-
#
|
|
10
|
-
zenrows extract https://www.scrapingcourse.com/ecommerce/ --autoparse
|
|
11
|
-
|
|
12
|
-
# Or a precise CSS selector map
|
|
10
|
+
# A precise CSS selector map, on any domain
|
|
13
11
|
zenrows extract <product-url> --css '{"title":"h1","price":".price"}' --validate
|
|
14
12
|
```
|
|
15
13
|
|
|
@@ -9,7 +9,7 @@ status: available
|
|
|
9
9
|
|
|
10
10
|
A higher-level process built on Zenrows **Fetch and Extract**: retrieve
|
|
11
11
|
protected pages with `zenrows fetch`, then turn them into structured data with
|
|
12
|
-
`zenrows extract` (the same API's
|
|
12
|
+
`zenrows extract` (the same API's `extract=auto` / CSS / Markdown — not a separate
|
|
13
13
|
product). Scheduling and scaling use the tools you already have (cron/CI, a
|
|
14
14
|
simple per-URL loop).
|
|
15
15
|
|
|
@@ -20,7 +20,7 @@ simple per-URL loop).
|
|
|
20
20
|
```
|
|
21
21
|
zenrows fetch https://competitor.example/products
|
|
22
22
|
```
|
|
23
|
-
2. **Validate extraction** on one page (
|
|
23
|
+
2. **Validate extraction** on one page (on a domain not prepared yet, `EXTRACT_DOMAIN_NOT_PREPARED`, run `zenrows extract prepare <domain> --url <page> --wait` first).
|
|
24
24
|
```
|
|
25
25
|
zenrows extract https://competitor.example/p/123 --validate
|
|
26
26
|
```
|