CrawlForge MCP
结构化提取2 credits

extract_embedded_state

现代站点会把界面所渲染的数据直接序列化进文档。本工具把它读回来:一次抓取、数值精确,提取链路中没有任何模型。

使用场景

从 JavaScript 渲染的页面取得精确价格

价格、库存和 ID 来自站点自身的状态,而不是由模型阅读渲染后的文本得出,因此无从编造。

普通抓取看不到的列表

客户端渲染的搜索结果和商品网格,通常在首次响应的 __NEXT_DATA__ 或 RSC 负载中就已经存在。

比 LLM 提取更省

2 credits,而 extract_with_llm 或 extract_structured 为 3 credits,而且不必等待推理步骤。

审查站点对自身发布了什么

found 会报告页面上的每一个状态来源及其大小,往往比可见界面所展示的更多。

Endpoint

POST/api/v1/tools/extract_embedded_state
Auth Required
Free 套餐 1 req/s
2 credits

Parameters

NameTypeRequiredDefaultDescription
url
stringRequired-
要读取嵌入状态的页面。
Example: https://example.com/products/widget
path
stringOptional-
只返回一个子树,而不是整个负载。仅支持点号分隔的键和数组索引——这不是 JSONPath,因此没有通配符、过滤器、切片或递归下降。无法解析的路径会返回 400,并列出中断处可用的键,且不消耗 credits。
Example: next_data.props.pageProps
user_agent
stringOptional-
覆盖发送给目标站点的 User-Agent。请求仍以 CrawlForge 的身份签名;签名覆盖的是 authority,而不是该请求头。
Example: MyCompanyBot/1.0
respect_robots
booleanOptionaltrue
遵守目标站点的 robots.txt。保持为 `true` 时,对 `CrawlForge` 禁止的路径会在抓取之前以 403 拒绝,并且不扣除 credits。只有在您与目标站点另有协议时才设为 `false`——此时响应会带有 `warnings` 条目,并且该覆盖会记录在您的 API key 上。
Example: true
timeout
numberOptional20000
抓取超时(毫秒),取值 1000 到 60000。状态负载常常有数兆字节,因此默认值高于更轻量的提取工具。
Example: 20000

请求示例

cURL - 读取完整状态

terminalBash
curl -X POST https://crawlforge.dev/api/v1/tools/extract_embedded_state \
  -H "X-API-Key: cf_test_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/products/widget"
  }'

TypeScript - 用 path 缩小范围

extractEmbeddedState.tsTypescript
const response = await fetch('https://crawlforge.dev/api/v1/tools/extract_embedded_state', {
  method: 'POST',
  headers: {
    'X-API-Key': process.env.CRAWLFORGE_API_KEY!,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    url: 'https://example.com/products/widget',
    // Dotted keys and array indexes. Not JSONPath: no wildcards or filters.
    path: 'next_data.props.pageProps',
  }),
});

const payload = await response.json();
if (!response.ok) {
  // A path that does not resolve is a 400 naming the keys that were available.
  throw new Error(payload.error.code + ': ' + payload.error.message);
}

const result = payload.data;

// Every state source on the page, largest first, whether or not it was scoped.
for (const source of result.found) {
  console.log(source.name, source.variable, source.bytes);
}

// The values are the site's own, so they can be used as they are.
console.log(result.data.product.price);

Python - 先发现,再缩小范围

extract_embedded_state.pyPython
import os
import requests

URL = 'https://crawlforge.dev/api/v1/tools/extract_embedded_state'
HEADERS = {
    'X-API-Key': os.environ['CRAWLFORGE_API_KEY'],
    'Content-Type': 'application/json',
}

# 1. Discover what the page carries. Nothing is truncated, so this can be big.
discovery = requests.post(
    URL,
    headers=HEADERS,
    json={'url': 'https://example.com/products/widget'},
).json()

for source in discovery['data']['found']:
    print(source['name'], source['variable'], source['bytes'])

for warning in discovery['data']['warnings']:
    print('warning:', warning)

# 2. Ask again for just the branch you want.
scoped = requests.post(
    URL,
    headers=HEADERS,
    json={
        'url': 'https://example.com/products/widget',
        'path': 'next_data.props.pageProps.product',
    },
)

payload = scoped.json()
if not scoped.ok:
    error = payload['error']
    raise RuntimeError(f"{error['code']}: {error['message']}")

print(payload['data']['bytes'], 'bytes')
print(payload['data']['data'])

响应示例

200 OK980ms
{
"success": true,
"data": {
"url": "https://example.com/products/widget",
"found": [
{
"name": "next_data",
"variable": "__NEXT_DATA__",
"bytes": 412880
}
],
"path": null,
"bytes": 412893,
"data": {
"next_data": {
"buildId": "KfC_3GF1zuM",
"props": {
"pageProps": {
"product": {
"sku": "WID-9001",
"price": 149.99,
"currency": "USD",
"inStock": true
}
}
}
}
},
"warnings": [
"Result is 412893 bytes; \"next_data\" alone is 412880. Re-run with path to scope it, e.g. path:\"next_data.props\"."
]
},
"credits_used": 2,
"credits_remaining": 998,
"processing_time": 980
}
Field Descriptions
data.found页面上的每一个状态来源,包含读取自的原始对象及其序列化大小
data.path所应用的路径;返回完整负载时为 null
data.bytes所返回内容的序列化大小——给出 path 时即为缩小后的大小
data.data状态本身,按来源名称索引
data.warnings存在但无法按 JSON 解析的来源,以及建议使用 path 的大小提示

错误处理

路径无法解析 (400 Bad Request)

path 在所提取的状态中不存在。消息会指出中断的位置以及该处可用的键,因此拼写错误可以直接修正。不扣除 credits。先不带 path 调用一次,即可看到页面实际携带的内容。

被 robots.txt 阻止 (403 Forbidden)

目标站点的 robots.txt 禁止 CrawlForge 访问此路径。如果您与目标站点另有协议,可设置 respect_robots: false 覆盖——该覆盖会记录在您的 API key 上。此覆盖对 CrawlForge 永久排除名单上的主机无效,无论 respect_robots 取何值都会被拒绝。

响应过大 (413 Payload Too Large)

页面 HTML 超过 25MB 的响应体上限。该上限针对服务端返回的页面本身,而非从中提取的状态。不收取任何费用。

目标未响应 (504 Gateway Timeout)

站点未在 timeout 内响应。状态密集的页面体积很大;在判定为失败之前,请先把 timeout 调高至 60000 的上限。不收取任何费用。

相关工具

extract_structured
当数据位于标记中而非状态块中时,使用基于 schema 的提取(3 credits)
extract_with_llm
针对完全不做序列化的页面的自然语言提取(3 credits)
extract_metadata
JSON-LD、OpenGraph 和 Twitter Card 标签,本工具有意不处理这些内容(1 credit)
准备好读取页面自己的数据了吗?免费注册,即可获得 1,000 credits。

页脚

CrawlForge MCP

面向 AI Agent 的企业级网页抓取。29 个专业 MCP 工具,专为构建智能系统的现代开发者而设计。

产品

  • 功能
  • Playground
  • 价格
  • 应用场景
  • 集成
  • 替代方案
  • 更新日志

资源

  • 快速上手
  • API 参考
  • 模板
  • 指南
  • 博客
  • 术语表
  • 常见问题
  • 网站地图

开发者

  • MCP 协议
  • Claude Desktop
  • Cursor IDE
  • LangChain
  • LlamaIndex

公司

  • 关于我们
  • 联系我们
  • 隐私政策
  • 服务条款
  • 可接受使用政策
  • Cookie

保持更新

获取新工具和新功能的最新动态。

基于 Next.js 和 MCP 协议构建

© 2025-2026 CrawlForge。保留所有权利。