Skip to content

feat(extract): remove the autoparse fallback and add zenrows extract prepare - #47

Merged
jonathan-zenrows merged 10 commits into
mainfrom
feat/extract-prepare-domain
Oct 20, 2026
Merged

jonathan-zenrows merged 10 commits into
mainfrom
feat/extract-prepare-domain

Conversation

@zenrows-dev-pool

@zenrows-dev-pool zenrows-dev-pool Bot commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

Summary

zenrows extract no longer retries with the deprecated Autoparse when Extract has not prepared a domain. It reports the error with the exact command to prepare the domain, and this PR adds that command (zenrows extract prepare), so users can prepare a domain themselves and extract again.

Flow: zenrows extract <url> → REQS007 → zenrows extract prepare <domain> --url <url> --wait → zenrows extract <url>.

Breaking / behaviour changes

  • The Autoparse fallback is removed. On 403 REQS007 (or the legacy 402 AUTH010), zenrows extract makes one request and reports the error with the prepare step. No code path retries with autoparse=true any more, whatever the caller passes. The adapter option fallbackAutoparse is still accepted so existing callers keep working, but it is deprecated and has no effect; when it is true, the CLI prints one deprecation warning on stderr. --autoparse is a different thing (the user asks for Autoparse directly) and is unchanged: it still runs Autoparse and warns that it is deprecated.
  • fellBackToAutoparse is removed from the adapter outcome, the run artifact and the --json output, since it can never be true now.
  • Stricter empty-result check. A result whose fields are all null, "" or [], at any depth, is now empty: true. Before, only {}, [], null and blank strings were empty, so page scaffolding read as data. --validate fails on such results and the plain run prints the empty-result warning. 0 and false still count as data.
  • REQS007 codes renamed to say what they mean. A domain not prepared yet is now EXTRACT_DOMAIN_NOT_PREPARED (it was EXTRACT_DOMAIN_NOT_ENABLED). A domain Extract is not enabled for is EXTRACT_DOMAIN_NOT_ENABLED. The page case is the new EXTRACT_PAGE_NOT_RECOGNISED. Code that compared against the old EXTRACT_DOMAIN_NOT_ENABLED did so to fall back to Autoparse, and that fallback no longer exists, so there is nothing left for that comparison to do.

REQS007: three cases, three answers

The API answers REQS007 in three cases. It names the case in a reason field, which arrives with an upcoming API deploy. The CLI reads that field first. Until the deploy, it falls back to the problem title and detail, which the API sends today. A comment in src/core/http.ts marks that fallback for removal.

reason Body title today CLI error Next step it prints
domain_not_prepared Extract is not prepared for the requested domain (…) EXTRACT_DOMAIN_NOT_PREPARED the exact zenrows extract prepare <domain> --url <url> command, --wait, status, and --css meanwhile
page_not_recognised Extract did not recognise this page on … EXTRACT_PAGE_NOT_RECOGNISED the API's own advice, in the API's order: try a product, article or listing page; if this page should work, retry it once in a few minutes, not in a loop; otherwise --css. Preparing again does not change it
domain_not_enabled Extract is not enabled for the requested domain (…) EXTRACT_DOMAIN_NOT_ENABLED --css, or contact support to have the site enabled; preparing does not help

page_not_recognised is not a missing page kind. On a prepared domain Extract learns a new kind of page on its first request, so this answer means the page is not one Extract extracts (a home, search, login or category page), or a transient failure kept it from trying. Sending the agent to prepare would loop, because resubmitting a prepared domain returns its ready record at once. That is why a submit answering ready at once sets already_prepared: true, and why the ready next step repeats the page advice. None of the messages offer Autoparse.

zenrows extract prepare

  • zenrows extract prepare <domain> --url <u> [--url <u>...] [--wait [--timeout <s>]] calls POST /v1/extract/prepared-domains (X-API-Key) and returns at once. --url takes 1 to 5 full http(s) URLs; anything else is rejected before any request. --wait polls every 30 seconds (the same interval the MCP server tells agents) until ready or failed; default timeout 900 seconds.
  • zenrows extract prepare status <domain> shows status, state, roles, the failure, the monthly allowance (used / limit / remaining) and the next step.
  • It never creates a Free plan account: it needs a key the user already has.
  • The domain is the host, minus a leading www.; it is not reduced to the registrable domain, because Extract prepares each host on its own (verified in production, below).
Answer Result
202 preparing Status record, next step (prepare status …)
202 ready at once already_prepared: true; do not loop, use --css
409 in_progress Follows the running preparation; EXTRACT_PREPARE_IN_PROGRESS only when this account cannot read it
400 invalid_argument / 409 idempotency_conflict EXTRACT_PREPARE_INVALID (with reason)
404 not_found (status) EXTRACT_PREPARE_NOT_FOUND, with the prepare command
429 out_of_allowance EXTRACT_PREPARE_OUT_OF_ALLOWANCE (with used / limit); do not retry this month, use --css
503 overloaded / disabled EXTRACT_PREPARE_UNAVAILABLE; retry in a few minutes, do not loop
status failed EXTRACT_PREPARE_FAILED, exit 1, with the step for the failure code; whether the attempt used an allowance slot comes from failure.slot_consumed
--wait runs out EXTRACT_PREPARE_TIMEOUT, with the status command

Docs and skills

skills/extract, skills/zenrows, agent-plugin/skills/*, README.md, docs/capabilities.md, the competitor-intelligence workflow, the pricing template and registry/*.json teach the flow, the do-not-loop rule and the host rule. They mark Autoparse deprecated and say "any prepared domain (you can prepare one yourself)". The agent-plugin extract skill describes the MCP server's prepare_domain / prepared_domain_status tools, which ship in the matching zenrows-mcp PR.

Production smoke test of the fallback removal

Local build of this branch against https://api.zenrows.com, key from the environment, every request to the API counted. Target: https://web-scraping.dev/product/1, a domain that is not prepared (absent from GET /v1/extract/domains) and not forbidden (a plain fetch returns 200).

Step Requests Result
a) zenrows extract <url>, defaults 1 (extract=auto&mode=auto, 403) exit 1, EXTRACT_DOMAIN_NOT_PREPARED (server code REQS007), first suggested command zenrows extract prepare web-scraping.dev --url https://web-scraping.dev/product/1 --wait
b) adapter runExtract with fallbackAutoparse: true 1 (extract=auto&mode=auto, 403) the same error, plus one stderr line: "fallbackAutoparse is deprecated and has no effect: Extract no longer falls back to Autoparse. …"

No step called prepare, so no allowance slot was used.

Verified against production

Local build of this branch against https://api.zenrows.com, no base override, key from the environment. Second pass, with the final texts. The production API does not send reason yet, so these runs also exercise the title fallback. They ran before the code rename: the same output now starts ✗ [EXTRACT_DOMAIN_NOT_PREPARED].

$ zenrows extract https://books.toscrape.com/catalogue/a-light-in-the-attic_1000/index.html
✗ [EXTRACT_DOMAIN_NOT_ENABLED] Extract hasn't prepared books.toscrape.com yet. Prepare it with `zenrows extract prepare books.toscrape.com --url https://books.toscrape.com/catalogue/a-light-in-the-attic_1000/index.html` (a few example URLs, a few minutes, no credits), then retry; meanwhile use --css.
  cause: (REQS007) Extract is not prepared for the requested domain (books.toscrape.com) (REQS007)
  next:  Run `zenrows extract prepare books.toscrape.com --url https://books.toscrape.com/catalogue/a-light-in-the-attic_1000/index.html --wait` (up to 5 --url pages, one per page kind you want), then retry `zenrows extract https://books.toscrape.com/catalogue/a-light-in-the-attic_1000/index.html`. Without --wait, check progress about every 30 seconds with `zenrows extract prepare status books.toscrape.com`. Meanwhile extract with --css and explicit selectors.
  $ zenrows extract prepare books.toscrape.com --url https://books.toscrape.com/catalogue/a-light-in-the-attic_1000/index.html --wait
  $ zenrows extract prepare status books.toscrape.com
  $ zenrows extract https://books.toscrape.com/catalogue/a-light-in-the-attic_1000/index.html --css '{"title":"h1"}'

$ zenrows extract prepare scrapingcourse.com --url https://www.scrapingcourse.com/ecommerce/ --wait
✓ scrapingcourse.com: ready
scrapingcourse.com is already prepared, so nothing new was submitted: run the extract (`zenrows extract https://www.scrapingcourse.com/ecommerce/`). If the extract then fails with EXTRACT_PAGE_NOT_RECOGNISED, Extract did not recognise that page. 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 with explicit selectors. Preparing the domain again does not change this.

$ zenrows extract prepare status sandbox.oxylabs.io
✗ [EXTRACT_PREPARE_NOT_FOUND] This account has not submitted sandbox.oxylabs.io for preparation.
  cause: (not_found) This domain has never been submitted.
  next:  Prepare it first: zenrows extract prepare sandbox.oxylabs.io --url <page url> (1 to 5 --url).

The already-prepared submit used no allowance slot: the allowance stayed at 1 of 10 before and after.

The page_not_recognised REQS007 still does not reproduce in production: search, login, cart and listing pages on prepared domains all came back 200 with data. That path is covered by tests that use the API's body, with and without reason.

From the first pass, still valid:

  • Hosts are keyed separately: pt.wikipedia.org answers REQS007 although es.wikipedia.org is ready, and www.scrapethissite.com is stored as scrapethissite.com.
  • End to end on scrapeme.live: REQS007, then prepare --wait reached ready in 2 min 31 s, then the extract returned 200 with data. That run used one slot.

Ordering

Release this only after the API deploy that adds the reason field to REQS007 is live in production. The client reads reason first and keeps a title match only for an API without it, but the docs describe reason, and the docs and both client releases should go out after the API carries it.

Release

No version change here. Per docs/contributing.md, release-please sets the version from the feat(extract) title after merge.

Tests

  • npm run typecheck and npm run build: clean. The repo has no linter beyond tsc.
  • npm test: 394 passed, 0 failed.
    • fallbackAutoparse: true on REQS007 and on AUTH010: one request, EXTRACT_DOMAIN_NOT_PREPARED with the prepare command, and exactly one deprecation warning on stderr. No warning without the option or with it false.
    • All three REQS007 cases, read from reason and, separately, from the title only. Each test checks the advice order for page_not_recognised, and that no prepare command and no Autoparse appear where they must not.
    • refusalReason prefers the field, and ignores a reason it does not know.
    • prepare: 202 preparing, ready at once (already_prepared), --wait ending in ready, failed and timeout, 409 followed and 409 unreadable, 400, 429, 503 overloaded and disabled, --url validation, no automatic account creation.
    • status with and without the allowance, and on 404.
    • Every failure code, with and without slot_consumed.
    • The empty-result rule, the capability notes, and routing from zenrows extract.

…g back to autoparse

On 403 REQS007 (domain not prepared yet) or the legacy 402 AUTH010,
`zenrows extract` used to retry with the deprecated autoparse. That hid
the prepare step, charged for an Autoparse call and often returned
unusable data. The error is now reported, not retried, and names the
next step:

  Extract hasn't prepared <domain> yet. Prepare it with POST
  /v1/extract/prepared-domains (a few example URLs, a few minutes, no
  credits), then retry; or run with --autoparse.

`--autoparse` stays as the explicit opt-in and now warns that Autoparse
is deprecated. The adapter's `fallbackAutoparse` option defaults to
false.

The empty-result check now treats a payload whose fields are all null
or empty (recursively) as empty, so page scaffolding no longer reads as
data.

Skills, docs and the capability matrix describe the prepare step, mark
autoparse deprecated and drop the fallback wording.
Removing the autoparse fallback leaves REQS007 as the answer on a domain
Extract has not prepared yet, so CLI users need a way to prepare one.

- `zenrows extract prepare <domain> --url <u> [--url <u>...]` submits
  the domain with 1 to 5 example URLs to
  POST /v1/extract/prepared-domains and returns at once. `--wait`
  (off by default) polls until ready or failed, up to `--timeout`.
  On 409 in_progress it follows the running preparation.
- `zenrows extract prepare status <domain>` shows progress, the failure
  code and detail, the account's monthly allowance and the next step.
- Errors name the next step: EXTRACT_PREPARE_INVALID (400),
  EXTRACT_PREPARE_NOT_FOUND (404), EXTRACT_PREPARE_IN_PROGRESS (409),
  EXTRACT_PREPARE_OUT_OF_ALLOWANCE (429), EXTRACT_PREPARE_UNAVAILABLE
  (503 overloaded / disabled), EXTRACT_PREPARE_FAILED (failed status,
  with the step for its failure code), EXTRACT_PREPARE_TIMEOUT.
- The REQS007 error now prints the exact command:
  zenrows extract prepare <domain> --url <url>.

Skills, README and the capability matrix teach the flow: extract,
REQS007, prepare, poll, extract again.
@zenrows-dev-pool zenrows-dev-pool Bot changed the title feat(extract): report REQS007 with the prepare step instead of falling back to autoparse feat(extract): replace the autoparse fallback with zenrows extract prepare Oct 15, 2026
@jonathan-zenrows jonathan-zenrows self-assigned this Oct 15, 2026
…he error

REQS007 has two causes. On a domain not prepared yet, preparing it is
the fix. On a prepared domain, the gateway answers REQS007 with "Extract
did not recognise this page" when it does not cover that kind of page,
and resubmitting the domain only returns its existing ready record. The
old wording sent agents round extract, prepare (ready at once), extract
again.

- A REQS007 whose body says the page was not recognised is now
  EXTRACT_PAGE_NOT_RECOGNISED: use --css or contact support with the
  URL; no prepare command.
- `zenrows extract prepare` answering ready at once sets
  `already_prepared` and says that a REQS007 on that domain means the
  kind of page is not covered, instead of "run the extract again".
- The REQS007 error no longer offers --autoparse; it offers --css.
- failureNextStep says whether the attempt used an allowance slot from
  failure.slot_consumed, not from the failure code.
- `zenrows extract prepare` never creates a Free plan account; the
  unused --no-signup flag is gone.
- Each function in http.ts has its own doc comment again.
- normalizeDomain keeps the full host: Extract prepares each host on its
  own (a prepared es.wikipedia.org does not cover pt.wikipedia.org).
- Poll interval: 30 seconds, shared with the MCP server.
@jonathan-zenrows
jonathan-zenrows marked this pull request as ready for review October 15, 2026 14:11
…for an unrecognised page

The API now says which REQS007 it is in a `reason` field:
domain_not_prepared, page_not_recognised or domain_not_enabled. The
error is classified by that field first; matching the API's sentences
stays only as the fallback for an API that does not send it yet, and
says so in a comment.

page_not_recognised does not mean that a kind of page is missing: on a
prepared domain Extract learns a new kind of page on its first request,
so the page is not one Extract extracts (a home, search, login or
category page) or a transient failure kept it from trying. The error
now gives the API's advice in the API's order: try a product, article
or listing page; if this page should work, retry it once in a few
minutes, not in a loop; otherwise use css. It no longer says "not
covered" or sends to support first, and it still says that preparing
again changes nothing.

domain_not_enabled says that preparing does not help, and offers css.

The "ready" and "already prepared" next steps say the same thing for a
later page_not_recognised. Skills, help, README, docs and tool
descriptions now tell one story with one vocabulary: prepared, ready,
page kind, allowance slot, a few minutes, about every 30 seconds.
…tract, not a search or category page

Production extracts search and category pages on prepared domains: a
prepared domain learns any new kind of page on its first request. The
example list "a home, search, login or category page" for a page
Extract did not recognise was therefore wrong for two of its four
entries, and it contradicted the advice to send a search results URL as
an example. The page-not-recognised wording now says "a page with
nothing to extract, such as a home page", everywhere it appears.
A domain Extract has not prepared yet is now EXTRACT_DOMAIN_NOT_PREPARED
(it was EXTRACT_DOMAIN_NOT_ENABLED), and a domain Extract is not enabled
for is now EXTRACT_DOMAIN_NOT_ENABLED (it was EXTRACT_DOMAIN_NOT_ALLOWED).
Help, skills, docs, the capability registry and tests use the new names.

Code that compared against the old EXTRACT_DOMAIN_NOT_ENABLED did so to
fall back to autoparse, and that fallback no longer exists.
zenrows extract no longer retries a refused Extract request with Autoparse,
on any REQS007 or AUTH010, whatever the caller passes. The adapter option
fallbackAutoparse is still accepted so existing callers keep working, but
it is deprecated and has no effect: when it is true, the CLI prints one
deprecation warning on stderr. fellBackToAutoparse is gone from the
outcome, the run artifact and the --json output, since it can never be
true. The explicit --autoparse flag is unchanged.
@zenrows-dev-pool zenrows-dev-pool Bot changed the title feat(extract): replace the autoparse fallback with zenrows extract prepare feat(extract): remove the autoparse fallback and add zenrows extract prepare Oct 16, 2026
@jonathan-zenrows
jonathan-zenrows merged commit 88a33d6 into main Oct 20, 2026
3 checks passed
@jonathan-zenrows
jonathan-zenrows deleted the feat/extract-prepare-domain branch October 20, 2026 10:29
@github-actions github-actions Bot mentioned this pull request Oct 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant