CrawlForge MCP
基础工具多格式2 credits

scrape

一次抓取即可完成的统一多格式提取。对同一次页面加载请求 markdown、HTML、原始 HTML、纯文本、链接、元数据、截图或 JSON——所有请求的格式都由同一次抓取提供,某个格式失败时会以警告形式返回,而不会让整次调用失败。加上带查询的 highlights 或 question 格式,只返回匹配的句子、表格行和代码块——页面逐字原文并附带指向 markdown 的偏移量,全程没有模型参与——只多 1 credit。传入 escalate: true 后,若返回的是反爬墙而不是页面,同一次调用会通过 stealth 浏览器重新抓取一次,加收 5 credits。

使用场景

一次调用替代四次

在一次请求中拿到页面的 markdown、链接和元数据,无需串联 fetch_url、extract_links 和 extract_metadata。

可直接喂给 LLM 的 markdown

开启 onlyMainContent 并请求 markdown,把干净、无模板噪声的页面文本直接送入 RAG 流水线或提示词。

存档快照

同时请求 rawHtml 与 markdown,只需一次抓取即可同时保留精确的源代码和一份干净的可读副本。

一次抓取,多种格式

六种格式与一种格式同样只需 2 credits,因此需要 markdown、links 与 metadata 的流水线应当在一次调用中一并请求,而不是分三次。

引用页面,而不是概括它

用查询请求 highlights,或用问题请求 question,只拿到匹配的句子、表格行和代码块——页面逐字原文,并附带指向同一次调用 markdown 的偏移量,让智能体引用原文而不是转述。与做摘要的抓取工具不同,全程没有模型参与。

Endpoint

POST/api/v1/tools/scrape
Auth Required
Free 计划 1 req/s
2 credits

Parameters

所有请求的格式都由同一次页面抓取提供,因此请求六种格式与请求一种格式同样是 2 credits。按查询范围限定的 highlights 或 question 格式加收 1 credit,每次请求只收一次,不论包含一种还是两种。使用 escalate: true 时,预估值即上限:7 credits(与按查询范围限定的格式同用时为 8);升级阶段的 5 credits 仅在普通抓取被拦下且该阶段真正执行时才收取。
NameTypeRequiredDefaultDescription
url
stringRequired-
要抓取的 URL(必须包含协议:http:// 或 https://)
Example: https://example.com
formats
arrayOptional["markdown"]
要返回的输出格式。可选一个或多个:`markdown`、`html`、`rawHtml`、`text`、`links`、`metadata`,另加两种按查询范围限定的对象格式:`{ "type": "highlights", "query": "…", "max_highlights": 10, "mode": "extractive" }` 返回与 `query` 最匹配的句子和代码块(`max_highlights` 取 1–50,默认 10)——在托管 REST API 上 `kind` 为 `sentence` 或 `code_block`;`table_row` 单元由 MCP 服务器返回,其 markdown 会把表格保留为竖线分隔的行,而 REST API 会把表格压平为文本;`{ "type": "question", "question": "…", "mode": "extractive" }` 返回由最匹配段落拼成的 `answer`。两者都返回页面逐字原文;每个单元带有指向同一次调用 `markdown` 格式的 `offset` 和 `length`(`onlyMainContent` 设置相同),因此若要带定位符引用,请同时请求 `markdown`。`mode: "model"` 在此会以 400 被拒绝——它需要 LLM,仅在 MCP 服务器上可用。`screenshot` 与 `json-schema` 能通过校验,但随后会以 400 被拒绝——它们需要浏览器或 LLM,而托管 REST API 并不提供。
Example: ["markdown", { "type": "highlights", "query": "Starter plan price" }, { "type": "question", "question": "How much does the Starter plan cost?" }]
onlyMainContent
booleanOptionaltrue
剥离导航、页眉和页脚,只返回正文主体内容。
Example: true
escalate
booleanOptionalfalse
选择加入:当普通抓取返回的是反爬墙而不是页面时,自动通过 stealth 浏览器重试一次——Cloudflare、Amazon、DataDome、PerimeterX、Akamai 或 Vercel 的挑战页、空壳页面,或标题为错误提示的短占位页。普通抓取始终先执行;只有在被拦下时,同一次调用才会用 stealth 浏览器渲染该页面,并从渲染结果中派生出所有请求的格式,因此被拦的页面只需一次调用而不是两次。升级复用与 [stealth_mode](/docs/api-reference/tools/stealth-mode) 相同的 stealth 路径和同一道 robots.txt 校验,不会新增任何针对反爬防护的处理手段。若 stealth 渲染同样被拒,结果仍作为被拦截的页面返回,带 `escalated: true` 且不计费:升级省下的是第二次往返,并不保证拿到页面。当普通抓取失败只是因为页面需要 JavaScript 才能渲染时,它最为可靠。响应随后会带上 `escalated`,当其为 `true` 时还会带上 `stealth`。仅在升级阶段真正执行时加收 5 credits。仅在 MCP 服务器上,被某主机拦下的记录会保留 24 小时,因此下一次对该主机的 `escalate: true` 调用会跳过注定失败的普通抓取,并在警告中说明。
Example: true
escalate_engine
stringOptionalplaywright
升级阶段使用的浏览器引擎:"playwright"(默认)或 "camoufox"(基于 Firefox,抗检测能力更强;仅在后端已安装时可用)。除非 `escalate` 为 `true` 且普通抓取被拦下,否则忽略此参数。
Example: camoufox
respect_robots
booleanOptionaltrue
遵守目标站点的 robots.txt。保持 `true` 时,robots.txt 对 `CrawlForge` 禁止的路径会在抓取之前以 403 拒绝,且不扣除 credits。仅在你与目标站点另有约定时才设为 `false`——此时响应会带上一条 `warnings`,并且该覆盖会记录到你的 API key 上。
Example: true
max_inline_chars
numberOptional40000
内联返回的最大结果大小,以其 JSON 的字符数计(1,000-10,000,000)。超过后,响应会携带 `preview`(markdown的前 `max_inline_chars` 个字符)、`result_handle`、`total_chars`、`truncated: true` 和 `expires_at`,其余部分由 [read_result](/docs/api-reference/tools/read-result) 读取,每次调用 1 credit。已存储的结果保留 1 小时。
Example: 40000
redact_pii
boolean | objectOptionalfalse
在结果被存储或返回之前,从本次调用返回的文本中移除个人数据。 `true` 是 `{ mode: "fast" }` 的简写:四个正则类别全开,以标签替换。只要请求了脱敏,响应就会在 `data` 内带上 `redaction: { entities, count, mode }`,即使没有任何匹配(`count: 0`)也会带上,因此“什么都没找到”永远不会被误认为“参数被忽略了”;没有命中的类别会被省略,而不是报成 `0`。脱敏在结果存储**之前**执行,因此超出阈值、之后再用 [read_result](/docs/api-reference/tools/read-result) 读回的结果本身就已脱敏。两条刻意的边界:地址类字段(`url`、`link`、`href`、`canonical_url`)从不脱敏;由文本派生的计数(`content_length`、`word_count`、`character_count`)描述的是抽取时的文本,即脱敏之前的文本。
Example: true

请求示例

cURL

terminalBash
curl -X POST https://crawlforge.dev/api/v1/tools/scrape \
  -H "X-API-Key: cf_test_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com",
    "formats": [
      "markdown", "links", "metadata",
      { "type": "highlights", "query": "professional plan price per month" }
    ],
    "onlyMainContent": true,
    "escalate": true
  }'

TypeScript

scrape.tsTypescript
// npm install crawlforge-sdk
import { CrawlForge, ToolError } from 'crawlforge-sdk';

const client = new CrawlForge({ apiKey: process.env.CRAWLFORGE_API_KEY });

try {
  const result = await client.scrape({
    url: 'https://example.com',
    formats: [
      'markdown', 'links', 'metadata',
      // 1 extra credit: the matching sentences, table rows and code blocks, verbatim, with offsets
      { type: 'highlights', query: 'professional plan price per month' },
    ],
    onlyMainContent: true,
    // Only when the plain fetch meets a bot wall: one stealth render in this same call (5 extra credits)
    escalate: true,
  });

  // result.data is untyped in crawlforge-sdk 0.1 — its shape is the Response Example below.
  const { formats } = result.data as {
    formats: { markdown: string; links: string[]; metadata: { title: string }; highlights: { text: string }[] };
  };
  console.log('Markdown:', formats.markdown);
  console.log('Links found:', formats.links.length);
  console.log('Title:', formats.metadata.title);
  // Each highlight is verbatim page text; offset/length index formats.markdown.
  console.log('Best match:', formats.highlights[0]?.text);

  // A success with warnings is a PARTIAL result — some formats came back, others didn't.
  if (result.warnings.length > 0) {
    console.warn('Partial result:', result.warnings);
  }

  console.log('Credits used:', result.creditsUsed);
  console.log('Credits remaining:', result.creditsRemaining);
} catch (err) {
  // A bot wall the stealth render could not pass either: not charged, blocked.vendor names it.
  if (err instanceof ToolError && err.blocked) {
    console.error('Blocked by', err.blocked.vendor, '— escalated:', err.escalated);
  } else {
    throw err;
  }
}

Python

scrape.pyPython
# pip install crawlforge
from crawlforge import CrawlForge, ToolError

client = CrawlForge()  # reads CRAWLFORGE_API_KEY

try:
    result = client.scrape(
        url='https://example.com',
        formats=[
            'markdown', 'links', 'metadata',
            # 1 extra credit: the matching sentences, table rows and code blocks, verbatim, with offsets
            {'type': 'highlights', 'query': 'professional plan price per month'},
        ],
        onlyMainContent=True,
        # Only when the plain fetch meets a bot wall: one stealth render in this same call (5 extra credits)
        escalate=True,
    )
except ToolError as e:
    # A bot wall the stealth render could not pass either: not charged, blocked names the vendor.
    print(f"Blocked: {e.blocked} (escalated: {e.escalated})")
    raise

# result.data is a plain dict — its shape is the Response Example below.
formats = result.data['formats']
print(f"Markdown: {formats['markdown']}")
print(f"Links found: {len(formats['links'])}")
print(f"Title: {formats['metadata']['title']}")
# Each highlight is verbatim page text; offset/length index formats['markdown'].
print(f"Best match: {formats['highlights'][0]['text']}")

# A success with warnings is a PARTIAL result — some formats came back, others didn't.
if result.warnings:
    print(f"Partial result: {result.warnings}")

print(f"Credits used: {result.credits_used}")
print(f"Credits remaining: {result.credits_remaining}")

响应示例

200 OK4218ms
{
"success": true,
"data": {
"url": "https://example.com",
"formats": {
"markdown": "# Example\n\nMain content scraped from https://example.com. The Starter plan costs $12 per month and includes three seats. Annual billing lowers the Starter plan to $10 per month.",
"highlights": [
{
"text": "The Starter plan costs $12 per month and includes three seats.",
"kind": "sentence",
"offset": 58,
"length": 62,
"score": 6.612
},
{
"text": "Annual billing lowers the Starter plan to $10 per month.",
"kind": "sentence",
"offset": 121,
"length": 56,
"score": 5.809
}
],
"answer": {
"text": "The Starter plan costs $12 per month and includes three seats.",
"grounded": true,
"evidence": [
{
"text": "The Starter plan costs $12 per month and includes three seats.",
"kind": "sentence",
"offset": 58,
"length": 62,
"score": 6.612
}
]
}
},
"escalated": true,
"stealth": {
"engine": "playwright",
"vendor_detected": "cloudflare"
},
"scraped_at": "2026-08-26T14:30:00.000Z"
},
"credits_used": 8,
"credits_remaining": 992,
"processing_time": 4218
}
Field Descriptions
data.url实际抓取的 URL。
data.formats每个所请求的格式对应一个键——提取到的内容位于此对象内,而不在 data 的顶层。
data.formats.markdown转换为 markdown 的正文内容(请求 `markdown` 时出现)。
data.formats.highlights与 `query` 匹配、排名最高的句子和代码块,逐字原文(请求 `highlights` 格式时出现)。每个单元带有 `text`、`kind`(托管 REST API 上为 `sentence` 或 `code_block`;`table_row` 单元由 MCP 服务器返回,其 markdown 会把表格保留为竖线分隔的行,而 REST API 会把表格压平为文本)、`offset`、`length` 和 `score`——后者是未归一化的 BM25 相关度值,只用于排序,不是 0–1 的置信度。
data.formats.highlights.offset指向同一次调用 `markdown` 格式的字符索引(`onlyMainContent` 设置相同):`markdown.slice(offset, offset + length) === text`。
data.formats.answer对 `question` 的回答(请求 `question` 格式时出现):`text` 是最匹配证据的拼接,`evidence` 列出最多 5 个支撑单元。
data.formats.answer.grounded在 REST API 上恒为 `true`——文本是页面逐字原文,不做任何合成。
data.escalated升级阶段是否执行过(仅当请求传入 `escalate: true` 时出现)。`false` 表示普通抓取拿到了页面,只按基础价计费。
data.stealth页面是如何渲染的(仅当 `escalated` 为 `true` 时出现):`engine` 是实际运行的浏览器,`vendor_detected` 指出普通抓取撞上的反爬防护厂商——`cloudflare`、`amazon`、`datadome`、`perimeterx`、`akamai` 或 `vercel`——当拦截表现为空壳页面或错误占位页而非具名挑战页时为 `null`。
data.scraped_at本次抓取的 ISO 8601 时间戳。
credits_used本次请求扣除的 credits——每次 scrape 固定 2 个,与请求了多少种格式无关;包含 `highlights` 或 `question` 格式时再加 1 个;升级阶段执行时再加 5 个。此处为 2 + 1 + 5。
credits_remaining您剩余的 credits 余额。

错误处理

输入无效(400 Bad Request)

URL 格式无效,formats 中包含受支持列表之外的值,或某个 highlights / question 格式请求了 mode: "model"——它需要 LLM,仅在 MCP 服务器上可用。传入该字段时至少需要一种格式。

URL 被拦截(403 Forbidden)

目标解析到私有、内网或链路本地地址,被 SSRF 防护拒绝。只能抓取公网可访问的 URL。

credits 不足(402 Payment Required)

你的账户 credits 不足。购买更多 credits 或升级你的计划。

超出速率限制(429 Too Many Requests)

你已超出所在计划的速率限制。稍等片刻,或升级你的计划以获得更高上限。

升级后端未配置(503 TOOL_NOT_AVAILABLE)

escalate: true 的 stealth 阶段运行在 CrawlForge 执行后端上。该后端未配置时,升级阶段返回 503,且不为此扣除任何 credits。

被 robots.txt 拦截(403 Forbidden)

目标站点的 robots.txt 对 CrawlForge 禁止了该路径。若你与目标站点另有约定,可设置 respect_robots: false 予以覆盖——该覆盖会记录到你的 API key 上。该覆盖不适用于列入 CrawlForge 永久排除名单的主机——无论 respect_robots 取何值,这类主机一律被拒绝。

专业提示: 同时请求 markdown、links 与 metadata 与只请求一种格式一样,都是 2 credits——所有格式都源自同一次页面加载。请在一次调用中把可能需要的都要齐;highlights 或 question 格式只加收 1 credit,按次而非按格式计。

credits 成本

2 credits
每次请求 2 credits
每次成功的 scrape 请求扣除 2 credits,无论请求多少种格式,因为所有格式都来自同一次抓取。highlights 或 question 格式加收 1 credit,每次请求只收一次,不论包含一种还是两种。使用 escalate: true 的调用预估最多 7 credits(与按查询范围限定的格式同用时为 8),仅当普通抓取返回反爬墙且 stealth 阶段执行时才收取 5 credits 的升级附加费——绝不会超过预估值。

Free 计划: 1,000 个一次性 credits = 500 次请求

Hobby 计划: 每月 5,000 credits = 2,500 次请求(19 美元/月)

Professional 计划: 每月 50,000 credits = 25,000 次请求(99 美元/月)

Business 计划: 每月 250,000 credits = 125,000 次请求(399 美元/月)

相关工具

fetch_url
需要未经处理的原始响应体时使用的原始 HTTP 抓取(1 credit)
extract_content
针对单个页面、基于可读性的正文提取(2 credits)
batch_scrape
以异步任务方式对大量 URL 执行相同的提取(5 credits)
scrape_with_actions
在抓取重 JS 页面前先点击、滚动或填写表单(5 credits)
准备好试用 scrape 了吗?免费注册,获得 1,000 credits 开始构建。

页脚

CrawlForge MCP

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

产品

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

资源

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

开发者

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

公司

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

保持更新

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

基于 Next.js 和 MCP 协议构建

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