Skip to main content
Glama

web-speed-agent

PyPI version Python License: GPL v3

本地浏览器自动化 + 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 工具:

工具

描述

store_credential

将登录信息保存到系统钥匙串

login

打开浏览器并登录

navigate

在活动会话中访问 URL

extract_page

从当前页面获取结构化数据

click

点击按钮或链接

fill_field

在表单字段中输入内容

submit_form

提交表单

close_browser

结束浏览器会话

account_info

检查 API 额度余额


API 参考

Agent

Agent(
    api_key: str | None = None,
    server_url: str | None = None,
    config_dir: str = "~/.webspeed",
    headless: bool = True,
)

参数

描述

api_key

Web Speed API 密钥。回退到 WEBSPEED_API_KEY 环境变量。

server_url

覆盖 API 服务器 URL。默认:https://api.getwebspeed.io

config_dir

配置、会话和日志目录。默认:~/.webspeed

headless

以无头模式运行浏览器。默认:True


agent.browser()

agent.browser(
    session_name: str | None = None,
    headless: bool | None = None,
    proxy: str | None = None,
) -> ManagedBrowser

返回一个异步上下文管理器。在代码块内,调用 .new_page() 以获取 Playwright Page

参数

描述

session_name

将 Cookie 持久化到 ~/.webspeed/sessions/<name>/None = 不持久化。

headless

为此会话覆盖实例的 headless 设置。

proxy

代理 URL,例如 "socks5://localhost:1080"

会话名称必须是字母数字 + 连字符/下划线,最多 64 个字符。


agent.extract()

await agent.extract(
    html: str,
    page_type: str = "auto",
) -> dict

将 HTML 发送到 Web Speed API。消耗 1 个额度。

参数

描述

html

原始 HTML 字符串(例如来自 page.content())。

page_type

"article""product""listing""auto"


agent.map()

await agent.map(
    url: str,
    js: bool = False,
) -> dict

通过服务器获取并提取公共 URL。无需本地浏览器。消耗 1 个额度。

参数

描述

url

页面 URL。必须是 http://https://

js

在提取前渲染 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}")

配置

环境变量

变量

描述

WEBSPEED_API_KEY

API 密钥(推荐,优于配置文件)

WEBSPEED_SERVER_URL

覆盖服务器 URL(必须是 https://

配置文件

~/.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>

  • 隐藏具有身份验证相关名称(csrftokennoncesession 等)的表单字段,其值会被清空

  • 清除敏感的 <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,无法禁用

  • 强制 HTTPSserver_url 必须以 https:// 开头,拒绝普通 HTTP

  • 路径遍历预防 — 会话名称根据 [a-zA-Z0-9_-] 白名单进行验证

  • 无凭据记录 — 密码绝不会出现在日志或错误消息中


许可证

GNU 通用公共许可证 v3.0 — 参见 LICENSE

Web Speed API 的使用受 Web Speed 服务条款约束。

A
license - permissive license
A
quality
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

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

  • A
    license
    A
    quality
    A
    maintenance
    Provides an MCP-native agent browser that enables autonomous agents to perceive and interact with web pages through stealth browsing, identity borrowing, and WAAP detection.
    9
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables MCP-capable runtimes to read agent message rooms, sign and post public messages, and create or verify Ed25519 contribution proofs for Technocore.
    MIT

View all related MCP servers

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

View all MCP Connectors

Latest Blog Posts

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