使用场景
生成站点地图
通过提取所有内部链接构建全面的站点地图
为爬取发现链接
在网页爬取工作流中找出所有要访问的 URL
内部链接分析
分析内部链接结构以进行 SEO 优化
失效链接检测
查找并校验页面上的所有链接
Endpoint
/api/v1/tools/extract_linksParameters
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
url | string | Optional | - | 要抓取并从中提取链接的页面。`url` 与 `html` 二者必填其一。 Example: https://example.com |
html | string | Optional | - | 直接解析的原始 HTML,替代抓取。请配合 `base_url` 使用,以便相对 href 能够解析。 Example: <a href='/about'>About</a> |
base_url | string | Optional | - | 解析相对链接所用的基地址,优先于页面自身的 `<base href>`。抓取时默认使用页面的 `<base href>`,没有则使用 `url`;传入 `html` 时请一并提供。 Example: https://example.com |
include_internal | boolean | Optional | true | 包含指向同一主机的链接。 Example: true |
include_external | boolean | Optional | true | 包含指向其他主机的链接。设为 false 可只保留内部链接。 Example: true |
filter_external | boolean | Optional | false | MCP 工具用于只返回出站链接的参数名:`true` 等同于 `include_internal: false`,并优先于它。这是一个别名,便于同一请求体在两个接口上通用。它不会移除类型为 `other`、`anchor` 或 `relative` 的链接。 Example: true |
filter_domains | array | Optional | - | 仅保留主机与这些域名之一匹配的链接。 Example: ["docs.example.com"] |
include_anchors | boolean | Optional | false | 包含形如 `#section` 的纯片段链接。 Example: false |
deduplicate | boolean | Optional | true | 将重复的 URL 合并为一条,比较时忽略片段和末尾斜杠(`/a`、`/a/` 和 `/a#x` 视为同一链接);保留首次出现的那条。 Example: true |
include_metadata | boolean | Optional | true | 返回每个链接的 `title` 属性以及 `domains` 计数表。无论是否开启,每条链接记录都带有 `href`、`text`、`type`、`domain`、`rel` 和 `original_href`,与 MCP 工具返回的结构相同。 Example: true |
respect_robots | boolean | Optional | true | 遵守目标站点的 robots.txt。保持 `true` 时,robots.txt 对 `CrawlForge` 禁止的路径会在抓取之前以 403 拒绝,且不扣除 credits。仅在你与目标站点另有约定时才设为 `false`——此时响应会带上一条 `warnings`,并且该覆盖会记录到你的 API key 上。 Example: true |
escalate | boolean | Optional | false | 选择加入:当对 `url` 的普通抓取遇到的是拦截墙而不是页面时——Cloudflare、Amazon、DataDome、PerimeterX、Akamai 或 Vercel 的挑战页、单纯的 403、429 或 444,或以 2xx 返回的空壳页面或错误占位页——自动通过 stealth 浏览器重试一次。普通抓取始终先执行;404、5xx、PDF 等二进制内容,或 `Retry-After` 等待期仍未结束的主机,永远不会触发升级;`html` 输入不会被抓取。链接从渲染出的 HTML 中读取,因此响应结构不变,另外只要设置了此参数就会带上 `escalated`,渲染实际执行时还会带上 `stealth: { engine, vendor_detected }`。升级复用与 [stealth_mode](/docs/api-reference/tools/stealth-mode) 相同的 stealth 路径和同一道 robots.txt 校验,不会新增任何针对反爬防护的处理手段;若渲染同样被拒,结果仍作为被拦截的页面返回并带有 `escalated: true`,且不计费。仅在渲染真正执行时加收 5 credits。 Example: true |
escalate_engine | string | Optional | playwright | 升级阶段使用的浏览器引擎:"playwright"(默认)或 "camoufox"(基于 Firefox,抗检测能力更强;仅在后端已安装时可用)。除非 `escalate` 为 `true` 且普通抓取被拦下,否则忽略此参数。 Example: camoufox |
max_inline_chars | number | Optional | 40000 | 内联返回的最大结果大小,以其 JSON 的字符数计(1,000-10,000,000)。超过后,响应会携带 `preview`(格式化 JSON 的前 `max_inline_chars` 个字符)、`result_handle`、`total_chars`、`truncated: true` 和 `expires_at`,其余部分由 [read_result](/docs/api-reference/tools/read-result) 读取,每次调用 1 credit。已存储的结果保留 1 小时。 Example: 40000 |
抓取 URL
- 页面只抓取一次,超时时间为 15 秒。若返回 429 或 503 且
Retry-After不超过 10 秒,会等待该时长后再抓取一次;Retry-After更长或缺失时不重试。 - 可读取 HTML、XHTML、XML 及所有
text/*类型,未带Content-Type的响应按 HTML 读取。PDF、图片或其他二进制内容返回415 UNSUPPORTED_CONTENT_TYPE,附带next_step: "process_document",且不计费:请改用 process_document 读取。 - JSON 响应体(
application/json或*+json)不返回任何链接,并附带警告the target returned application/json; it has no HTML links。 - 在客户端渲染的页面——可见文本少于 200 个字符,且含有空的
<div id="root">、"app"或"__next",或文本说明页面需要 JavaScript("Enable JavaScript…")——在未执行 stealth 渲染时仍返回成功,data中带有rendered: false,warnings中带有page renders client-side; use scrape,以免把空壳页面误认为内容很短的页面。html输入同样会做此检查。 - 每次调用 1 credit。设置
escalate: true时,预估上限为 6 credits;只有当普通抓取被拦下且升级阶段真正执行时,才会收取升级阶段的 5 credits。任何失败都不计费。
请求示例
cURL - 提取所有链接
curl -X POST https://crawlforge.dev/api/v1/tools/extract_links \
-H "X-API-Key: cf_test_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com",
"include_internal": true,
"include_external": false,
"deduplicate": true
}'TypeScript - 仅内部链接
// npm install crawlforge-sdk
import { CrawlForge } from 'crawlforge-sdk';
const client = new CrawlForge({ apiKey: process.env.CRAWLFORGE_API_KEY });
const result = await client.extractLinks({
url: 'https://example.com',
// Internal-only: keep include_internal, switch include_external off.
include_internal: true,
include_external: false,
deduplicate: true,
});
// result.data is untyped in crawlforge-sdk 0.1 — its shape is the Response Example below.
const { base_url, extracted_from, links } = result.data as {
base_url: string; extracted_from: string; links: unknown[];
};
console.log('Base URL:', base_url);
console.log('Extracted from:', extracted_from);
for (const link of links) console.log(link);
// Narrow to specific hosts instead of a blanket internal/external split.
const docsOnly = await client.extractLinks({
url: 'https://example.com',
filter_domains: ['docs.example.com'],
});响应示例
{ "success": true, "data": { "links": [ { "href": "https://example.com/about", "text": "About", "type": "internal", "domain": "example.com", "rel": null, "original_href": "/about", "title": "About us" }, { "href": "https://example.com/products", "text": "Products", "type": "internal", "domain": "example.com", "rel": null, "original_href": "/products" }, { "href": "https://other-site.com/", "text": "External Resource", "type": "external", "domain": "other-site.com", "rel": "nofollow", "original_href": "https://other-site.com" }, { "href": "mailto:hello@example.com", "text": "Email us", "type": "other", "domain": null, "rel": null, "original_href": "mailto:hello@example.com" } ], "statistics": { "total_links": 4, "internal_links": 2, "external_links": 1, "anchor_links": 0, "relative_links": 0, "other_links": 1, "unique_domains": 2 }, "domains": { "example.com": 2, "other-site.com": 1 }, "base_url": "https://example.com", "extracted_from": "https://example.com/" }, "credits_used": 1, "credits_remaining": 999, "processing_time": 210}data.links每个链接为 { href, text, type, domain, rel, original_href }(开启 include_metadata 时另含 title),与 MCP 工具返回的记录结构相同data.links[].typeinternal(与页面同一主机)、external、anchor(#片段,需 include_anchors)、other(mailto:、tel:、javascript: 等非网页协议;除 mailto: 和 tel: 外 href 为 null)或 relative(html 输入且未提供 base_url)data.links[].original_href页面上书写的原始 href;href 是解析后的绝对 URLdata.statistics按类型计数:total_links、internal_links、external_links、anchor_links、relative_links、other_links、unique_domainsdata.domains每个域名的链接数(仅在开启 include_metadata 时返回)错误处理
被反机器人拦截页阻挡(403、444 或 502)
无论 HTTP 状态码为何,目标返回的都是反机器人验证页面,而非实际内容。响应为 success: false,error.code 为 BLOCKED,附带指明 vendor(例如 cloudflare 或 akamai)及识别依据 evidence 的 blocked 对象,以及 next_step:extract_links with escalate:true, or stealth_mode operation:"scrape"。目标的状态码为 403、404、410、429、444 或 451 时原样返回,其他情况(包括以 200 返回的拦截页)均为 502。不扣除任何 credits。设置 escalate: true 时,会改为在 stealth 浏览器中渲染一次;若渲染同样被拒,同一错误会带有 escalated: true,且不带 next_step。
目标返回错误(502 Bad Gateway)
目标返回了 HTTP 错误,且未识别出反机器人拦截页。error.code 为 UPSTREAM_HTTP,消息为 Target answered HTTP <n>。403、404、410、429、444 或 451 会作为响应状态码原样透传;其他错误(5xx,或目标自身返回的 400、401)一律为 502,以免被误认为是你的请求或 API key 有问题。403、429 或 444 还会附带 next_step。不扣除任何 credits。
被 robots.txt 拦截(403 Forbidden)
目标站点的 robots.txt 对 CrawlForge 禁止了该路径。若你与目标站点另有约定,可设置 respect_robots: false 予以覆盖——该覆盖会记录到你的 API key 上。该覆盖不适用于列入 CrawlForge 永久排除名单的主机——无论 respect_robots 取何值,这类主机一律被拒绝。
不支持的内容类型(415 Unsupported Media Type)
目标返回的是 PDF、图片或其他二进制内容。error.code 为 UNSUPPORTED_CONTENT_TYPE,消息为 Unsupported content type <type>: extract_links reads HTML,next_step 为 process_document。不会读取响应体,不会触发升级,也不扣除任何 credits。
升级后端未配置(503 TOOL_NOT_AVAILABLE)
escalate: true 的 stealth 阶段运行在 CrawlForge 执行后端上。该后端未配置时,升级阶段返回 503,且不扣除任何 credits。
相关工具
准备好提取链接了吗?免费注册,获取 1,000 credits。