web-speed-agent
web-speed-agent
本地浏览器自动化 + Web Speed API 集成,用于已授权的网页提取。
将 AI 代理指向任何网站(包括需要登录的网站),即可获取干净、结构化的数据。凭据保留在您的机器上。只有提取出的 HTML 会发送到服务器。
pip install web-speed-agent
playwright install chromium想要将其与 Claude、Gemini 或其他 AI 客户端一起使用吗?
查看 MCP 服务器安装指南 —— 这是让 AI 代理通过自然语言登录并提取数据的最简单方法。
工作原理
Your machine Web Speed server
───────────────────────────────── ──────────────────────────
Playwright browser (local)
↓ navigates, logs in, clicks
↓ gets page HTML
↓ (no passwords sent)
agent.extract(html) ────────→ Advanced extraction engine
←──────── Structured JSON凭据永远不会离开您的机器。服务器只能看到 HTML。
Related MCP server: Agent Identity MCP Server
快速入门
import asyncio
from web_speed_agent import Agent
async def main():
agent = Agent(api_key="wsp_...") # or set WEBSPEED_API_KEY env var
# Public pages — no browser needed
result = await agent.map("https://techcrunch.com/some-article/")
print(result["article"]["sections"])
# Authenticated pages — browser runs locally
agent.store_credential("mysite", "me@example.com", "mypassword")
async with agent.browser(session_name="mysite") as browser:
page = await browser.new_page()
await page.goto("https://mysite.com/login")
username, password = agent.get_credential("mysite")
await page.fill('[name="email"]', username)
await page.fill('[name="password"]', password)
await page.click('button[type="submit"]')
await page.wait_for_load_state("networkidle")
# Now on a logged-in page — extract it
html = await page.content()
result = await agent.extract(html, page_type="listing")
print(result["listing"]["items"])
asyncio.run(main())在 getwebspeed.io 获取 API 密钥。
安装
要求: Python 3.10+,Web Speed API 密钥
pip install web-speed-agent
playwright install chromium
export WEBSPEED_API_KEY="wsp_..."核心概念
代理 (Agent)
主类。管理凭据、浏览器会话和 API 调用。
from web_speed_agent import Agent
# API key from argument
agent = Agent(api_key="wsp_...")
# API key from environment variable (recommended)
# export WEBSPEED_API_KEY="wsp_..."
agent = Agent()
# Use as async context manager (auto-closes HTTP client)
async with Agent() as agent:
...提取公共页面
对于不需要登录的页面,无需浏览器:
# Fetch + extract in one call
result = await agent.map("https://example.com/article")
# With JavaScript rendering (for heavy SPAs)
result = await agent.map("https://example.com/spa", js=True)提取已授权页面
使用本地浏览器会话。浏览器在您的机器上运行:
async with agent.browser(session_name="mysite") as browser:
page = await browser.new_page()
await page.goto("https://mysite.com/dashboard")
html = await page.content()
result = await agent.extract(html)session_name 会将 Cookie 持久化到 ~/.webspeed/sessions/<name>/,以便后续运行跳过登录步骤。
凭据管理
凭据存储在您的系统钥匙串中(macOS Keychain、Windows 凭据管理器、Linux secret-tool)。它们永远不会发送到 Web Speed 服务器。
# Store once
agent.store_credential("mysite", "me@example.com", "mypassword")
# Retrieve anywhere
username, password = agent.get_credential("mysite")
# Remove
agent.delete_credential("mysite")提取输出
服务器返回页面类型感知的结构化数据:
# Article
result = await agent.extract(html, page_type="article")
# result["page_type"] → "article"
# result["title"] → "Article Title"
# result["author"] → "Jane Smith"
# result["published_date"] → "2026-05-06"
# result["article"]["sections"] → [{"heading": "...", "paragraphs": [...]}]
# result["article"]["links"] → [{"text": "...", "url": "..."}]
# Product
result = await agent.extract(html, page_type="product")
# result["product"]["name"] → "Wireless Headphones"
# result["product"]["price"] → "$99.99"
# result["product"]["availability"] → "In Stock"
# result["product"]["rating"] → "4.5"
# result["product"]["specs"] → {"Battery": "30h", ...}
# Listing (search results, category pages)
result = await agent.extract(html, page_type="listing")
# result["listing"]["items"] → [{"title": "...", "url": "...", "price": "..."}]
# Auto-detect (default)
result = await agent.extract(html)
# result["page_type"] → "article" | "product" | "listing" | "other"所有结果都包含 engine: "advanced" —— 比原始 HTML 的 Token 效率高 60–85%。
示例
价格监控
import asyncio
from web_speed_agent import Agent
async def check_price(url: str, site_name: str) -> str:
async with Agent() as agent:
agent.store_credential(site_name, "me@example.com", "password", overwrite=True)
async with agent.browser(session_name=site_name) as browser:
page = await browser.new_page()
# Login
await page.goto(f"https://{site_name}.com/login")
user, pwd = agent.get_credential(site_name)
await page.fill('[name="email"]', user)
await page.fill('[name="password"]', pwd)
await page.click('button[type="submit"]')
await page.wait_for_load_state("networkidle")
# Check product
await page.goto(url)
await page.wait_for_load_state("networkidle")
html = await page.content()
result = await agent.extract(html, page_type="product")
return result.get("product", {}).get("price", "unknown")
price = asyncio.run(check_price("https://example.com/product/123", "example"))
print(f"Current price: {price}")读取私人仪表板
import asyncio
from web_speed_agent import Agent
async def get_dashboard_data():
async with Agent() as agent:
async with agent.browser(session_name="analytics") as browser:
page = await browser.new_page()
# Login (first run only — session persists after)
creds = agent.get_credential("analytics")
if not creds:
agent.store_credential("analytics", "me@company.com", "password")
creds = agent.get_credential("analytics")
await page.goto("https://analytics.company.com/login")
await page.fill('[name="email"]', creds[0])
await page.fill('[name="password"]', creds[1])
await page.click('button[type="submit"]')
await page.wait_for_load_state("networkidle")
# Navigate to dashboard
await page.goto("https://analytics.company.com/dashboard")
await page.wait_for_selector(".metrics-table", timeout=10000)
html = await page.content()
result = await agent.extract(html)
return result
asyncio.run(get_dashboard_data())登录状态下的多页面抓取
import asyncio
from web_speed_agent import Agent
async def scrape_inbox():
async with Agent() as agent:
async with agent.browser(session_name="webmail") as browser:
page = await browser.new_page()
# Login
await page.goto("https://mail.example.com/login")
user, pwd = agent.get_credential("webmail")
await page.fill('[name="username"]', user)
await page.fill('[name="password"]', pwd)
await page.click('[type="submit"]')
await page.wait_for_load_state("networkidle")
# Scrape multiple pages
emails = []
for page_num in range(1, 4):
await page.goto(f"https://mail.example.com/inbox?page={page_num}")
await page.wait_for_load_state("networkidle")
html = await page.content()
result = await agent.extract(html, page_type="listing")
emails.extend(result.get("listing", {}).get("items", []))
return emails
asyncio.run(scrape_inbox())AI 代理集成 (MCP)
随附的 MCP 服务器允许 Claude Desktop、Gemini CLI 和任何兼容 MCP 的代理直接使用该 SDK。代理可以通过自然语言进行登录、导航、点击和提取。
启动 MCP 服务器:
WEBSPEED_API_KEY="wsp_..." python3 agent_mcp_server.py添加到 Claude Desktop (~/Library/Application Support/Claude/claude_desktop_config.json):
{
"mcpServers": {
"web-speed-agent": {
"command": "python3",
"args": ["/path/to/agent_mcp_server.py"],
"env": {
"WEBSPEED_API_KEY": "wsp_..."
}
}
}
}添加到 Gemini CLI (~/.gemini/settings.json):
{
"mcpServers": {
"web-speed-agent": {
"command": "python3.11",
"args": ["/path/to/agent_mcp_server.py"],
"env": {
"WEBSPEED_API_KEY": "wsp_...",
"PYTHONPATH": "/path/to/web-speed-agent"
}
}
}
}然后告诉代理:
"存储我的 united 凭据 — 用户名 me@example.com,密码 mypassword"
"登录 united.com 并帮我查找下周五从 SFO 到 JFK 最便宜的航班"
可用的 MCP 工具:
工具 | 描述 |
| 将登录信息保存到系统钥匙串 |
| 打开浏览器并登录 |
| 在活动会话中访问 URL |
| 从当前页面获取结构化数据 |
| 点击按钮或链接 |
| 在表单字段中输入内容 |
| 提交表单 |
| 结束浏览器会话 |
| 检查 API 额度余额 |
API 参考
Agent
Agent(
api_key: str | None = None,
server_url: str | None = None,
config_dir: str = "~/.webspeed",
headless: bool = True,
)参数 | 描述 |
| Web Speed API 密钥。回退到 |
| 覆盖 API 服务器 URL。默认: |
| 配置、会话和日志目录。默认: |
| 以无头模式运行浏览器。默认: |
agent.browser()
agent.browser(
session_name: str | None = None,
headless: bool | None = None,
proxy: str | None = None,
) -> ManagedBrowser返回一个异步上下文管理器。在代码块内,调用 .new_page() 以获取 Playwright Page。
参数 | 描述 |
| 将 Cookie 持久化到 |
| 为此会话覆盖实例的 |
| 代理 URL,例如 |
会话名称必须是字母数字 + 连字符/下划线,最多 64 个字符。
agent.extract()
await agent.extract(
html: str,
page_type: str = "auto",
) -> dict将 HTML 发送到 Web Speed API。消耗 1 个额度。
参数 | 描述 |
| 原始 HTML 字符串(例如来自 |
|
|
agent.map()
await agent.map(
url: str,
js: bool = False,
) -> dict通过服务器获取并提取公共 URL。无需本地浏览器。消耗 1 个额度。
参数 | 描述 |
| 页面 URL。必须是 |
| 在提取前渲染 JavaScript。 |
agent.account()
await agent.account() -> dict返回:credits(额度)、tier(等级)、status(状态)、lifetime(总计/成功/失败)。
agent.store_credential()
agent.store_credential(
site: str,
username: str,
password: str,
overwrite: bool = False,
) -> None保存到系统钥匙串。如果凭据已存在且 overwrite=False,则引发 CredentialError。
agent.get_credential()
agent.get_credential(site: str) -> tuple[str, str] | None返回 (username, password),如果未找到则返回 None。
agent.delete_credential()
agent.delete_credential(site: str) -> None从钥匙串中删除凭据。
异常
from web_speed_agent import (
WebSpeedError, # Base exception
AuthenticationError, # Invalid/missing API key
InsufficientCreditsError, # No credits remaining
APIError, # API returned 4xx/5xx
RateLimitError, # 429 Too Many Requests
CredentialError, # Keychain error
BrowserError, # Playwright error
NetworkError, # Timeout or DNS failure
PlaywrightNotInstalledError, # Run: playwright install chromium
)from web_speed_agent import Agent, InsufficientCreditsError, NetworkError
try:
result = await agent.extract(html)
except InsufficientCreditsError:
print("Out of credits — top up at getwebspeed.io")
except NetworkError as e:
print(f"Connection failed: {e}")配置
环境变量
变量 | 描述 |
| API 密钥(推荐,优于配置文件) |
| 覆盖服务器 URL(必须是 |
配置文件
~/.webspeed/config.yaml — 首次运行时自动创建。权限设置为 0o600(仅所有者可读写)。
api:
server_url: https://api.getwebspeed.io
timeout: 30
browser:
headless: true会话文件
持久化的浏览器会话存储在 ~/.webspeed/sessions/<name>/storage.json 中。
权限:
0o600(仅所有者可读写)包含:Cookie、localStorage、sessionStorage
可安全删除:代理将在下次运行时重新进行身份验证
安全性
什么会离开您的机器
当您调用 agent.extract(html) 时,页面 HTML 会被发送到 Web Speed API 进行处理。其他所有内容都保留在本地。
数据 | 去向 |
登录凭据 | 永远不会离开您的机器(仅限系统钥匙串) |
浏览器 Cookie / 会话 | 永远不会离开您的机器(本地 Playwright) |
页面 HTML | 通过 HTTPS 发送到 Web Speed API 进行提取 |
提取出的 JSON | 返回给您 |
HTML 清理(默认开启)
在传输任何 HTML 之前,SDK 会在本地自动对其进行清理:
移除内联
<script>和<style>块隐藏具有身份验证相关名称(
csrf、token、nonce、session等)的表单字段,其值会被清空清除敏感的
<meta>内容属性移除 HTML 注释
可见内容(文本、链接、表格、标题、产品数据)保持不变。
# Default: scrubbing is on
result = await agent.extract(html)
# Turn off only if the page has no sensitive data
result = await agent.extract(html, scrub=False)
# Or scrub manually and inspect before sending
from web_speed_agent import scrub
clean_html = scrub(raw_html)
print(clean_html) # inspect what will be sent
result = await agent.extract(clean_html, scrub=False)服务器端数据处理
HTML 仅在内存中处理 — 绝不写入磁盘,绝不记录日志,绝不缓存
身份验证保护页面绝不缓存 — 需要登录的页面被明确排除在共享注册表之外
使用日志仅存储:API 密钥哈希、URL 哈希(或
"sdk-extract")、时间戳和检测到的页面类型 — 不包含内容错误响应中不包含原始 HTML — 异常在返回任何错误之前会被清理
其他保护措施
凭据存储在系统钥匙串中,从不出现在文件中,从不发送到服务器
会话文件以
0o600权限写入(仅所有者可读写)配置目录以
0o700权限创建TLS 始终验证 — 所有 HTTP 调用均设置
verify=True,无法禁用强制 HTTPS —
server_url必须以https://开头,拒绝普通 HTTP路径遍历预防 — 会话名称根据
[a-zA-Z0-9_-]白名单进行验证无凭据记录 — 密码绝不会出现在日志或错误消息中
许可证
GNU 通用公共许可证 v3.0 — 参见 LICENSE。
Web Speed API 的使用受 Web Speed 服务条款约束。
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceReducing token usage by 70% with a deterministic mapping engine. Also links in with the Web Speed Agent SDK and MCP for post-auth agents.10GPL 3.0
- AlicenseNot gradedqualityDmaintenanceMCP Server for AI agent identity and authorization. Create, verify, and manage agent identities with trust scores and scoped authorization tokens.MIT
- AlicenseAqualityAmaintenanceProvides an MCP-native agent browser that enables autonomous agents to perceive and interact with web pages through stealth browsing, identity borrowing, and WAAP detection.9MIT
- AlicenseNot gradedqualityBmaintenanceEnables MCP-capable runtimes to read agent message rooms, sign and post public messages, and create or verify Ed25519 contribution proofs for Technocore.MIT
Related MCP Connectors
Agent-first web hosting: deploy sites, apps, databases and domains over MCP.
Hosted AgentLux MCP server for marketplace, identity, creator, services, and social flows.
MCP Server for agents to onboard, pay, and provision services autonomously with InFlow
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/Dominic-Pi-Sunyer/web-speed-agent'
If you have feedback or need assistance with the MCP directory API, please join our Discord server