Skip to main content
Glama

web-speed-agent

PyPI version Python License: GPL v3

Lokale Browser-Automatisierung + Web Speed API Integration für authentifizierte Web-Extraktion.

Setzen Sie einen KI-Agenten auf eine beliebige Website an – auch auf solche, die einen Login erfordern – und erhalten Sie saubere, strukturierte Daten zurück. Anmeldedaten bleiben auf Ihrem Rechner. Nur die extrahierte HTML wird an den Server gesendet.

pip install web-speed-agent
playwright install chromium

Möchten Sie dies mit Claude, Gemini oder anderen KI-Clients verwenden?

Schauen Sie sich das MCP Server Installationshandbuch an – es ist der einfachste Weg, KI-Agenten über natürliche Sprache einloggen und Daten extrahieren zu lassen.


Funktionsweise

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

Anmeldedaten verlassen niemals Ihren Rechner. Der Server sieht nur HTML.


Related MCP server: Agent Identity MCP Server

Schnellstart

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())

Holen Sie sich einen API-Schlüssel unter getwebspeed.io.


Installation

Voraussetzungen: Python 3.10+, ein Web Speed API-Schlüssel

pip install web-speed-agent
playwright install chromium
export WEBSPEED_API_KEY="wsp_..."

Kernkonzepte

Agent

Die Hauptklasse. Verwaltet Anmeldedaten, Browsersitzungen und API-Aufrufe.

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:
    ...

Extrahieren öffentlicher Seiten

Kein Browser erforderlich für Seiten, die keinen Login erfordern:

# 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)

Extrahieren authentifizierter Seiten

Verwenden Sie eine lokale Browsersitzung. Der Browser läuft auf Ihrem Rechner:

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)

Der session_name speichert Cookies dauerhaft unter ~/.webspeed/sessions/<name>/, sodass nachfolgende Ausführungen den Login-Schritt überspringen.


Verwaltung von Anmeldedaten

Anmeldedaten werden in Ihrem System-Schlüsselbund gespeichert (macOS Keychain, Windows Credential Manager, Linux secret-tool). Sie werden niemals an Web Speed-Server gesendet.

# Store once
agent.store_credential("mysite", "me@example.com", "mypassword")

# Retrieve anywhere
username, password = agent.get_credential("mysite")

# Remove
agent.delete_credential("mysite")

Extraktionsergebnis

Der Server gibt seitentyp-bewusste strukturierte Daten zurück:

# 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"

Alle Ergebnisse enthalten engine: "advanced" – 60–85 % effizienter bei der Token-Nutzung als rohes HTML.


Beispiele

Preisüberwachung

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}")

Ein privates Dashboard lesen

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())

Mehrseitiges Scrapen während des Logins

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())

KI-Agenten-Integration (MCP)

Der enthaltene MCP-Server ermöglicht es Claude Desktop, Gemini CLI und jedem MCP-kompatiblen Agenten, das SDK direkt zu nutzen. Der Agent kann sich einloggen, navigieren, klicken und extrahieren – alles durch natürliche Sprache.

Starten Sie den MCP-Server:

WEBSPEED_API_KEY="wsp_..." python3 agent_mcp_server.py

Zu Claude Desktop hinzufügen (~/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_..."
      }
    }
  }
}

Zu Gemini CLI hinzufügen (~/.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"
      }
    }
  }
}

Sagen Sie dann dem Agenten:

"Speichere meine Anmeldedaten für united – Benutzername me@example.com, Passwort meinpasswort"

"Logge dich bei united.com ein und finde mir den günstigsten Flug von SFO nach JFK am nächsten Freitag"

Verfügbare MCP-Tools:

Tool

Beschreibung

store_credential

Login im System-Schlüsselbund speichern

login

Browser öffnen + anmelden

navigate

URL in der aktiven Sitzung aufrufen

extract_page

Strukturierte Daten von der aktuellen Seite abrufen

click

Auf eine Schaltfläche oder einen Link klicken

fill_field

In ein Formularfeld schreiben

submit_form

Ein Formular absenden

close_browser

Browsersitzung beenden

account_info

API-Guthaben prüfen


API-Referenz

Agent

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

Parameter

Beschreibung

api_key

Web Speed API-Schlüssel. Greift auf die Umgebungsvariable WEBSPEED_API_KEY zurück.

server_url

API-Server-URL überschreiben. Standard: https://api.getwebspeed.io.

config_dir

Verzeichnis für Konfiguration, Sitzungen und Protokolle. Standard: ~/.webspeed.

headless

Browser im Headless-Modus ausführen. Standard: True.


agent.browser()

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

Gibt einen asynchronen Kontext-Manager zurück. Rufen Sie innerhalb des Blocks .new_page() auf, um eine Playwright-Page zu erhalten.

Parameter

Beschreibung

session_name

Cookies unter ~/.webspeed/sessions/<name>/ speichern. None = keine Persistenz.

headless

Instanz-headless für diese Sitzung überschreiben.

proxy

Proxy-URL, z. B. "socks5://localhost:1080".

Sitzungsnamen müssen alphanumerisch sein + Bindestriche/Unterstriche, maximal 64 Zeichen.


agent.extract()

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

Sendet HTML an die Web Speed API. Kostet 1 Credit.

Parameter

Beschreibung

html

Roher HTML-String (z. B. von page.content()).

page_type

"article", "product", "listing" oder "auto".


agent.map()

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

Ruft eine öffentliche URL über den Server ab und extrahiert sie. Kein lokaler Browser erforderlich. Kostet 1 Credit.

Parameter

Beschreibung

url

Seiten-URL. Muss http:// oder https:// sein.

js

JavaScript vor der Extraktion rendern.


agent.account()

await agent.account() -> dict

Gibt zurück: credits, tier, status, lifetime (gesamt/Treffer/Fehlschläge).


agent.store_credential()

agent.store_credential(
    site: str,
    username: str,
    password: str,
    overwrite: bool = False,
) -> None

Speichert im System-Schlüsselbund. Löst CredentialError aus, wenn Anmeldedaten existieren und overwrite=False.


agent.get_credential()

agent.get_credential(site: str) -> tuple[str, str] | None

Gibt (username, password) zurück oder None, falls nicht gefunden.


agent.delete_credential()

agent.delete_credential(site: str) -> None

Entfernt Anmeldedaten aus dem Schlüsselbund.


Ausnahmen

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}")

Konfiguration

Umgebungsvariablen

Variable

Beschreibung

WEBSPEED_API_KEY

API-Schlüssel (empfohlen gegenüber Konfigurationsdatei)

WEBSPEED_SERVER_URL

Server-URL überschreiben (muss https:// sein)

Konfigurationsdatei

~/.webspeed/config.yaml – wird beim ersten Start automatisch erstellt. Berechtigungen auf 0o600 gesetzt (nur Besitzer).

api:
  server_url: https://api.getwebspeed.io
  timeout: 30

browser:
  headless: true

Sitzungsdateien

Persistente Browsersitzungen werden unter ~/.webspeed/sessions/<name>/storage.json gespeichert.

  • Berechtigungen: 0o600 (nur Besitzer)

  • Enthält: Cookies, localStorage, sessionStorage

  • Sicher zu löschen: Der Agent authentifiziert sich beim nächsten Lauf erneut


Sicherheit

Was Ihren Rechner verlässt

Wenn Sie agent.extract(html) aufrufen, wird das Seiten-HTML zur Verarbeitung an die Web Speed API gesendet. Alles andere bleibt lokal.

Daten

Wohin sie gehen

Anmeldedaten

Verlassen niemals Ihren Rechner (nur System-Schlüsselbund)

Browser-Cookies / Sitzung

Verlassen niemals Ihren Rechner (lokales Playwright)

Seiten-HTML

Über HTTPS an Web Speed API zur Extraktion gesendet

Extrahiertes JSON

An Sie zurückgegeben

HTML-Bereinigung (standardmäßig aktiviert)

Bevor HTML übertragen wird, bereinigt das SDK es automatisch lokal:

  • Inline-<script>- und <style>-Blöcke entfernt

  • Versteckte Formularfelder mit auth-bezogenen Namen (csrf, token, nonce, session usw.) werden geleert

  • Sensible <meta>-Inhaltsattribute gelöscht

  • HTML-Kommentare entfernt

Sichtbare Inhalte – Text, Links, Tabellen, Überschriften, Produktdaten – bleiben unberührt.

# 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)

Serverseitige Datenverarbeitung

  • HTML wird nur im Arbeitsspeicher verarbeitet – niemals auf die Festplatte geschrieben, niemals protokolliert, niemals zwischengespeichert

  • Auth-geschützte Seiten werden niemals zwischengespeichert – Seiten, die einen Login erfordern, sind explizit vom gemeinsamen Register ausgeschlossen

  • Nutzungsprotokolle speichern nur: einen Hash Ihres API-Schlüssels, einen Hash der URL (oder "sdk-extract"), Zeitstempel und erkannten Seitentyp – keine Inhalte

  • Kein rohes HTML in Fehlerantworten – Ausnahmen werden bereinigt, bevor ein Fehler zurückgegeben wird

Weitere Schutzmaßnahmen

  • Anmeldedaten werden im System-Schlüsselbund gespeichert, niemals in Dateien, niemals an Server gesendet

  • Sitzungsdateien werden mit 0o600-Berechtigungen geschrieben (nur Besitzer lesen/schreiben)

  • Konfigurationsverzeichnis mit 0o700-Berechtigungen erstellt

  • TLS immer verifiziertverify=True bei allen HTTP-Aufrufen, kann nicht deaktiviert werden

  • HTTPS erzwungenserver_url muss mit https:// beginnen, einfaches HTTP wird abgelehnt

  • Pfad-Traversal-Prävention – Sitzungsnamen gegen [a-zA-Z0-9_-]-Whitelist validiert

  • Keine Protokollierung von Anmeldedaten – Passwörter erscheinen niemals in Protokollen oder Fehlermeldungen


Lizenz

GNU General Public License v3.0 – siehe LICENSE.

Die Nutzung der Web Speed API unterliegt den Web Speed Nutzungsbedingungen.

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