@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
package/README.md
CHANGED
|
@@ -37,7 +37,7 @@ that endpoint with extraction parameters, not a separate product.
|
|
|
37
37
|
| Command | What it does | Status (this build) |
|
|
38
38
|
| --- | --- | --- |
|
|
39
39
|
| `zenrows fetch` | Fetch: retrieve a protected page | **available**: `GET https://api.zenrows.com/v1/` |
|
|
40
|
-
| `zenrows extract` | Extract: turn a page into structured data with `extract=auto` on any prepared domain (
|
|
40
|
+
| `zenrows extract` | Extract: turn a page into structured data with `extract=auto` on any prepared domain (prepare one yourself with `zenrows extract prepare`), CSS selectors, or Markdown | **available**: `GET https://api.zenrows.com/v1/?extract=auto` |
|
|
41
41
|
| `zenrows batch` | Batch: run Fetch and Extract over many URLs in one job; specs validate and estimate locally with no key | **available**: `POST https://async.api.zenrows.com/v1/jobs` |
|
|
42
42
|
| `zenrows crawl` | Crawl (new): collect the URLs behind one start page, optionally with each page's HTML | **available**: `POST https://api.zenrows.com/v1/crawls` |
|
|
43
43
|
| `zenrows browser` | Browser Sessions: a real cloud browser over REST (same backend as MCP `browser_*`); escalation-only, billed by bandwidth + time | **available**: `POST https://mcp.zenrows.com/browser/sessions` |
|
|
@@ -56,7 +56,7 @@ npm install -g @zenrows/cli # puts `zenrows` on PATH (466 ms, zero deps)
|
|
|
56
56
|
zenrows init
|
|
57
57
|
zenrows fetch https://httpbin.io/html # auto-provisions a Free plan account on first use
|
|
58
58
|
zenrows extract https://www.owler.com/company/meltwater # extract=auto on a prepared domain
|
|
59
|
-
zenrows extract https://www.scrapingcourse.com/ecommerce/ --
|
|
59
|
+
zenrows extract https://www.scrapingcourse.com/ecommerce/ --css '{"title":"h1"}' # CSS selectors (any domain)
|
|
60
60
|
```
|
|
61
61
|
|
|
62
62
|
> Prefer no global install? Prefix each command with `npx -y @zenrows/cli`
|
|
@@ -118,30 +118,101 @@ zenrows fetch <url> --proxy-country us --wait-for ".price"
|
|
|
118
118
|
|
|
119
119
|
```bash
|
|
120
120
|
zenrows extract https://www.owler.com/company/meltwater # extract=auto (prepared domain)
|
|
121
|
-
zenrows extract https://www.scrapingcourse.com/ecommerce/ --autoparse # Autoparse (any domain)
|
|
121
|
+
zenrows extract https://www.scrapingcourse.com/ecommerce/ --autoparse # deprecated Autoparse (any domain)
|
|
122
122
|
zenrows extract <url> --css '{"title":"h1","price":".price"}' --validate
|
|
123
123
|
zenrows extract <url> --outputs emails,links # built-in output filters → JSON
|
|
124
124
|
zenrows extract <url> --output markdown
|
|
125
125
|
```
|
|
126
126
|
|
|
127
|
+
On a domain Extract hasn't prepared yet, `zenrows extract` fails with
|
|
128
|
+
`EXTRACT_DOMAIN_NOT_PREPARED` (API code REQS007) and prints the command to
|
|
129
|
+
prepare it. Preparing takes a few minutes and costs no credits; each new domain
|
|
130
|
+
uses one slot of the monthly allowance. `EXTRACT_PAGE_NOT_RECOGNISED` (also
|
|
131
|
+
REQS007) is different: the domain is prepared, but this page is not one Extract
|
|
132
|
+
extracts. Try a product, article or listing page instead, retry it once in a
|
|
133
|
+
few minutes if it should work, or use `--css`; preparing again does not change
|
|
134
|
+
it. `zenrows extract` never falls back to Autoparse. The `fallbackAutoparse`
|
|
135
|
+
adapter option is deprecated and has no effect.
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
zenrows extract prepare example.com --url https://example.com/p/1 --url https://example.com/list --wait
|
|
139
|
+
zenrows extract prepare status example.com # progress + monthly allowance
|
|
140
|
+
zenrows extract https://example.com/p/1 # then extract again
|
|
141
|
+
```
|
|
142
|
+
|
|
127
143
|
## 9. Batch
|
|
128
144
|
|
|
129
145
|
Zenrows **Batch** (`https://async.api.zenrows.com/v1`) fans a
|
|
130
146
|
protected fetch/extract out over many URLs. The cloud subcommands work
|
|
131
|
-
with any active API key and
|
|
132
|
-
|
|
147
|
+
with any active API key and cost the same credits as Fetch: Batch is the
|
|
148
|
+
reliable path at scale, at Fetch's prices. Local spec validation + credit
|
|
149
|
+
estimation always work (no key needed).
|
|
133
150
|
|
|
134
151
|
```bash
|
|
135
|
-
zenrows batch estimate jobs.jsonl
|
|
136
|
-
zenrows batch create jobs.jsonl --
|
|
137
|
-
zenrows batch
|
|
138
|
-
zenrows batch
|
|
139
|
-
zenrows batch
|
|
152
|
+
zenrows batch estimate jobs.jsonl # validate the spec + estimate credits (local)
|
|
153
|
+
zenrows batch create jobs.jsonl --follow # submit a job and wait for it to finish
|
|
154
|
+
zenrows batch list # your jobs, newest first
|
|
155
|
+
zenrows batch status <job-id> # run status, progress stats, pause state
|
|
156
|
+
zenrows batch wait <job-id> --timeout 30m # wait for the run to end
|
|
157
|
+
zenrows batch results <job-id> --out results.jsonl # collect results (paginated)
|
|
158
|
+
zenrows batch content <job-id> <task-id> # one task's result body
|
|
159
|
+
zenrows batch pause <job-id> # pause the run (resume <job-id> continues it)
|
|
160
|
+
zenrows batch cancel <job-id> # stop an in-flight run
|
|
161
|
+
zenrows batch retry-failed <job-id> --include-pending # rerun every task that did not succeed
|
|
162
|
+
zenrows batch rerun <job-id> # rerun failed + pending tasks (--all: every task)
|
|
163
|
+
zenrows batch delete <job-id> --yes # delete the job, its runs and results
|
|
140
164
|
```
|
|
141
165
|
|
|
142
166
|
`jobs.jsonl` is one JSON object per line, each with a `url` (plus optional
|
|
143
167
|
per-line overrides like `js_render`, `premium_proxy`, `proxy_country`,
|
|
144
|
-
`extract
|
|
168
|
+
`extract`, nested `zenrows_params`, an `external_id`, string `metadata`, and
|
|
169
|
+
`"method": "POST"` with a `body` of up to 16 KiB). `estimate` and `create`
|
|
170
|
+
check every line against the API's limits before anything is sent: `url` up
|
|
171
|
+
to 2048 bytes, `external_id` up to 128 letters, digits, `.`, `_` or `-`,
|
|
172
|
+
and `metadata` up to 20 string entries (4 KiB). Validate and estimate locally
|
|
173
|
+
first, then submit with `create`. `estimate` takes `create`'s
|
|
174
|
+
`--manual` / `--js-render` / `--premium-proxy` / `--proxy-country` flags and
|
|
175
|
+
prices the same request, as a range (Adaptive Stealth Mode costs 1 to 25).
|
|
176
|
+
|
|
177
|
+
`create` also takes `--name`, `--external-id` and `--metadata key=value`
|
|
178
|
+
(repeatable) for the job itself. It sends an `Idempotency-Key` (generated, or
|
|
179
|
+
`--idempotency-key`) and retries network errors and 502/503/504 under it; an
|
|
180
|
+
outcome that stays unknown prints the command that repeats the request with
|
|
181
|
+
that key, which cannot create a second job.
|
|
182
|
+
|
|
183
|
+
The local policy caps a run at 10,000 URLs and 250,000 estimated credits by
|
|
184
|
+
default (an Adaptive Stealth Mode task counts 25), so a default run of up to
|
|
185
|
+
10,000 URLs passes in any mode. Raise them for larger jobs (the API takes up to
|
|
186
|
+
100,000 tasks per job): `zenrows policy set max_pages_per_run 100000` and
|
|
187
|
+
`zenrows policy set max_credits_per_run 2500000`. A workspace created by an
|
|
188
|
+
earlier version keeps its caps (1,000 and 10,000) in `policy.json`.
|
|
189
|
+
|
|
190
|
+
`wait`, `create --follow` and `rerun --follow` poll until the run ends, the run
|
|
191
|
+
is paused, or `--timeout` runs out (default 10 minutes; `30s`, `5m`, `1h`; a
|
|
192
|
+
bare number is milliseconds, as before). When the time runs out, or the run is
|
|
193
|
+
paused, the command exits 0 and prints the run with a `note` and the next
|
|
194
|
+
command; the job keeps running. Ctrl-C stops the wait, not the job, and exits
|
|
195
|
+
130. A run that ends `failed` exits 1: out of credits is
|
|
196
|
+
`POLICY_MAX_CREDITS_EXCEEDED`, an inactive subscription `AUTH_INVALID`, a key
|
|
197
|
+
cap `KEY_CREDIT_CAP_REACHED` (the same codes a refused request gets), anything
|
|
198
|
+
else `BATCH_FAILED`, each with the run's `failure_reason` as `server_code` and
|
|
199
|
+
the `job_id`. Then run the unfinished tasks with
|
|
200
|
+
`zenrows batch rerun <job-id> --status failed,pending,processing`. With no
|
|
201
|
+
flag, `rerun` reruns the `failed` and `pending` tasks, so successful tasks are
|
|
202
|
+
never billed again by surprise; `--status <list>` picks the statuses and
|
|
203
|
+
`--all` reruns every task (not with `--status`). A partial rerun works for 10
|
|
204
|
+
days after the run started; `--all` always does.
|
|
205
|
+
|
|
206
|
+
With `--json`, `create`, `status`, `wait`, `cancel`, `pause`, `resume` and
|
|
207
|
+
`rerun` print `{ok, job_id, run_id, status, stats, job}` (`jobId` is kept for
|
|
208
|
+
older scripts), plus `paused`, `ingest_status`, `accepted_tasks`, `rerun_of`,
|
|
209
|
+
`retried_tasks` and `inherited_tasks` when the API sends them. Results are
|
|
210
|
+
kept 14 days by default and then read `expired`; a `result_url` is valid 2
|
|
211
|
+
hours. Lifecycle errors get their own codes (`BATCH_RUN_IN_PROGRESS`,
|
|
212
|
+
`BATCH_NO_MATCHING_TASKS`, `BATCH_RERUN_WINDOW_EXPIRED`,
|
|
213
|
+
`BATCH_REQUEST_IN_FLIGHT`, `BATCH_RESULT_EXPIRED`, ...) and carry the API's code
|
|
214
|
+
as `server_code`. Schedules, webhooks, ZIP exports, CSV inputs and open jobs
|
|
215
|
+
are available through the Batch API and the SDKs, not this CLI.
|
|
145
216
|
|
|
146
217
|
**Extract in Batch.** Set `"extract": "auto"` on a line to run that URL through
|
|
147
218
|
Extract — structured data instead of raw HTML:
|
|
@@ -186,7 +257,7 @@ zenrows crawl stop <crawl-id> # stop a running crawl
|
|
|
186
257
|
follows links until `--max-items` or `--max-pages` stops it, or nothing is left
|
|
187
258
|
to open. `--max-items` and `--max-pages` cap the crawl (API default 100 each),
|
|
188
259
|
and `--max-pages` bounds the cost, since each page is one fetch. The local policy `max_pages_per_run` caps `--max-pages` (default
|
|
189
|
-
|
|
260
|
+
10000). `--output-format html` uses up the page budget: each kept page is one
|
|
190
261
|
more fetch, and `--max-pages` counts it. `--include-patterns` /
|
|
191
262
|
`--exclude-patterns` are repeatable substring filters on the URL. A crawl whose
|
|
192
263
|
pages held nothing new to follow ends `completed` with no results and exits 0.
|
package/agent-plugin/README.md
CHANGED
|
@@ -62,7 +62,7 @@ Use MCP tool names — not CLI `zenrows fetch`:
|
|
|
62
62
|
| --- | --- |
|
|
63
63
|
| `zenrows` | Decision tree across all primitives |
|
|
64
64
|
| `protected-fetch` | `scrape` |
|
|
65
|
-
| `extract` | `extract` (fallback: `scrape` +
|
|
65
|
+
| `extract` | `extract` (fallback: `scrape` + css_extractor); on REQS007 with reason `domain_not_prepared`, `prepare_domain` then `prepared_domain_status` |
|
|
66
66
|
| `batch-jobs` | `batch_create`, `batch_status`, `batch_results`, `batch_cancel` |
|
|
67
67
|
| `interact-browser` | `browser_*` (escalation only) |
|
|
68
68
|
| `cost-control` | Cost multipliers + escalate-with-evidence |
|
|
@@ -7,7 +7,8 @@ version: 0.1.0
|
|
|
7
7
|
# Batch Jobs (MCP)
|
|
8
8
|
|
|
9
9
|
Process large workloads asynchronously. Batch is where Zenrows' high-scale
|
|
10
|
-
anti-bot advantage becomes obvious
|
|
10
|
+
anti-bot advantage becomes obvious: thousands to 100,000 URLs per job, at
|
|
11
|
+
Fetch's prices.
|
|
11
12
|
|
|
12
13
|
> Cloud Batch lives on `async.api.zenrows.com/v1`. A 403 maps to
|
|
13
14
|
> `BATCH_ACCESS_DENIED`. Do not fake a successful
|
|
@@ -33,10 +34,22 @@ Optional if exposed by the server: `batch_wait` to block until terminal status.
|
|
|
33
34
|
`autoparse`, `extract`, `external_id`, `metadata`). `extract: "auto"`
|
|
34
35
|
returns structured data instead of raw HTML, at the same credit cost as a
|
|
35
36
|
regular task; the result carries `html` and `parsed` keys.
|
|
36
|
-
3. Poll `batch_status` until terminal (`completed
|
|
37
|
-
|
|
37
|
+
3. Poll `batch_status` until terminal (`completed`, `stopped`, `failed` or
|
|
38
|
+
`deleted`). A paused run (`pause_state: paused`) is not terminal and picks
|
|
39
|
+
up no new task until resumed: report it instead of polling on.
|
|
40
|
+
4. Collect with `batch_results`. Results are kept 14 days by default (then a
|
|
41
|
+
row reads `expired`); a `result_url` is valid 2 hours.
|
|
38
42
|
5. `batch_cancel` if the user aborts or the run should stop early.
|
|
39
43
|
|
|
44
|
+
A run ends `failed` when an account problem stops it: `failure_reason`
|
|
45
|
+
`insufficient_credits` (add credits), `subscription_inactive` (fix it in
|
|
46
|
+
Billing) or `api_key_cap_reached` (the key's own cap; the account still has
|
|
47
|
+
credits). The tasks not yet run stay `pending`: once fixed, rerun them with
|
|
48
|
+
status `failed,pending,processing` rather than resubmitting the job.
|
|
49
|
+
|
|
50
|
+
Schedules, webhooks, ZIP exports and CSV inputs are available through the
|
|
51
|
+
Batch API and the SDKs.
|
|
52
|
+
|
|
40
53
|
## Rules
|
|
41
54
|
|
|
42
55
|
- **Never batch before validating** on a single page ([[extract]] /
|
|
@@ -19,8 +19,8 @@ These multipliers apply when you enable the flags (on `scrape` or `extract`):
|
|
|
19
19
|
- Both: **25×**
|
|
20
20
|
|
|
21
21
|
`extract` `mode=auto` is currently free; billing may apply
|
|
22
|
-
later. Do not promise permanent free extract pricing.
|
|
23
|
-
follow the multipliers above when stealth flags are set.
|
|
22
|
+
later. Do not promise permanent free extract pricing. CSS (and the deprecated
|
|
23
|
+
Autoparse) still follow the multipliers above when stealth flags are set.
|
|
24
24
|
|
|
25
25
|
## Browser sessions (`browser_*`)
|
|
26
26
|
|
|
@@ -14,28 +14,67 @@ Convert protected pages into structured data. Value is **protected page access
|
|
|
14
14
|
Use **`extract`** when you need structured JSON fields rather than a full page:
|
|
15
15
|
|
|
16
16
|
```
|
|
17
|
-
extract({ url }) # mode=auto (default)
|
|
18
|
-
extract({ url,
|
|
17
|
+
extract({ url }) # mode=auto (default), returns `parsed` only
|
|
18
|
+
extract({ url, include_html: true }) # also return the full page HTML
|
|
19
|
+
extract({ url, mode: "autoparse" }) # deprecated Autoparse (any domain)
|
|
19
20
|
extract({ url, mode: "css", css_extractor: '{"title":"h1","price":".price"}' })
|
|
20
21
|
extract({ url, proxy_country: "US" }) # geo-targeted
|
|
21
22
|
```
|
|
22
23
|
|
|
23
|
-
`mode=auto` (`extract=auto`) works on any domain
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
`mode=auto` (`extract=auto`) works on any prepared domain, with any key, and
|
|
25
|
+
is currently free; billing may apply later. The result carries `parsed` only;
|
|
26
|
+
the page HTML is most of the response size, so ask for it with
|
|
27
|
+
`include_html: true` only when you need it.
|
|
27
28
|
|
|
28
29
|
Every mode uses Adaptive Stealth Mode by default: pass just the URL, even for
|
|
29
30
|
protected or dynamic sites. Set `js_render` or `premium_proxy` only to force a
|
|
30
31
|
fixed configuration; that turns Adaptive Stealth Mode off. Check `empty` in the
|
|
31
32
|
result: true means no field came back with a value.
|
|
32
33
|
|
|
34
|
+
## REQS007: prepare the domain, then extract again
|
|
35
|
+
|
|
36
|
+
`mode=auto` works on any prepared domain, and you can prepare one yourself.
|
|
37
|
+
When Extract refuses a page, `extract` returns a tool error with code
|
|
38
|
+
`REQS007` (legacy `AUTH010`) and a `reason`. It never retries with Autoparse.
|
|
39
|
+
`fallback_autoparse` is deprecated and has no effect; don't send it.
|
|
40
|
+
|
|
41
|
+
| `reason` | Meaning | Next step |
|
|
42
|
+
| --- | --- | --- |
|
|
43
|
+
| `domain_not_prepared` | The domain is not prepared yet. | `prepare_domain` (the error's `next_tool` holds its arguments), then poll, then `extract` again. |
|
|
44
|
+
| `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 `mode=css`. Do not call `prepare_domain`: preparing again does not change this. |
|
|
45
|
+
| `domain_not_enabled` | Extract is not enabled for the site. | Use `mode=css`, or contact Zenrows support to have the site enabled. Preparing does not change this. |
|
|
46
|
+
|
|
47
|
+
Preparing a domain:
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
extract({ url }) # 1. REQS007, reason domain_not_prepared
|
|
51
|
+
prepare_domain({ domain: "example.com",
|
|
52
|
+
example_urls: ["https://example.com/p/1", "https://example.com/list"] })
|
|
53
|
+
# 2. returns at once, status "preparing"
|
|
54
|
+
prepared_domain_status({ domain: "example.com" }) # 3. about every 30 seconds until "ready"
|
|
55
|
+
extract({ url }) # 4. extract again
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
- `example_urls`: 1 to 5 real pages you want to extract, one per page kind
|
|
59
|
+
(for example a product page and a listing page).
|
|
60
|
+
- The domain is the host: `shop.example.com` and `example.com` are prepared
|
|
61
|
+
separately, and a leading `www.` is dropped.
|
|
62
|
+
- Preparing takes a few minutes and costs no credits. Each new domain uses one
|
|
63
|
+
slot of the account's monthly allowance; `prepared_domain_status` returns it
|
|
64
|
+
(`used` / `limit` / `remaining`) and a `next` field with what to do now.
|
|
65
|
+
- `out_of_allowance`: no slots left this month; use `mode=css`.
|
|
66
|
+
`overloaded` / `disabled`: retry in a few minutes; do not loop.
|
|
67
|
+
A `failed` status carries `failure.code` and `failure.slot_consumed`; follow `next`.
|
|
68
|
+
- A domain that is already prepared answers `ready` at once
|
|
69
|
+
(`already_prepared: true`) and uses no slot: call `extract`. If it then
|
|
70
|
+
returns `page_not_recognised`, follow that row of the table, not `prepare_domain`.
|
|
71
|
+
|
|
33
72
|
## Fallback: `scrape` extraction params
|
|
34
73
|
|
|
35
74
|
If `extract` is unavailable, similar outcomes are available on **`scrape`**:
|
|
36
75
|
|
|
37
76
|
```
|
|
38
|
-
scrape({ url, autoparse: true })
|
|
77
|
+
scrape({ url, autoparse: true }) # deprecated
|
|
39
78
|
scrape({ url, css_extractor: '{"title":"h1","price":".price"}' })
|
|
40
79
|
scrape({ url, outputs: "emails,links" }) # or "*" for all built-ins
|
|
41
80
|
```
|
|
@@ -46,7 +85,8 @@ scrape({ url, outputs: "emails,links" }) # or "*" for all built-ins
|
|
|
46
85
|
## When to use which
|
|
47
86
|
|
|
48
87
|
- **`mode=auto`**: site-tailored fields on any prepared domain.
|
|
49
|
-
- **`mode=autoparse
|
|
88
|
+
- **`mode=autoparse`** (deprecated): any website, only when asked for. Do not
|
|
89
|
+
build new work on it.
|
|
50
90
|
- **`mode=css`**: known fields/selectors; deterministic.
|
|
51
91
|
- **Markdown via `scrape`**: feed clean content to an LLM yourself.
|
|
52
92
|
|
|
@@ -57,7 +97,7 @@ Stealth flags (`js_render`, `premium_proxy`) still apply the usual multipliers
|
|
|
57
97
|
## Rules
|
|
58
98
|
|
|
59
99
|
- Validate on a single page before `batch_create` ([[batch-jobs]]).
|
|
60
|
-
- If
|
|
100
|
+
- If a field is missing, switch to `css_extractor`, or add `js_render`
|
|
61
101
|
for JS-heavy pages.
|
|
62
102
|
- Prefer MCP `extract` / `scrape` over CLI `zenrows extract` when the MCP
|
|
63
103
|
server is connected.
|
|
@@ -34,7 +34,7 @@ scrape({ url, js_render: true, wait_for: ".price" })
|
|
|
34
34
|
- Prefer `response_type: "markdown"` for LLM consumption; use `html` only when
|
|
35
35
|
you need raw markup.
|
|
36
36
|
- For **structured** fields, prefer the `extract` tool (or `scrape` with
|
|
37
|
-
`
|
|
37
|
+
`css_extractor` / `outputs`) — see [[extract]].
|
|
38
38
|
- On failure, escalate with evidence before `browser_*` ([[interact-browser]]).
|
|
39
39
|
- Cost model: [[cost-control]].
|
|
40
40
|
|
|
@@ -37,7 +37,7 @@ If the user has a known URL and wants page content:
|
|
|
37
37
|
|
|
38
38
|
If the user has a known URL and wants structured data:
|
|
39
39
|
→ Use Extract. (MCP tool: extract)
|
|
40
|
-
Fallback: scrape with
|
|
40
|
+
Fallback: scrape with css_extractor / outputs
|
|
41
41
|
|
|
42
42
|
If the user has many URLs (bulk):
|
|
43
43
|
→ Use Batch. (validate one page with scrape/extract first,
|
|
@@ -67,7 +67,8 @@ If the user needs login, clicks, forms, sessions, or persistent state:
|
|
|
67
67
|
| Primitive | MCP tools | Notes |
|
|
68
68
|
| --- | --- | --- |
|
|
69
69
|
| Protected Fetch | `scrape` | Default markdown; HTML / plaintext / PDF / screenshot options |
|
|
70
|
-
| Extract | `extract` | Structured JSON (`extract=auto
|
|
70
|
+
| Extract | `extract` | Structured JSON (`extract=auto` on any prepared domain, css_extractor; autoparse deprecated). `extract=auto` is currently free; billing may apply later |
|
|
71
|
+
| Prepare a domain | `prepare_domain`, `prepared_domain_status` | After an `extract` REQS007 with reason `domain_not_prepared`: prepare the domain with 1 to 5 example URLs, poll about every 30 seconds until ready, extract again. No credits; uses one monthly allowance slot. Not for `page_not_recognised`: that domain is already prepared |
|
|
71
72
|
| Batch | `batch_create`, `batch_status`, `batch_results`, `batch_cancel` | Same credits as Fetch; a 403 maps to `BATCH_ACCESS_DENIED` |
|
|
72
73
|
| Browser | `browser_*` (start with `browser_navigate`) | Escalation-only; same backend as Browser Sessions |
|
|
73
74
|
|