scrape_ with_ actions
执行包括点击、滚动、输入和表单自动填充在内的浏览器操作链,并支持截图捕获。非常适合登录流程、无限滚动、模态对话框以及复杂的重 JavaScript 网站。
使用场景
登录流程
自动化登录表单,访问登录墙后的已认证内容
无限滚动
从社交媒体动态流和产品列表等无限滚动页面抓取内容
模态对话框
与弹窗、模态框和动态浮层进行交互
重 JavaScript 网站
处理 SPA 以及通过 AJAX 动态加载内容的网站
多步骤表单
在多步骤向导和复杂表单提交中进行导航
可视化测试
在每一步捕获截图,用于调试和视觉回归测试
Endpoint
/api/v1/tools/scrape_with_actionsParameters
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
url | string | Required | - | 在运行操作链之前要加载的 URL Example: https://app.example.com/dashboard |
actions | array | Required | - | 在抓取之前要运行的 1-20 个浏览器操作的有序列表。每个元素都是一个对象,其 `type` 为 `wait`、`click`、`type`、`press`、`scroll`、`screenshot`、`executeJavaScript`、`select`、`hover`、`navigate` 或 `snapshot`,外加与类型相关的字段:`selector`(CSS 目标,或来自先前 `snapshot` 的 `@e1` 引用)、`text`(用于 `type`)、`key`(用于 `press`)、`script`(用于 `executeJavaScript`)、`duration`/`condition`(用于 `wait`)、`button`/`clickCount`/`delay`(用于 `click`)、`direction`/`distance`/`toElement`(用于 `scroll`)、`fullPage`/`quality`/`format`(用于 `screenshot`)、`value` 或 `values`(用于 `select`)、`url`/`waitUntil`(用于 `navigate`)以及 `interactiveOnly`/`maxNodes`(用于 `snapshot`)。`select` 接受单个 `value` 或 `values` 数组,普通字符串会按选项的 value 或可见文本进行匹配;`hover` 需要 `selector`,并可选 `force` 和 `position`。`snapshot` 会为页面上的每个可交互元素(包括开放 shadow root 和 iframe 内的元素)附上稳定的引用(按文档顺序为 `@e1`、`@e2`、…),同一条链中后续的任何操作都可以用这些引用代替 CSS 选择器作为目标;导航会使引用失效,因此页面变化后需重新执行 `snapshot`。任何操作均可选:`timeout`(每个操作,默认 10000ms,区别于按整条链计算预算的 `browserOptions.timeout`)、`description`、`continueOnError`(默认 false)、`retries`(0-5,默认 1)和 `captureAfter`(默认 false)。 Example: [{"type": "click", "selector": "#login"}, {"type": "type", "selector": "#email", "text": "user@example.com"}, {"type": "wait", "duration": 1000}, {"type": "screenshot"}] |
formats | array | Optional | ["json"] | 要返回的输出格式:`markdown`、`html`、`json` 或 `text`。需要图像时,请在希望截图的位置添加一个 `{"type": "screenshot"}` 操作。 Example: ["markdown"] |
captureIntermediateStates | boolean | Optional | false | 在每个操作之后捕获页面状态:`intermediateStates[]` 中每个操作对应一项(`capturePoint` 是该操作从 1 开始计的位置),包含当时的 `url`、`title` 和所请求的格式 Example: true |
formAutoFill | object | Optional | - | 一步填写并提交表单。结构:`{ fields: [{ selector, value, type: text|select|checkbox|radio|file, waitAfter }], submitSelector, waitAfterSubmit }`——`waitAfterSubmit` 默认为 2000ms。每个字段的 `type` 决定填写方式:`text`(默认)输入该值,`select` 按值或标签选择选项,`checkbox` 和 `radio` 勾选该控件——若选择器匹配整组控件(例如 `input[name=size]`),则勾选 `value` 属性等于 `value` 的那一个;值为 `"false"` 的 checkbox 会被取消勾选。不支持 `file`,该动作会失败。 Example: {"fields": [{"selector": "#email", "value": "user@example.com", "type": "text"}], "submitSelector": "#login"} |
browserOptions | object | Optional | - | 浏览器配置:`headless`(默认 true)、`userAgent`、`viewportWidth`(默认 1280,范围 800-1920)、`viewportHeight`(默认 720,范围 600-1080)、`timeout`(默认 30000ms,范围 10000-120000)以及 `stealth`(默认 false)。请将 `timeout` 保持在约 25 秒的 REST 窗口内。将 `stealth` 设为 true,可用隐身 Chromium 引擎的 `medium` 配置运行整条操作链,而不使用标准浏览器池——该布尔值是唯一的开关,级别、指纹随机化和引擎选择都无法在此设置。它启动更慢,并且只是渲染 JavaScript,并不解决挑战。`consent`(默认 `"off"`)处理 cookie 和同意横幅:`"reject"` 会在初始导航之后以及每个 `navigate` 操作之后各对横幅执行一次 DuckDuckGo autoconsent 的拒绝(opt-out),上限 2 秒;`"accept"` 则改为同意。当它不是 `"off"` 时,结果会带有初始导航的 `consent: { cmp, action, ms }`,每个 `navigate` 操作的结果也会带有各自的 `result.consent`。`cmp` 是匹配到的同意管理平台,没有匹配时为 `null`;`action` 为 `optOut`、`optIn`、`hide`(外观规则隐藏了横幅)、`timeout`(检测到横幅,但未在 2 秒上限内完成应答)、`error` 或 `none`(没有匹配);`ms` 是耗时。操作链绝不会因为没有匹配到平台而失败。默认值为 off,这样自行点击横幅的操作链仍能照常工作。`proxyRotation` 让隐身浏览器经由你自备的代理访问:`{ enabled, proxies, rotationInterval }`,其中 `enabled` 默认 false,`rotationInterval`(默认 300000)是在一个代理上停留的最短毫秒数,之后列表才切换到下一个。它要求 `stealth: true`,否则会被拒绝。代理仅在 Chromium 引擎上按上下文生效;Camoufox 会拒绝单次调用的 `proxyRotation`,因为它在启动浏览器时就应用代理,并在多次调用之间共享该浏览器。`proxies` 中的每一项都是代理 URL——`"http://user:pass@host:port"`(密码中含 `@`、`:` 或 `/` 时请做百分号编码),或用于无需认证的 HTTP 代理的裸 `"host:port"`;支持 `http`、`https`、`socks4` 和 `socks5`。位于回环、私有、链路本地或云元数据地址上的代理会被拒绝,凭据也绝不会回显——结果中的 `metadata.browserOptions` 会将其脱敏显示。CrawlForge 不提供代理:托管的隐身浏览器从数据中心地址发出请求,而 IP 信誉封锁是任何指纹都解决不了的,能通过它的是住宅代理。 Example: {"viewportWidth": 1440, "viewportHeight": 900, "timeout": 20000} |
extractionOptions | object | Optional | - | 内容提取选项:`selectors`(要提取数据的 CSS 键→值映射)、`includeMetadata`(默认 true)、`includeLinks`(默认 true)和 `includeImages`(默认 true)。 Example: {"selectors": {"title": "h1", "price": ".price"}} |
continueOnActionError | boolean | Optional | false | 当某个操作失败时继续执行其余操作,而不是中止整个操作链 Example: false |
maxRetries | number | Optional | 0 | 失败时整条操作链的重试次数(0-3)。每次重试都会重新导航到起始 URL 并重放所有操作,因此每次重试的开销与首次运行相同;每次尝试都会记录在 `attempts[]` 中 Example: 0 |
screenshotOnError | boolean | Optional | true | 发生错误时捕获截图 Example: true |
respect_robots | boolean | Optional | true | 遵守目标站点的 robots.txt。省略该参数时按合规默认值(`true`)执行:robots.txt 对 `CrawlForge` 禁止的 URL 会在打开浏览器之前被拒绝,此端点不会为此扣费,每个 `navigate` 操作也会同样检查。页面最终停在哪里也会再次检查——无论是经过重定向、点击还是表单提交——一旦落到被禁止的路径,调用即失败,且不会返回该页面的任何内容。无论此参数如何设置,都会遵守站点的 `Crawl-delay`:`navigate`,以及可能让页面跳转的 `click`、`press`、`select` 或 `check`,都会在距上次请求该页面所在主机满这段时间后才执行。仅在您与目标站点另有约定时才设为 `false`——该覆盖会记录到您的 API key 上。 Example: true |
max_inline_chars | number | Optional | 40000 | 内联返回的最大结果大小,以其 JSON 的字符数计(1,000-10,000,000)。超过后,响应会携带 `preview`(结果主文本字段的前 `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 | object | Optional | false | 在结果被存储或返回之前,从本次调用返回的文本中移除个人数据。 `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 |
可用的操作类型
{"type": "wait", "duration": 2000}{"type": "click", "selector": "#button"}{"type": "type", "selector": "#search", "text": "query"}{"type": "press", "key": "Enter"}{"type": "scroll", "toElement": "#content"}{"type": "screenshot"}ALLOW_JAVASCRIPT_EXECUTION=true,否则该操作处于禁用状态;托管 API 会拒绝该操作。{"type": "executeJavaScript", "script": "window.scrollTo(0, 0)"}<select> 中选择选项:selector 指定下拉框,然后使用 value(单个选项)或 values(多个选项)。普通字符串会按选项的 value 或可见文本进行匹配。selector 指定的元素上——适用于仅在悬停时出现的菜单和提示。force 与 position 的行为与 click 相同。url,因此先前操作留下的 cookie、localStorage 和登录状态都会保留。可选的 waitUntil 取值为 load、domcontentloaded(默认)、networkidle 或 commit。新 URL 会经过与初始 URL 相同的 robots.txt 和 SSRF 检查,因此无法借此绕过限制。每次导航都会检查是否遇到机器人墙:该操作的 result 会带有 httpStatus,识别出墙时还会带有 blocked: { vendor, evidence }。操作本身仍然成功——墙只会被报告,不会让操作失败。[document] "Example Domain",然后是 @e1 [textbox] "Search..." 和 @e2 [button] "Search"。iframe 或 shadow root 内的元素和其他元素一样获得普通的 @eN 引用。将 interactiveOnly(默认 true)设为 false 会一并列出标题和地标元素,但它们永远不会获得引用;maxNodes(默认 200,最大 1000)限制树中列出的节点数量(在默认设置下,每个节点各对应一个引用),当该上限中断遍历时,结果会报告 truncated: true。此操作在 actionResults 中的条目会以 result.tree 返回该树,同时包含 snapshotId、url、title、refCount、nodeCount、truncated、interactiveOnly 和 source——树来自浏览器原生无障碍快照时为 aria,由后备遍历生成时为 walk。{"type": "snapshot", "interactiveOnly": true, "maxNodes": 200}通过引用定位元素
snapshot 会为它找到的每个可交互元素附上稳定的引用,因此整条链的写法是:先 snapshot,再对引用执行操作,页面变化后再次 snapshot:[{"type": "snapshot"}, {"type": "type", "selector": "@e1", "text": "crawlforge"}, {"type": "click", "selector": "@e2"}]。引用仅对拍摄它的那个文档有效:任何导航——navigate 操作,或加载新页面的点击——都会使全部引用失效,使用失效的引用会返回错误,提示你重新执行 snapshot。开放 shadow root 和 iframe 内的元素获得普通的 @eN 引用,定位方式完全相同。
每次导航都检查机器人墙
操作链中的每一次导航——初始页面加载以及每个 navigate 操作——都会检查是否遇到机器人墙、HTTP 错误页或挑战中间页,包括 HTTP 202 中间页,例如 AWS WAF 或 Amazon 的挑战。结果在 navigations 中按顺序列出这些导航,索引 0 为初始加载,每项形如 { url, finalUrl, httpStatus, blocked }:未知时 httpStatus 为 null,只有识别出墙时才会出现 blocked: { vendor, evidence }(cloudflare、akamai、datadome、perimeterx、amazon、vercel 等)。点击或表单提交如果加载了另一个页面,同样算作一次导航:它有自己的条目,其中 trigger 指明操作类型(click、press 等),顶层的 finalUrl 是操作链最终停留的位置,而 url 仍是你请求的那个地址。中途遇到墙不会中断操作链,后续操作仍可继续导航。调用是否成功取决于操作链最终停留的文档:停在墙上的操作链绝不会报告为成功。在此 API 中它会以 502 BLOCKED 失败,并附带 blocked 和 navigations,且不扣除任何费用;没有可识别墙的 HTTP 错误页则以 502 TOOL_ERROR 失败。该工具只报告墙,不会破解它——如果封锁针对的是网络地址,请在 browserOptions.proxyRotation 中传入你自己的代理(同时设置 stealth: true)。
请求示例
# 1. Snapshot the page to learn its interactive elements and their refs.
curl -X POST https://crawlforge.dev/api/v1/tools/scrape_with_actions \
-H "X-API-Key: cf_test_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://app.example.com/login",
"actions": [{"type": "snapshot"}],
"formats": ["json"]
}'
# actionResults[0].result.tree comes back as:
# [document] "Sign in"
# @e1 [textbox] "Email"
# @e2 [textbox] "Password"
# @e3 [button] "Sign in"
# 2. Target those refs instead of guessing selectors. The chain snapshots
# again first, which stamps the refs onto this fresh load.
curl -X POST https://crawlforge.dev/api/v1/tools/scrape_with_actions \
-H "X-API-Key: cf_test_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://app.example.com/login",
"actions": [
{"type": "snapshot"},
{"type": "type", "selector": "@e1", "text": "user@example.com"},
{"type": "type", "selector": "@e2", "text": "secret123"},
{"type": "click", "selector": "@e3"},
{"type": "wait", "duration": 1000},
{"type": "screenshot"}
],
"formats": ["markdown"]
}'响应示例
{ "success": true, "data": { "success": true, "url": "https://app.example.com/login", "finalUrl": "https://app.example.com/dashboard", "httpStatus": 200, "engine": "chromium", "navigations": [ { "url": "https://app.example.com/login", "finalUrl": "https://app.example.com/login", "httpStatus": 200 }, { "url": "https://app.example.com/dashboard", "finalUrl": "https://app.example.com/dashboard", "httpStatus": 200, "trigger": "click" } ], "actionResults": [ { "id": "action_1759480001102_k2m8x1q0z", "type": "click", "success": true, "executionTime": 640 }, { "id": "action_1759480001790_p7c4n9d2a", "type": "wait", "success": true, "executionTime": 1001 }, { "id": "action_1759480002805_h5t1v8r3e", "type": "screenshot", "success": true, "executionTime": 212, "result": { "format": "png", "fullPage": false, "resourceUri": "crawlforge://screenshot/action_1759480002805_h5t1v8r3e" } } ], "totalActions": 3, "successfulActions": 3, "failedActions": 0, "actionsExecuted": 3, "content": { "markdown": "# Dashboard\n\nWelcome back — you are now signed in..." }, "screenshots": [ { "actionId": "action_1759480002805_h5t1v8r3e", "format": "png", "fullPage": false, "timestamp": 1759480002805, "resourceUri": "crawlforge://screenshot/action_1759480002805_h5t1v8r3e" } ] }, "credits_used": 5, "credits_remaining": 995, "processing_time": 9000}data.url你请求的 URL。无论操作链走了多远,它都保持不变data.finalUrl操作链最终停留的位置,包含任何重定向、点击或表单提交之后的结果data.httpStatus操作链加载的最后一个主框架文档的状态码data.navigations按顺序列出的每一次导航,索引 0 为初始加载。由点击或表单提交引起的条目带有 `trigger`,即让页面跳转的操作类型data.actionResults每个操作一项,包含其 `type`、`success`、耗时以及该操作自身的 `result`data.actionsExecuted已执行的操作数量;`successfulActions` 和 `failedActions` 是其细分data.content.markdown所有操作完成后,以每种请求格式返回的页面内容data.screenshots始终存在:每个 `screenshot` 操作一项,出错时另有一张,没有截图时为空数组。每一项都是 `crawlforge://screenshot/{actionId}` 资源 URI,而不是内联的 base64,并且此 REST 端点会原样传递该 URI 而不解析它——因此目前只能通过 CrawlForge MCP 服务器读取图像数据credits_used本次请求扣除的 credits(每次抓取 5 个)processing_time总耗时(毫秒),包含所有操作和等待错误处理
浏览器运行时未配置(503 TOOL_NOT_AVAILABLE)
该工具需要浏览器自动化运行时。当托管执行后端未配置时,调用会立即返回 503,且不扣除 credits。
执行后端超时(504 MCP_UPSTREAM_TIMEOUT)
导航加上动作链超出了执行后端的时间预算。请缩短等待、减少动作数量,或稍后重试。失败不计费。
被 robots.txt 阻止(502 TOOL_ERROR)
目标站点的 robots.txt 对 CrawlForge 禁止了该 URL,因此没有启动任何浏览器,也没有产生任何费用。每个 navigate 操作都会同样检查,而不仅是初始 URL。页面最终停在哪里也会同样检查:如果重定向、点击或表单提交把页面带到被禁止的路径,错误信息会同时给出两个 URL(“The page moved from … to …”),操作链就此停止,且不产生任何费用。登录页和搜索页常常被禁止,因此经过这类页面的流程需要使用该覆盖。若您与目标站点另有约定,可设置 respect_robots: false 予以覆盖——该覆盖会记录到您的 API key 上。
停在机器人墙上(502 BLOCKED)
操作链最终停留的文档是机器人墙或挑战中间页,因此调用会失败,而不是把墙当作页面返回,且不扣除任何费用。响应体包含指明该墙的 blocked: { vendor, evidence }、操作链的 navigations,以及已知时的最终 httpStatus,便于你看出是哪一次导航遇到了它。工具无法归属到具体厂商的 HTTP 错误页或占位页则以 502 TOOL_ERROR 失败,同样不扣除费用。较早导航中遇到的墙不会导致调用失败,而是在 navigations 中报告。该工具只报告墙,不会破解它;如果封锁针对的是网络地址,请通过 browserOptions.proxyRotation 让操作链经由你自己的代理。
无效操作(400 Bad Request)
一个或多个操作的参数无效。请检查操作类型和必填字段。
Credits 不足(402 Payment Required)
您的账户 credits 不足(需要 5 个)。购买更多 credits 或 升级您的套餐。
超出速率限制(429 Too Many Requests)
您已超出套餐的速率限制。请稍候片刻,或 升级您的套餐 以获得更高限额。
在交互之间使用 wait 操作,以确保 JavaScript 有时间执行。调试时,可在每一步之后添加一个 screenshot 操作,查看浏览器当时所看到的内容。
Credit 费用
Free 套餐: 1,000 个一次性试用 credits = 200 条操作链
Hobby 套餐: 5,000 credits/月 = 1,000 条操作链($19/mo)
Professional 套餐: 100,000 credits/月 = 20,000 条操作链($99/mo)
Business 套餐: 500,000 credits/月 = 100,000 条操作链($399/mo)
相关工具
准备好试用 scrape_with_actions 了吗?免费注册,获取 1,000 credits,开始构建。