Skip to main content
Glama
mysleekdesigns

CrawlForge MCP Server

extract_embedded_state

Read-onlyIdempotent

Extract embedded JavaScript state from a page's framework payloads, such as Next.js, Nuxt, or ytInitialData, to get exact structured values from one fetch.

Instructions

Use this when a page's data lives in its embedded JavaScript state rather than its rendered HTML - Next.js (NEXT_DATA, and React Server Component payloads with references between rows resolved plus a data_rows index of the rows carrying data), Nuxt (Nuxt 3's NUXT_DATA decoded), SvelteKit, Apollo, Redux (INITIAL_STATE, PRELOADED_STATE), ytInitialData and ytInitialPlayerResponse, Inertia, Shopify, JSON data-* attributes and blocks. One fetch, exact values, no LLM in the extraction path, so nothing can be fabricated. Payloads are routinely over a megabyte - pass path to return one subtree, keys_only:true to see the first two levels of keys before choosing one, or find:"" to get every path where a field of that name lives, each ready to pass back as path. A result over max_inline_chars comes back as a preview (whole lines of the JSON), data_keys and a result_handle; read the rest with read_result json_path, e.g. "data.next_data.props". Set escalate:true when the site is known to block: the plain fetch still runs first, and only if it is walled does the stealth browser re-read the page, run the same parser and also read the globals off window (window_state: NEXT_DATA, NUXT, ytInitialData and others, read after JavaScript ran) - projected at 7, charged 2 when the plain fetch worked. Not for the rendered text of a page (scrape) or for sites built without a framework payload. Cost: 2 credits. Example: extract_embedded_state({url: "https://www.ticketmaster.com/discover/concerts", path: "next_data.props.pageProps"})

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
rawNoAlso keep the undecoded __NUXT_DATA__ devalue array under json_scripts, beside the decoded nuxt_data. Default: false
urlYesThe URL to read embedded state from
findNoReturn `matches` instead of `data`: every property with this key name (case-insensitive) anywhere in the selected data (after `path`), in document order, each as {path, preview} with the first 200 characters of its value - at most 50, with `matches_total` and `matches_truncated`. Each match path already starts with `path`, so it can be passed straight back as `path`. Discover where a field lives without downloading the payload. Cannot be combined with keys_only
pathNoReturn only this subtree instead of the whole payload. Dotted keys and array indexes, e.g. "next_data.props.pageProps" or "next_f[0].f" — not JSONPath (no wildcards, filters or recursion). State payloads are routinely over a megabyte; scope them.
escalateNoWhen the plain fetch comes back blocked (403/429/challenge page, or an empty shell with no state), re-read the page once in the stealth browser and run the same parser on the rendered document; the browser also reads the framework globals off window (window_state). Under escalate_engine "auto" a Chrome TLS handshake with the honest CrawlForge User-Agent (impit) is tried first, and the browser runs only when that does not get the page. A 404 or 5xx never escalates. Projected at 2+5; the actual charge stays at 2 when the plain fetch succeeded. Default: false
wait_forNoEscalated render only: extra wait after page load, in ms — for state assigned after DOMContentLoaded. Ignored without escalation
keys_onlyNoReturn `keys` instead of `data`: the first two levels of keys of the selected data (after `path`), each value replaced by its type ("object", "array(<n>)", "string", "number", "boolean", "null"); an array shows its length and its first item. Cheap discovery before choosing a path. Default: false
user_agentNoOverride the outbound User-Agent. CrawlForge identifies itself honestly by default; use this only for targets you have your own agreement with.
respect_robotsNoRespect the target site's robots.txt (default: true). Setting this to false is honoured, returns a warning in the response, and is recorded against your API key — it is your decision, not a silent default.
escalate_engineNoStealth engine for the escalated retry: "auto" (default — Camoufox when it is installed, Chromium otherwise, reported in warnings), "playwright" (Chromium) or "camoufox"auto
max_inline_charsNoLargest result to return inline, in characters of its JSON. Over it, the call returns a preview plus a result_handle for read_result instead of the whole result (default 40,000; env CRAWLFORGE_MAX_INLINE_CHARS)

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed2 schema fields changedv6.18.1
    • addedInput schema / properties / find
      Added value: +{
      +  "description": "Return `matches` instead of `data`: every property with this key name (case-insensitive) anywhere in the selected data (after `path`), in document order, each as {path, preview} with the first 200 characters of its value - at most 50, with `matches_total` and `matches_truncated`. Each match path already starts with `path`, so it can be passed straight back as `path`. Discover where a field lives without downloading the payload. Cannot be combined with keys_only",
      +  "maxLength": 100,
      +  "minLength": 1,
      +  "type": "string"
      +}
    • addedInput schema / properties / raw
      Added value: +{
      +  "default": false,
      +  "description": "Also keep the undecoded __NUXT_DATA__ devalue array under json_scripts, beside the decoded nuxt_data. Default: false",
      +  "type": "boolean"
      +}
  2. Changed4 schema fields changedv6.14.0
    • addedInput schema / properties / escalate
      Added value: +{
      +  "default": false,
      +  "description": "When the plain fetch comes back blocked (403/429/challenge page, or an empty shell with no state), re-read the page once in the stealth browser and run the same parser on the rendered document; the browser also reads the framework globals off window (window_state). Under escalate_engine \"auto\" a Chrome TLS handshake with the honest CrawlForge User-Agent (impit) is tried first, and the browser runs only when that does not get the page. A 404 or 5xx never escalates. Projected at 2+5; the actual charge stays at 2 when the plain fetch succeeded. Default: false",
      +  "type": "boolean"
      +}
    • addedInput schema / properties / escalate_engine
      Added value: +{
      +  "default": "auto",
      +  "description": "Stealth engine for the escalated retry: \"auto\" (default — Camoufox when it is installed, Chromium otherwise, reported in warnings), \"playwright\" (Chromium) or \"camoufox\"",
      +  "enum": [
      +    "auto",
      +    "playwright",
      +    "camoufox"
      +  ],
      +  "type": "string"
      +}
    • addedInput schema / properties / keys_only
      Added value: +{
      +  "default": false,
      +  "description": "Return `keys` instead of `data`: the first two levels of keys of the selected data (after `path`), each value replaced by its type (\"object\", \"array(<n>)\", \"string\", \"number\", \"boolean\", \"null\"); an array shows its length and its first item. Cheap discovery before choosing a path. Default: false",
      +  "type": "boolean"
      +}
    • addedInput schema / properties / wait_for
      Added value: +{
      +  "description": "Escalated render only: extra wait after page load, in ms — for state assigned after DOMContentLoaded. Ignored without escalation",
      +  "maximum": 30000,
      +  "minimum": 0,
      +  "type": "number"
      +}
  3. Changed2 schema fields changedv6.0.0
    • removedInput schema / additionalProperties
      Removed value: -false
    • addedInput schema / properties / max_inline_chars
      Added value: +{
      +  "description": "Largest result to return inline, in characters of its JSON. Over it, the call returns a preview plus a result_handle for read_result instead of the whole result (default 40,000; env CRAWLFORGE_MAX_INLINE_CHARS)",
      +  "maximum": 10000000,
      +  "minimum": 1000,
      +  "type": "integer"
      +}
  4. Addedv5.4.0

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already establish the read-only/idempotent/no-destruction profile, and the description still adds substantial behavior beyond them: exact cost (2 credits), the projected-vs-charged escalation pricing (7 projected, 2 charged when the plain fetch worked), the conditions that trigger escalation and the ones that never do (404/5xx), and the over-max_inline_chars fallback to a preview plus result_handle read via read_result. This is the kind of context annotations cannot carry.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The routing sentence is correctly front-loaded, but the body is a single dense paragraph of nested parentheticals that restates much of what the 100%-covered schema already documents (path, keys_only, find, escalate). Information-dense rather than wasteful, yet harder to scan than it needs to be for a tool with 11 parameters.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description carries the return-shape burden and does so: it describes the data_rows index, the matches/matches_total/matches_truncated shape of find, the keys/type listing of keys_only, and the preview + result_handle contract for oversized results. Combined with the annotation-covered safety profile and full schema coverage, an agent has everything needed to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description goes beyond the schema by explaining how the parameters interact and what workflow they enable: find returns match paths 'ready to pass back as path', keys_only is for cheap key discovery before choosing a path, and the example shows a real path expression. It duplicates several schema details, but the combined-usage guidance is genuinely additive.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a precise verb+resource (extract a page's embedded JavaScript state) and enumerates the concrete framework payloads it targets (__NEXT_DATA__, __NUXT_DATA__, SvelteKit, Apollo, Redux, ytInitialData, Shopify, JSON script blocks). It also explicitly distinguishes itself from the sibling `scrape` for rendered HTML, so an agent can route without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The opening clause gives the exact selection condition (a page whose data lives in embedded state rather than rendered HTML) and the closing sentence gives both exclusions: 'Not for the rendered text of a page (scrape) or for sites built without a framework payload.' It also prescribes the escalation workflow (set escalate:true only when the site is known to block) and the discovery-first pattern (keys_only before choosing a path).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.