关于 Kloakt
Kloakt 是面向 AI Agent 的 Rust 无头浏览器和命令行工具,可渲染 JavaScript、提取网页内容并支持持久化浏览器会话。其 MCP 服务提供 12 个工具,涵盖提取、爬取、页面结构、截图和会话控制。
主要功能
- 01提取干净的 Markdown 和结构化数据
- 02渲染 JavaScript 并获取网页
- 03并行抓取、搜索和爬取
- 04生成无障碍结构及交互元素快照
- 05持久化会话与页面操作
- 06MCP 工具和 CDP 服务
适用场景
- 01提取 JavaScript 密集型网页的主要内容
- 02并发收集多个 URL 的数据
- 03操作网页前检查可点击元素
- 04在多次浏览器操作间保留 Cookie 和页面状态
MCP 相关
内置 MCP 服务,提供 12 个用于提取、获取、抓取、搜索、爬取、生成快照和截图以及管理持久化会话的工具。它还提供 CDP 服务,供 Puppeteer 和 Playwright 客户端使用。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
2收录的工具列表 · 更新于 2 周前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| url | string | 是 | 要提取内容的 URL |
| delay | integer | 否 | 页面加载后等待异步内容的额外毫秒数(默认值:0) |
| format | enum | 否 | 输出格式(默认:markdown)markdown | text | links |
| stealth | boolean | 否 | 启用反检测模式 |
| selector | string | 否 | 提取前等待的 CSS 选择器 |
| main_only | boolean | 否 | 移除导航栏、页眉、页脚和侧边栏(默认值:true) |
| max_chars | integer | 否 | 将内容截断为 N 个字符(0 = 不限,默认值:0) |
| wait_until | enum | 否 | 页面加载完成的判定时机(默认值:load)load | domcontentloaded | networkidle0 |
详细介绍
Kloakt
适用于 AI Agent 的隐身无头浏览器。
轻量、隐身,以 Rust 构建。基于 Obscura。
Kloakt 是一款为 AI Agent 打造的无头浏览器。它通过 V8 运行 JavaScript,从任何网页(包括 SPA)提取干净的 Markdown,并通过 MCP 为 Claude Code 和其他 AI 系统提供工具。
除了单次提取,它还可以驱动持久化、有状态的会话(点击、输入、导航——Cookie 和页面/JS 状态都会在多次调用之间保留),生成无障碍/结构快照以替代 Agent 视觉能力,还能通过系统 Chrome 捕获真实截图——总共提供 12 个 MCP 工具。
为什么选择 Kloakt?
| 指标 | Kloakt | Headless Chrome |
|---|---|---|
| 内存 | 30 MB | 200+ MB |
| 二进制大小 | 70 MB | 300+ MB |
| 反检测 | 内置 | 无 |
| 页面加载 | 85 ms | ~500 ms |
| 启动 | 即时 | ~2s |
| SPA 提取 | 支持 | 手动 |
安装
预编译二进制文件(推荐)
单行安装(Linux 和 macOS)。从最新的 GitHub Release 下载适用于你的操作系统和架构的二进制文件,并安装到 ~/.local/bin(以 root 运行时安装到 /usr/local/bin):
curl -fsSL https://raw.githubusercontent.com/KultMember6Banger/kloakt/main/install.sh | sh
你可以指定版本,或覆盖安装目录:
KLOAKT_VERSION=v0.1.2 INSTALL_DIR=/usr/local/bin \
sh -c "$(curl -fsSL https://raw.githubusercontent.com/KultMember6Banger/kloakt/main/install.sh)"
Windows:从 Releases 页面下载 kloakt-x86_64-windows.zip,并将 kloakt.exe 解压到 PATH 中。
Homebrew(macOS)
brew install KultMember6Banger/kloakt/kloakt
# or, from a local checkout:
brew install --formula ./Formula/kloakt.rb
(在专用 tap 建立之前,先运行 brew tap KultMember6Banger/kloakt https://github.com/KultMember6Banger/kloakt,然后运行 brew install kloakt。)
cargo install
从 crates.io 构建 CLI(需要 Rust 工具链;首次构建会编译 V8,约需 5 分钟):
cargo install obscura-cli
这会安装 kloakt 二进制文件。若要启用隐身模式进行构建,请添加 --features stealth。
从源代码构建
git clone https://github.com/KultMember6Banger/kloakt.git
cd kloakt
cargo build --release
# With stealth mode (anti-detection + tracker blocking)
cargo build --release --features stealth
需要 Rust 1.75+(rustup.rs)。首次构建约需 5 分钟(V8 会从源代码编译,之后会缓存)。
快速开始
提取内容(供 AI Agent 使用)
# Clean markdown from any page
kloakt extract https://example.com --main
# Structured JSON with metadata
kloakt extract https://example.com --main --json
# Cap output for agent context windows
kloakt extract https://en.wikipedia.org/wiki/Rust --main --json --max-chars 3000
# Wait for SPA hydration
kloakt extract https://example.com --delay 2000 --json
获取页面
# Get the page title
kloakt fetch https://example.com --eval "document.title"
# Extract all links
kloakt fetch https://example.com --dump links
# Render JavaScript and dump markdown
kloakt fetch https://news.ycombinator.com --dump markdown
# Wait for dynamic content
kloakt fetch https://example.com --wait-until networkidle0
启动 CDP 服务
kloakt serve --port 9222
# With stealth mode
kloakt serve --port 9222 --stealth
并行抓取
kloakt scrape url1 url2 url3 ... \
--concurrency 25 \
--eval "document.querySelector('h1').textContent" \
--format json
快照页面结构(Agent 视觉能力)
# Indexed accessibility/structure tree — tags, text, roles, what's clickable, visibility
kloakt snapshot https://example.com
# Only the actionable elements (links, buttons, inputs), with id/name/label for targeting
kloakt snapshot https://example.com --interactive
kloakt 没有光栅化器,因此对于依赖结构而非像素工作的 Agent,这是一个轻量视图,可展示“页面上有什么,以及可以对哪些内容执行操作”。
截图(通过系统 Chrome)
# Real PNG — delegates to a locally-installed Chrome/Chromium/Edge
kloakt screenshot https://example.com --output shot.png --width 1280 --height 800
持久化会话
通过正在运行的 kloakt serve 守护进程,驱动一个具名会话,让 Cookie 和页面/JS 状态在多次独立调用之间保持不变:
kloakt serve --port 9222 & # start the daemon once
kloakt session open shop --url https://example.com
kloakt session snapshot shop --interactive # see the page structure
kloakt session type shop 'input[name=q]' 'hello' # fill a field
kloakt session click shop 'button[type=submit]' # click an element
kloakt session text shop # read the body text
kloakt session eval shop 'document.title' # run JS, get the value back
kloakt session close shop # tear down (drops cookies + page)
智能提取
extract 命令采用针对 AI Agent 优化的多阶段处理流程:
- 移除噪声 — 清除 Cookie 横幅、广告、弹窗、导航栏和社交组件
- 内容评分 — 使用文本密度算法(类似 Readability)查找主要内容块
- Markdown 转换 — 将 DOM 转换为 Markdown,并解析绝对 URL
- SPA 回退 — JavaScript 渲染失败时,从 meta 标签、Open Graph、JSON-LD 和 noscript 内容中提取信息
适用于静态 HTML、服务端渲染页面和纯客户端 SPA(React、Vue 等)。
Python API
from kloakt import (
extract, extract_fields, fetch, scrape, search, crawl,
snapshot, screenshot, session_open, session_close,
)
# Extract clean markdown
page = extract("https://example.com")
print(page.title, page.content, page.meta)
# Cap output length
page = extract("https://example.com", max_chars=3000)
# Wait for SPA content
page = extract("https://example.com", delay=2000)
# Structured field extraction via CSS selectors
data = extract_fields("https://news.ycombinator.com", {
"title": "title",
"stories": ".titleline > a[]", # [] => list of all matches
"links": ".titleline > a[]@href" # @href => an attribute
})
print(data["data"]["stories"])
# Raw fetch
html = fetch("https://example.com", dump="html")
title = fetch("https://example.com", eval_js="document.title")
# Parallel scrape
results = scrape(["https://a.com", "https://b.com"], concurrency=5)
# Discover links, or breadth-first crawl a small section of a site
links = search("https://news.ycombinator.com", same_domain=True)
pages = crawl("https://example.com", max_pages=5, max_depth=1)
# Structure snapshot (agent vision) and a real screenshot via system Chrome
snap = snapshot("https://example.com", interactive=True)
screenshot("https://example.com", output="shot.png")
# Persistent session — auto-starts a daemon if one isn't running; cookies + page
# state persist across calls. (session_nav / _click / _type / _eval / _text / _snapshot)
session_open("shop", url="https://example.com")
# ... drive the page across calls ...
session_close("shop")
MCP 服务(Claude Code)
Kloakt 内置了一个 MCP 服务,可用作 Claude Code 工具:
{
"mcpServers": {
"kloakt": {
"command": "python3",
"args": ["/path/to/kloakt/mcp_server.py"]
}
}
}
提供 12 个原生工具:
| 工具 | 功能 |
|---|---|
kloakt_extract | 清理 Markdown,或通过 schema 提取结构化字段 |
kloakt_fetch | 底层抓取(html/text/links/markdown,或执行 JS) |
kloakt_scrape | 并行处理多个 URL |
kloakt_search | 发现页面上的外链 |
kloakt_crawl | 限制预算和深度的广度优先爬取 |
kloakt_snapshot | 可访问性/结构树(Agent 视觉) |
kloakt_screenshot | 使用系统 Chrome 截取真实 PNG |
kloakt_session_open | 打开一个持久命名会话 |
kloakt_session_act | 在会话中导航/点击/输入/执行 eval |
kloakt_session_read | 将会话页面读取为文本或快照 |
kloakt_session_list | 列出打开的会话 |
kloakt_session_close | 关闭会话(清除其 Cookie 和页面) |
Puppeteer / Playwright
Puppeteer
CDP 服务会在 WebSocket 路径中嵌入每个会话的令牌(类似 Chrome)。通过
browserURL 连接,客户端会自动从 /json/version 获取令牌——不要
硬编码 ws://.../devtools/browser 路径。
import puppeteer from 'puppeteer-core';
const browser = await puppeteer.connect({
browserURL: 'http://127.0.0.1:9222', // discovers the tokenized ws endpoint
});
const page = await browser.newPage();
await page.goto('https://news.ycombinator.com');
const stories = await page.evaluate(() =>
Array.from(document.querySelectorAll('.titleline > a'))
.map(a => ({ title: a.textContent, url: a.href }))
);
await browser.disconnect();
Playwright
import { chromium } from 'playwright-core';
const browser = await chromium.connectOverCDP({
endpointURL: 'http://127.0.0.1:9222', // discovers the tokenized ws endpoint
});
const page = await browser.newContext().then(ctx => ctx.newPage());
await page.goto('https://en.wikipedia.org/wiki/Web_scraping');
console.log(await page.title());
await browser.close();
隐身模式
使用 --features stealth 启用。
- 每个会话随机化指纹(GPU、屏幕、Canvas、音频、电池)
- 真实的
navigator.userAgentData(Chrome 145、高熵值) - 为派发的事件设置
event.isTrusted = true - 原生函数伪装(
Function.prototype.toString()→[native code]) navigator.webdriver = undefined- 真实的
Accept-Language和 Client Hints(Sec-CH-UA)请求标头 - 每个会话随机化
navigator.languages - TLS 指纹(JA3)在 Chrome 145 Linux / Windows / macOS 配置间轮换
- 阻止 3,520 个跟踪器域名
CLI 参考
kloakt extract <URL>
| 标志 | 默认值 | 描述 |
|---|---|---|
--format | markdown | 输出:markdown、text 或 links |
--main | 关闭 | 移除导航栏、页眉、页脚和侧边栏 |
--json | 关闭 | 结构化 JSON:标题、URL、内容、元数据 |
--max-chars | 不限 | 将内容截断为 N 个字符 |
--delay | 0 | 加载后额外等待的毫秒数 |
--stealth | 关闭 | 反检测模式 |
--selector | — | 等待 CSS 选择器 |
--wait-until | load | load、domcontentloaded、networkidle0(受 --wait 限制) |
--schema | — | 将结构化字段提取为 JSON(见下文) |
--har | — | 将捕获的网络活动写入 HAR 文件 |
--cache-ttl | 0 | 将结果缓存到磁盘,并在 N 秒内复用 |
使用 --schema 进行结构化提取
传入一个 JSON 对象,将字段名称映射到 CSS 选择器。在选择器末尾加上 [],可将所有匹配项作为列表返回;加上 @attr,则返回属性而不是文本:
kloakt extract https://news.ycombinator.com \
--schema '{"title":"title","stories":".titleline > a[]","first_link":".titleline > a@href"}'
# => { "url": ..., "data": { "title": "...", "stories": [...], "first_link": "..." }, "elapsed_ms": ... }
也可通过可选的 schema 参数,使用 MCP kloakt_extract 工具进行此操作。
kloakt fetch <URL>
| 标志 | 默认值 | 描述 |
|---|---|---|
--dump | html | 输出:html、text、links、markdown |
--eval | — | 要执行的 JavaScript 表达式 |
--wait-until | load | 等待条件 |
--selector | — | 等待 CSS 选择器 |
--stealth | 关闭 | 反检测模式 |
--quiet | 关闭 | 禁止显示横幅 |
kloakt serve
| 标志 | 默认值 | 描述 |
|---|---|---|
--port | 9222 | WebSocket 端口 |
--proxy | — | HTTP/SOCKS5 代理 URL |
--stealth | 关闭 | 反检测并阻止跟踪器 |
--workers | 1 | 并行工作线程数 |
kloakt scrape <URL...>
| 标志 | 默认值 | 描述 |
|---|---|---|
--concurrency | 10 | 并行工作线程数 |
--eval | — | 对每个页面执行的 JS 表达式 |
--format | json | 输出:json 或 text |
kloakt snapshot <URL>
生成带索引的无障碍/结构树(始终为 JSON)——作为 Agent 视觉能力的替代方案。
每个节点都经过精简:i(索引)、tag、depth、vis(可见),以及(如有)click、
role、text、type/value、href、id、name、label。
| 标志 | 默认值 | 描述 |
|---|---|---|
--interactive | 关闭 | 仅包含可操作元素(链接、按钮、输入框) |
--max-nodes | 1500 | 输出节点数上限 |
--stealth | 关闭 | 反检测模式 |
--delay | 0 | 页面加载后额外等待的毫秒数 |
--wait-until | load | 等待条件 |
kloakt screenshot <URL>
委托给本地安装的 Chrome/Chromium/Edge,截取真实 PNG 图片(kloakt 不含栅格化程序)。
如果找不到浏览器,会清楚地报错;可通过 --chrome <path> 或 KLOAKT_CHROME 环境变量覆盖检测结果。
| 标志 | 默认值 | 描述 |
|---|---|---|
--output | screenshot.png | 输出 PNG 路径 |
--width | 1280 | 视口宽度 |
--height | 800 | 视口高度 |
--chrome | 自动检测 | Chrome/Chromium/Edge 二进制文件的路径 |
kloakt session <COMMAND>
通过正在运行的 kloakt serve 守护进程,操作持久化的命名会话。Cookie 和
页面/JS 状态会在多次调用之间保留(客户端状态存储于 ~/.kloakt/sessions/<name>.json)。
| 命令 | 描述 |
|---|---|
open <name> [--url URL] [--port] | 打开会话(或重新连接到会话)并创建页面 |
nav <name> <url> | 导航会话页面 |
eval <name> <expr> | 计算 JS 表达式并打印 JSON 值 |
text <name> | 打印 document.body.innerText |
snapshot <name> [--interactive] | 获取会话页面的结构快照 |
click <name> <selector> | 点击第一个匹配的元素 |
type <name> <selector> <text> | 聚焦元素、设置其值,并触发 input/change 事件 |
list [--port] | 列出守护进程上的开放会话 |
close <name> | 关闭会话(移除其页面和 Cookie) |
传递给
eval的多语句 JS 会返回null(守护进程只计算单个表达式);请将其包装在 IIFE 中——(function(){ ...; return v })()——以返回值。
kloakt benchmark <URL...>
测量每个 URL 的加载性能——加载时间的平均值/最小值/最大值、请求数、字节数和 DOM
节点数——以表格或 --json 格式输出。
kloakt benchmark https://example.com https://news.ycombinator.com --runs 3
| 标志 | 默认值 | 描述 |
|---|---|---|
--runs | 1 | 每个 URL 的运行次数(报告平均值) |
--json | 关闭 | 输出 JSON,而非表格 |
--wait-until | load | load、domcontentloaded 或 networkidle0 |
挑战 / 机器人拦截检测
kloakt extract --json 会包含 "challenge" 字段,用于报告检测到的验证码或机器人拦截
(recaptcha、hcaptcha、turnstile、cloudflare、datadome、perimeterx),未检测到时则为
null。这仅用于检测——kloakt 会告知你页面受到拦截,让 Agent 可以停止操作并暂缓尝试;不会尝试解决或规避挑战。(此信息也会显示在 MCP
kloakt_extract 输出和 Python Page.challenge 字段中。)
全局标志
| 标志 | 默认值 | 描述 |
|---|---|---|
--obey-robots | 关闭 | 遵循 robots.txt——拒绝抓取禁止访问的路径 |
--allow-private | 关闭 | 允许私有/内部/回环主机(禁用 SSRF 防护) |
安全提示: 默认情况下,kloakt 会拒绝抓取私有、回环、链路本地和云元数据地址(SSRF 防护),并拒绝
file://URL。仅在确实需要访问内部服务时才使用--allow-private。CDP 服务绑定到127.0.0.1,并验证Host请求头以阻止 DNS 重绑定。
CDP API
完整支持 Chrome DevTools Protocol,兼容 Puppeteer/Playwright。
| 域 | 方法 |
|---|---|
| Session | open、close、list — 命名且持久的浏览器上下文,可保持 Cookie 有效 |
| Target | createTarget(browserContextName 将页面绑定到会话)、closeTarget、attachToTarget、createBrowserContext、disposeBrowserContext |
| Page | navigate、getFrameTree、addScriptToEvaluateOnNewDocument、lifecycleEvents |
| Runtime | evaluate、callFunctionOn、getProperties、addBinding |
| DOM | getDocument、querySelector、querySelectorAll、getOuterHTML、resolveNode |
| Network | enable、setCookies、getCookies、setExtraHTTPHeaders、setUserAgentOverride |
| Fetch | enable、continueRequest、fulfillRequest、failRequest |
| Storage | getCookies、setCookies、deleteCookies |
| Input | dispatchMouseEvent、dispatchKeyEvent |
许可证
Apache 2.0 — 基于 h4ckf0r0day 的 Obscura。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。