关于 crawlbrulee
crawlbrulee 是面向 AI Agent 和开发者、在欧盟运行的网页抓取服务。其 MCP 服务提供页面提取、站点映射、异步任务和用量信息。
主要功能
- 01提取页面内容与元数据
- 02使用 CSS 选择器提取值
- 03映射网站链接
- 04运行异步抓取任务
- 05查看任务状态和用量
适用场景
- 01将网页转换为适合模型处理的 Markdown
- 02提取商品页面中的指定字段
- 03抓取前发现网站 URL
- 04处理耗时较长的 JavaScript 页面捕获
MCP 相关
stdio MCP 服务向 MCP 客户端提供 crawlbrulee 的抓取、映射、异步任务和用量工具。需要设置 `CRAWLBRULEE_API_KEY` 环境变量。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
7收录的工具列表 · 更新于 2 天前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| url | string | 是 | 要抓取的 URL。获取页面前会移除已知的跟踪参数,因此这些参数既不会发送到目标网站,也不属于缓存键。其他所有查询参数都会原样保留,并作为缓存键的一部分。 |
| cache | object | 否 | 此请求的缓存设置 |
| cache.max_age | any | 否 | 缓存有效期上限(秒),或 ISO 8601 日期时间截止值 |
| proxy | enum | 否 | 要用于获取内容的代理层级basic | advanced | auto |
| cleanup | object | 否 | 生成任何输出前从页面中移除的内容。适用于所有引擎的 Markdown、cleaned_html、链接和图像,也适用于截图。绝不适用于 raw_html;raw_html 始终是移除任何内容之前的页面。 |
| cleanup.ads_and_popups | boolean | 否 | 移除广告、Cookie 横幅、同意对话框和聊天组件。默认为 true。也会影响截图。设为 false 可按原样捕获页面,或绕过拒绝向拦截广告的客户端提供内容的网站。 |
| cleanup.exclude_selectors | array | 否 | 在捕获任何内容之前移除其元素的 CSS 选择器。影响提取内容和截图,但不影响 raw_html。用于指定 ads_and_popups 无法识别的横幅或组件。发送任何选择器都会使请求跳过缓存。 |
| extract | object | 否 | 要提取的内容格式。默认值为 metadata + cleaned_html。 |
| extract.links | boolean | 否 | 提取页面上的链接,每页最多 30,000 个。超过上限后,数组会被截断,响应中会包含 `links_truncated` 警告。 |
| extract.images | boolean | 否 | 提取页面上的行内图像,每页最多 10,000 张。超过上限后,数组会被截断,响应中会包含 `inline_images_truncated` 警告。 |
| extract.elements | object | 否 | 通过 CSS 选择器读取页面中的命名值,并以相同名称返回到顶层 `elements` 字段。每个值可以是选择器字符串(第一个匹配项的文本),也可以是包含 `selector`、`output`、`attribute` 和 `all` 的对象。使用 `fields`(而非 `output`)时,会将每个匹配项转换为对象,只读取该匹配项内部的命名值,因此商品卡片列表可为每张卡片返回标题、价格和 URL。未匹配到的名称返回 null;设置 `all: true` 时返回 []。在清理后读取;`<script>` 和 `<style>` 标签不包含在内。无效选择器会导致 400 错误。不额外消耗额度,即使页面来自缓存也一样。限制和选择器规则:https://crawlbrulee.com/docs/scrape/elements。 |
| extract.markdown | boolean | 否 | 将页面内容提取为整洁的 Markdown |
| extract.metadata | boolean | 否 | 从页面 head 中提取页面元数据(标题、描述、OG 标签等) |
| extract.raw_html | boolean | 否 | 返回未经处理的原始 HTML,页面正文最多 10,000,000 个字符。正文较大时,会在标签边界处截断,响应中会包含 `raw_html_truncated` 警告。 |
| extract.screenshot | object | 否 | 截取页面截图 |
| extract.screenshot.type | enum | 是 | 截图捕获模式viewport | full_page |
| extract.screenshot.viewport | object | 否 | 自定义视口尺寸;未指定时使用 device_mode 默认值 |
| extract.screenshot.viewport.width | integer | 是 | 视口宽度(像素,16–10000) |
| extract.screenshot.viewport.height | integer | 是 | 视口高度,单位为像素(16–10000) |
| extract.screenshot.viewport.device_scale_factor | number | 否 | 设备像素比(1–3,可为小数;例如 Retina 屏幕为 2)。默认值为 1。 |
| extract.screenshot.device_mode | enum | 否 | 模拟桌面或移动设备视口desktop | mobile |
| extract.screenshot.actions_after | array | 否 | 截图后执行的操作(例如,切分为多个区块) |
| extract.screenshot.actions_before | array | 否 | 截图前执行的操作(等待、滚动) |
| extract.cleaned_html | boolean | 否 | 提取清理后的 HTML:移除脚本、样式、广告和 Cookie 横幅后的页面正文 |
| location | object | 否 | 抓取时可选的区域设置和国家/地区模拟 |
| location.locale | string | 否 | BCP-47 区域设置(2–35 个字符,例如 'en-US'、'de-DE'、'pt-BR'),用于设置 Accept-Language 和 navigator.language |
| location.country | string | 否 | ISO 3166-1 alpha-2(例如 'us'、'de'、'br';不区分大小写),用于设置模拟浏览器的时区和代理出口国家/地区。也接受 'eu'(随机欧盟成员国)或 'europe'(随机欧洲国家/地区,包括英国和非欧盟国家/地区)。 |
| require_js | boolean | 否 | 使用无头浏览器在抓取前渲染 JavaScript |
| zero_data_retention | boolean | 否 | 不将结果存入共享缓存;为交付结果而存储的任何内容都会保留 24 小时,然后删除。增加 1 个额度。必须由你的组织启用。请参阅 https://crawlbrulee.com/docs/zero-data-retention。 |
详细介绍
🍮 crawlbrulee mcp
专为 AI Agent 和开发者打造的欧盟本土网页抓取服务。
将 crawlbrulee 接入你的 Agent。官方的 mcp 服务 crawlbrulee 为支持 mcp 的 Agent——Claude Code、Codex、Cursor、Claude Desktop——提供原生工具,可抓取网页、站点地图、运行后台任务并查看用量。一次调用即可将任意 url 转换为干净的 markdown、截图、元数据和链接。
- **所有操作都在欧盟境内运行。**抓取、渲染、缓存和结果都不会离开欧盟服务。代理出口是你选择的唯一一跳:选择欧盟出口,数据就不会离开欧盟。符合 gdpr 要求,并提供数据处理协议。
- **专为模型打造的输出。**markdown 会移除广告、弹窗和 cookie 横幅,同时保留链接,可直接用于提示词。整页截图可以按适合图像模型的尺寸分块返回。
- **复杂环节,轻松搞定。**网页需要时启用无头 Chrome,支持可选择国家的轮换代理、自动重试、广告和 cookie 横幅移除、缓存、后台任务和签名 webhook。
- **免费开始。**750 个积分,无需信用卡。
获取免费的 api 密钥 → dashboard.crawlbrulee.com
该服务:
- 可通过
npx运行,无需安装。 - 底层封装了
@crawlbrulee/sdk;这个 mcp 只是一个轻量的协议适配器。 - 为基于终端的 Agent 提供 stdio 传输。
- 工具架构严格且描述完整——Agent 无需阅读文档,就能了解每个参数的作用。
本 readme 介绍 mcp 服务本身——它提供的工具,以及如何将其接入宿主。关于 api 的行为——端点、参数和错误语义——请参阅我们的 api 文档。
安装
**1. 获取密钥。**如果你还没有 crawlbrulee 账户, 请注册。免费套餐无需信用卡。 然后在控制面板菜单中打开 tokens,并点击 create token。
**2. 将密钥添加到环境中。**将其添加到 shell 配置文件(例如 ~/.zshrc)中,
然后打开新的终端,并从该终端启动 Agent。不要将密钥粘贴到 Agent 的聊天中:
聊天中的所有内容都会保留在历史记录中。
export CRAWLBRULEE_API_KEY="cwbl_..."
**3. 添加服务,不要在配置中填写密钥。**在 Claude Code 中:
claude mcp add crawlbrulee -- npx -y @crawlbrulee/mcp
其他 stdio 宿主也运行相同的命令:npx -y @crawlbrulee/mcp。其中一些宿主(Codex、
Cursor、Windsurf、Gemini CLI、Claude Desktop)需要在配置文件中填写密钥或对应的
变量,而 VS Code 和 Claude Code 插件可以通过输入时隐藏内容的提示词询问密钥。
每个宿主对应的配置文件和条目请参阅:文档中的 mcp 配置。
如果密钥停止工作(invalid_credentials),说明它已过期、被撤销或输入有误:按相同方式创建
新密钥,替换旧密钥,然后重新启动 Agent。
配置
| 环境变量 | 必需 | 描述 |
|---|---|---|
CRAWLBRULEE_API_KEY | 是 | 作为 Authorization: Bearer … 发送的 api 密钥。如何获取请参阅安装。 |
mcp 会在首次调用工具时读取环境变量,而不是在启动时读取,因此配置中的拼写错误会显示为清晰的工具错误消息,而不会导致服务无法启动。关于 api 如何使用密钥,请参阅 身份验证。
工具
scrape
抓取单个 url,并返回所请求的内容(markdown、清理后的
html、原始 html、链接、图片、截图、页面元数据)。
输入 — 仅 url 是必填项;其他所有参数都有合理的默认值。
{
"url": "https://example.com",
"extract": {
"markdown": true,
"links": true,
"screenshot": { "type": "full_page", "device_mode": "desktop" },
},
"require_js": false,
"proxy": "basic",
"cleanup": { "ads_and_popups": true, "exclude_selectors": ["nav", "footer"] },
"cache": { "max_age": 3600 },
"location": { "locale": "en-US", "country": "US" },
"zero_data_retention": false,
}
zero_data_retention(布尔值,默认 false)会使结果不进入共享缓存;为传递结果而存储的任何内容都会保留 24 小时,然后删除。启用此选项会额外消耗 1 个点数,且必须由你的组织启用。scrape_async 也支持此选项。请参阅零数据保留。
使用 extract.elements 获取命名值。 要从页面提取少量值(例如价格、标题、链接),请为每个值指定名称和 CSS 选择器,而不是读取整篇 Markdown。提取结果会以相同名称返回在 elements 中。all: true 会以列表形式返回所有匹配项,fields 则会读取每个匹配项中的命名值。此功能不额外消耗点数。scrape_async 也支持此功能。
{
"url": "https://books.toscrape.com/",
"extract": {
"elements": {
"heading": "h1",
"books": {
"selector": "article.product_pod",
"all": true,
"fields": {
"title": { "selector": "h3 a", "output": "attribute", "attribute": "title" },
"price": ".price_color",
},
},
},
},
}
// → "elements": {
// "heading": "All products",
// "books": [{ "title": "A Light in the Attic", "price": "£51.77" }, ...]
// }
没有匹配项的名称会返回 null(使用 all: true 时则返回 [])。限制和选择器规则请参阅 elements。
输出 — 完整的抓取结果。页面元数据(标题、OG 标签等)会在 metadata 下返回。提取的 images 会以绝对 URL 返回——保留查询字符串,并根据页面 URL 解析相对 src。截图会以带签名的下载 URL 返回,Agent 可以单独获取。在少数情况下,截图可能无法捕获:如果你还请求了其他输出,系统只会省略 screenshot 字段,并继续返回其余内容;但如果仅请求截图且无法提供,则会返回错误(当内容类型不支持截图时,错误为 unsupported_screenshot_output,HTTP 422),且不计费。结果还包含 page_status_code 和顶层的 response_meta.usage 块:
{
"url": "https://example.com",
"requested_url": "https://example.com",
"page_status_code": 200, // the site's own HTTP status for the final page
"markdown": "...",
"metadata": { "title": "Example Domain" },
"response_meta": {
"usage": {
// total_credit_cost = engine_credit_cost × proxy_multiplier + screenshot_slicing_credit_cost + zero_data_retention_credit_cost
"total_credit_cost": 1,
"engine_credit_cost": 1, // http 1, browser 3, screenshot 5, cache 0
"proxy_multiplier": 1, // basic 1, advanced 5
"screenshot_slicing_credit_cost": 0, // 1 when the screenshot was split into slices, otherwise 0
"zero_data_retention_credit_cost": 0, // 1 when zero_data_retention added its credit, otherwise 0
"engine": "http", // "http" | "browser" | "screenshot" | "cache"
"proxy": "basic", // resolved tier actually used: "basic" | "advanced" (never "auto")
},
},
}
网站返回的页面属于结果,而不是错误。 page_status_code 是网站在重定向后对最终页面返回的 HTTP 状态码。404、410 或 503 页面会连同其内容和此处的状态码一起返回,因此请先检查 page_status_code,再判断内容是否可信:404 表示 Markdown 内容是网站的“未找到”页面。2xx 和 4xx 页面会计费,但 403、407、408、429 和 451 除外;5xx 页面永不计费。如果完全无法访问该网站,工具会改为返回 target_unreachable 错误(请参阅错误)。
除了 response_meta.usage,结果还会提供任何非致命的 warnings——Agent 可以据此判断的稳定字符串代码。对于超大页面,系统会截断内容,而不是拒绝请求;代码会指出被截断的部分:
| code | 对返回内容的含义 |
|---|---|
screenshot_truncated | 页面高度超过滚动截图的高度上限;截图仅包含页面顶部。 |
links_truncated | 页面链接超过 30,000 个;links 数组会截断至上限,因此内容不完整。 |
inline_images_truncated | 页面内嵌图片超过 10,000 张;images 数组会截断至上限,因此内容不完整。 |
raw_html_truncated | 页面正文超过 10,000,000 个字符;raw_html 会在标签边界处截断,不会截断标签本身。 |
elements_truncated | 某个 elements 值达到限制;请参阅 elements。 |
还有一个代码与大小无关:screenshot_unavailable 表示请求了截图,但页面从 HTTP 引擎返回时没有截图。其余结果仍会返回。
如果你请求的提取内容不适用于该内容类型(例如 JSON 文件的 metadata),字段名称会出现在 unsupported_fields 列表中,其余内容仍会返回。
每个输入字段、默认值和约束都记录在 scrape 端点下;其中,提取、屏幕截图、代理和位置以及缓存分别介绍了各个模块。
scrape_async
提交一个异步运行的抓取任务,并立即获取 job_id,而不是让连接一直保持打开状态。适用于运行时间较长的抓取(繁重的 JS 渲染、长页面的整页屏幕截图);若要快速进行一次性抓取,请优先使用同步的 scrape 工具。然后轮询 scrape_status,直到任务状态为 done,再通过 scrape_result 获取页面。
接受与 scrape 相同的输入,另有一个可选的、按任务设置的完成 webhook:
{
"url": "https://example.com",
"extract": { "markdown": true },
"webhook": {
// Endpoint that receives one signed `scrape.complete` POST when the job
// finishes. http/https (HTTPS required in production), max 2048 chars.
"url": "https://hooks.example.com/cwbl",
// Opaque correlation object echoed back verbatim in the delivery's
// `data.metadata`. Serializes to at most 2048 bytes.
"metadata": { "ref": "order-42" },
},
}
输出 — { "job_id": "..." }。
关联 webhook 后,任务到达终止状态时,我们会向你的端点发送一次带签名的 scrape.complete POST,其中 metadata 会原样包含在 data.metadata 下,任务用量则包含在 data.response_meta.usage 下。这样,你无需轮询即可对任务完成做出响应(并跟踪成本)。请使用 SDK 的 verifyWebhookSignature 验证 X-Cwbl-Signature 标头(在仪表板的 account → webhooks 下配置签名密钥)。
任务生命周期记录在 异步抓取中;投递约定和载荷格式记录在 webhooks中;签名方案则记录在 webhook 验证中。
scrape_status
查询异步任务当前的生命周期状态:pending、running、done 或 failed(失败时会附带 error 消息)。任务状态为 done 后,响应还会包含一个 response_meta.usage 块(total_credit_cost 及其组成部分、计费的 engine、解析后的 proxy 级别)。缓存命中会显示为 engine: "cache"。如果网站返回了页面,任务就会以 done 结束,即使该页面是 404;请读取结果中的 page_status_code。持续轮询直到状态为 done,然后调用 scrape_result。
{ "job_id": "..." }
scrape_result
获取已完成异步任务的提取内容——其结果格式与同步 scrape 工具相同(包括 page_status_code、metadata、elements 和 response_meta.usage)。如果任务仍处于 pending/running 状态,则会报错,因此请先检查 scrape_status。
{ "job_id": "..." }
map
为网站构建链接映射(或获取缓存的映射)。它结合站点地图发现和首页链接提取。可先用它枚举网站,再抓取选定页面。每个链接都只是 { url }。
max_urls(默认值为 5000,最大值为 100000)是发现预算,并非最后再裁剪结果:找到这么多 URL 后,发现过程就会停止,因此值越小,爬取速度越快、成本越低。limit(默认值为 5000,最大值为 10000)仅用于分页返回结果。
返回的 URL 会按照与 scrape 规范化其返回的 url 相同的方式进行规范化,因此先执行 map 再执行 scrape 会始终使用同一主机。结果按链接的实用程度从高到低排序。
响应中的 response_meta 包含 pagination、truncation 和 usage 块(total_credit_cost = engine_credit_cost × proxy_multiplier + zero_data_retention_credit_cost,以及计费的 engine 和解析后的 proxy 层级)。map 不会进行截图切片,也不会提供 page_status_code,因为它读取的是多个文件,而不是单个页面。如果网站只返回不计费的状态码(例如 5xx),或完全没有响应,导致 map 未找到任何内容,那么结果为空且免费。
{
"url": "https://example.com",
"sitemap_only": false,
"types": { "internal": true, "external": false, "internal_subdomains": true },
"max_urls": 5000,
"page": 1,
"limit": 1000,
"zero_data_retention": false,
}
zero_data_retention 的工作方式与 scrape 相同(参见零数据保留)。
如果 map 因你设置的 max_urls 而停止,则会恰好返回这么多条链接,且 response_capped: false。网站还有更多内容的信号是 truncation.discovery_cap_reason:
{
"truncation": {
"storage_capped": false,
"response_capped": false,
"total_before_max_urls": 5000,
"total_detected_before_storage_cap": 5000,
"discovery_capped": true, // discovery stopped before reading every sitemap file
"sitemaps_skipped": 3, // files skipped or only partly read
"discovery_cap_reason": "max_urls", // retry with a higher max_urls
},
}
discovery_cap_reason 的值为 max_urls、time、file_budget、depth、file_size、unread_files,或者在发现过程未被中断时为 null。只有 max_urls 是可通过请求提高的限制。unread_files 表示网站发布的某个站点地图文件此次完全无法读取;这通常是暂时情况,因此稍后再次请求可能会返回更多内容。time、file_budget、depth 和 file_size 表示网站本身规模大、速度慢或层级深,重试也无济于事。
有关发现规则和分页语义,请参阅 map 端点。
usage
返回当前计费周期的快照:总额度、已用额度、可用额度、已用配额百分比、最大并发数和周期重置时间戳。不接受任何参数。有关调用费用以及额度的计算方式,请参阅额度与定价。
whoami
返回配置的 API 密钥对应的组织名称、令牌名称和截断后的令牌预览。可用于在执行会消耗额度的操作前确认当前使用的是哪个帐户。
错误
每个工具在 API 调用失败时都会返回 MCP 错误结果(isError: true)。错误文本遵循稳定的格式:
[<errorName>] <message> (HTTP <status>)
部分错误代码后会附带简短的后续步骤,例如 target_unreachable 和 zero_data_retention_not_enabled。请根据 errorName 代码进行分支处理,不要依赖其余文本。
Agent 可以根据 errorName 代码进行分支处理。代码集合来自 SDK 的 ApiErrorName 联合类型,以及此 MCP 添加的两个合成代码(missing_api_key、internal_error):
| code | 含义 |
|---|---|
missing_api_key | MCP 主机的环境变量中未设置 CRAWLBRULEE_API_KEY。消息会说明如何获取密钥。 |
invalid_credentials | API 拒绝了该密钥:密钥已过期、已撤销或输入有误。消息会说明如何获取新密钥。 |
service_unavailable | 后端临时故障(HTTP 503)。密钥没有问题——请采用退避策略后重试。 |
too_many_requests | 达到速率限制——请退避后重试。 |
usage_allocation_error | 超出计划额度或并发上限。向用户显示 usage。 |
validation_error | 输入未通过服务器验证。 |
invalid_url | 抓取前目标 URL 已被拒绝。 |
blocked_url | 目标 URL 位于屏蔽列表中。 |
antibot_blocked | 来源站点的反机器人防护阻止了抓取。 |
too_many_redirects | 来源站点使抓取陷入重定向循环(HTTP 422)。这是目标站点导致的——不要盲目重试。 |
page_too_large | 网页 HTML 太大,无法处理(HTTP 422)。这是终止性错误——切勿重试。 |
target_unreachable | 完全无法访问该站点(HTTP 502)。不计费。稍后重试或检查 URL。 |
zero_data_retention_not_enabled | 你的组织未启用 zero_data_retention(HTTP 403)。不计费。 |
scrape_error | 无法完成抓取。站点返回的页面(即使是 404)也不会触发此错误。 |
unsupported_screenshot_output | 请求仅获取屏幕截图,但内容类型不支持截图(HTTP 422)。不计费。 |
not_found | 异步任务 ID 未知,或提交时间已超过 24 小时(scrape_status / scrape_result)。 |
request_timeout | 网络超时或读取超时。可以安全重试。 |
client_closed_request | 调用方在完成前取消了请求。 |
internal_server_error | 未处理的服务器端故障。 |
crawlbrulee_error | SDK 错误,未指定类型名称。 |
internal_error | 此 MCP 中存在错误——请提交 issue。 |
API 文档提供了权威的错误参考,列出每个错误名称、错误原因及恢复方法。
开发
pnpm install
pnpm typecheck # tsc --noEmit
pnpm lint # eslint
pnpm test # vitest run
pnpm build # tsup → dist/index.js with shebang
pnpm verify # all of the above
在本地运行已构建的 MCP:
CRAWLBRULEE_API_KEY=cwbl_... node ./dist/index.js
它会阻塞并等待通过 stdio 连接的 MCP 客户端。与 MCP Inspector 配合使用,可进行交互式调试。
文档
本 README 介绍 MCP 服务本身——如何安装、将其接入宿主,以及它提供的工具。有关 API 的行为方式——端点、参数和错误语义,请以API 文档为准。MCP 指南更详细地介绍了宿主设置。
Crawlbrulee 工具包的一部分
一个 API,多种调用方式:
- JS/TS SDK —
@crawlbrulee/sdk(此 MCP 服务封装的 SDK) - Python SDK — PyPI 上的
crawlbrulee - CLI —
npx crawlbrulee - MCP 服务 —
@crawlbrulee/mcp(本项目) - Agent 技能 — 适用于支持技能的编码 Agent
文档:crawlbrulee.com/docs · 控制面板:dashboard.crawlbrulee.com
许可证
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。