bb-browser (BadBoy Browser)

repository·main·Indexed 27 days ago

https://github.com/epiral/bb-browser

A CLI tool and MCP server that turns a Chrome browser into an API for AI agents. It allows machines to use human interfaces and existing login states to access websites, bypassing anti-bot measures. Features include site-specific adapters, full browser automation (click, fill, eval, snapshot), network traffic capture, and a daemon for routing commands via HTTP API.

Tokens
23.3K
Snippets
38
Records
171
Agent score
91%

What's inside bb-browser

  1. Understand bb-browser data privacy and local communication

    main
    bb-browser is designed for local-only operation. All communication between the AI Agent, the CLI/MCP server, the local HTTP daemon, and the Chrome extension occurs exclusively on your machine via localhost. No data, telemetry, or analytics are sent to external servers or third parties.
  2. Run bb-browser site commands with --openclaw

    main

    Every bb-browser site command MUST include the --openclaw flag. This ensures the command runs through OpenClaw's browser, allowing it to use your existing login state and avoiding the need for a separate Chrome extension or daemon.

    If you omit --openclaw, the command will fail or require a separate Chrome extension.

    # Correct usage
    bb-browser site twitter/search "AI agent" --openclaw
    bb-browser site zhihu/hot 10 --openclaw --json
    
    # Wrong (requires separate Chrome extension)
    bb-browser site twitter/search "AI agent"
  3. Use bb-browser with OpenClaw

    main

    If you use OpenClaw, you can run bb-browser directly through its built-in browser without installing extra Chrome extensions or a daemon by using the --openclaw flag.

    bb-browser site reddit/hot --openclaw
    bb-browser site xueqiu/hot-stock 5 --openclaw --jq '.items[] | {name, changePercent}'
  4. Integrate bb-browser with MCP (Claude Code / Cursor)

    main

    You can connect bb-browser to AI coding agents like Claude Code or Cursor using the Model Context Protocol (MCP) by adding the following configuration to your MCP settings:

    {
      "mcpServers": {
        "bb-browser": {
          "command": "npx",
          "args": ["-y", "bb-browser", "--mcp"]
        }
      }
    }
  5. Use the Site System to call website APIs via CLI

    main

    The Site system uses adapters to turn website features into CLI commands. It automatically handles tab management (finding existing tabs or creating new ones) and detects login errors.

    # List all available adapters
    bb-browser site list
    
    # Search for an adapter
    bb-browser site search <query>
    
    # Run an adapter (syntax: bb-browser site <name> [args...])
    bb-browser site twitter/search "Claude Code"
    bb-browser site zhihu/hot
    bb-browser site github/repo owner/repo
    bb-browser site youtube/transcript <video_id>
    
    # Update community adapters
    bb-browser site update
  6. Configure bb-browser as an MCP server

    main

    To use bb-browser with AI agents like Claude Code or Cursor, add it as an MCP (Model Context Protocol) server in your configuration file.

    {
      "mcpServers": {
        "bb-browser": {
          "command": "npx",
          "args": ["-y", "bb-browser", "--mcp"]
        }
      }
    }
  7. Extract structured data using --jq

    main

    You can use the --jq flag to filter and extract specific fields from the JSON output returned by adapters. When using --jq, the --json flag is implied and does not need to be explicitly provided.

    # Just stock names
    bb-browser site xueqiu/hot-stock 5 --openclaw --jq '.items[].name'
    
    # Specific fields as objects
    bb-browser site xueqiu/hot-stock 5 --openclaw --jq '.items[] | {name, changePercent, heat}'
    
    # Filter results
    bb-browser site reddit/hot --openclaw --jq '.posts[] | {title, score}'
  8. Use the fetch command to execute requests with browser context

    main

    The fetch command allows you to execute fetch() calls within the browser context. This is essentially a version of curl that automatically carries cookies and existing login states from the browser.

    Automatic Domain Routing:

    • Relative paths (e.g., /api/me.json): Uses the origin of the currently active tab.
    • Absolute paths (e.g., https://www.reddit.com/...): Searches for an existing tab with a matching domain. If none is found, it automatically opens a new tab and waits 3 seconds before executing the fetch in that new tab's context.

    Response Handling:

    • JSON responses are automatically parsed into objects.
    • Non-JSON responses are returned as text.
    • Using --output automatically formats and writes the response to the specified file.
  9. Manage and run website adapters via the Site system

    main

    The Site system turns websites into CLI APIs using adapters. Each adapter is a JS file that executes in a real browser, reusing your login session and returning structured JSON.

    Core Commands

    • List adapters: bb-browser site list (groups by platform)
    • Search adapters: bb-browser site search <query> (matches name, description, or domain)
    • Run adapter (shorthand): bb-browser site <name> [args...]
    • Run adapter (explicit): bb-browser site run <name> [args...]
    • Update community adapters: bb-browser site update (pulls from github.com/epiral/bb-sites)
    • View development guide: bb-browser guide
  10. Implement Webpack module discovery (Anti-change Pattern 2)

    main

    For Single Page Applications (SPAs) like Twitter/X where Webpack module IDs change frequently, do not hardcode IDs. Instead, dynamically find modules by searching for stable code signatures or operationName in GraphQL queries.

    // 1. Get webpack require
    let __webpack_require__;
    const chunkId = '__bb_' + Date.now();
    window.webpackChunk_twitter_responsive_web.push(
      [[chunkId], {}, (req) => { __webpack_require__ = req; }]
    );
    
    // 2. Find module by signature (e.g., finding a transaction generator)
    let genTxId;
    for (const id of Object.keys(__webpack_require__.m)) {
      const src = __webpack_require__.m[id].toString();
      if (src.includes('jf.x.com') && src.includes('jJ:')) {
        genTxId = __webpack_require__(id).jJ;
        break;
      }
    }
    
    // 3. Find GraphQL queryId by operationName
    let queryId;
    for (const id of Object.keys(__webpack_require__.m)) {
      const src = __webpack_require__.m[id].toString();
      const m = src.match(/queryId:"([^" ]+)",operationName:"CreateTweet"/);
      if (m) { queryId = m[1]; break; }
    }
  11. Best practices for managing Ref lifecycle

    main

    To avoid Ref not found errors, follow these patterns:

    1. Always Snapshot before acting: Never assume a ref exists without a fresh snapshot.
    2. Re-snapshot after navigation: If a click causes a page jump or form submission, run bb-browser snapshot -i again.
    3. Re-snapshot after dynamic changes: If an action opens a menu or dropdown, run bb-browser snapshot -i to get the new elements' refs.
    4. Wait for loading: If an action triggers AJAX, use bb-browser wait <ms> before snapshotting.
    # Correct pattern for AJAX/Dynamic content
    bb-browser click @3
    bb-browser wait 1000
    bb-browser snapshot -i