{
  "markdown": "# browsegrab\n\n> [한국어 문서](README.ko.md) · [llms.txt](llms.txt)\n\n> Token-efficient browser agent for local LLMs — Playwright + accessibility tree + MarkGrab, MCP native.\n\n**browsegrab** is a lightweight browser automation library designed for local LLMs (8B-35B parameters). It combines Playwright's accessibility tree with [MarkGrab](https://github.com/QuartzUnit/markgrab)'s HTML-to-markdown conversion to achieve **5-8x fewer tokens per step** compared to alternatives like browser-use.\n\n## Features\n\n- **Token-efficient**: ~500-1,500 tokens/step (vs 4,000-10,000 for browser-use)\n- **Local LLM first**: Optimized for vLLM, Ollama, and OpenAI-compatible endpoints\n- **MCP native**: Built-in MCP server with 8 browser automation tools\n- **MarkGrab integration**: HTML → clean markdown for content extraction\n- **Accessibility tree + ref system**: Stable element references (`e1`, `e2`, ...) without vision models\n- **Success pattern caching**: Zero LLM calls on repeated workflows\n- **5-stage JSON parser**: Robust action parsing for local LLM outputs\n- **Minimal dependencies**: Only `playwright` + `httpx` in core\n\n## Installation\n\n```bash\npip install browsegrab\nplaywright install chromium\n```\n\nWith optional features:\n\n```bash\npip install browsegrab[mcp]      # MCP server support\npip install browsegrab[content]  # MarkGrab content extraction\npip install browsegrab[cli]      # CLI with rich output\npip install browsegrab[all]      # Everything\n```\n\n## Quick Start\n\n### Python API\n\n```python\nfrom browsegrab import BrowseSession\n\nasync with BrowseSession() as session:\n    # Navigate and get accessibility tree snapshot\n    await session.navigate(\"https://example.com\")\n    snap = await session.snapshot()\n    print(snap.tree_text)\n    # - heading \"Example Domain\" [level=1]\n    # - link \"Learn more\": [ref=e1]\n\n    # Click using ref ID\n    result = await session.click(\"e1\")\n    print(result.url)  # https://www.iana.org/help/example-domains\n\n    # Type into search box\n    await session.navigate(\"https://en.wikipedia.org\")\n    snap = await session.snapshot()\n    await session.type(\"e4\", \"Python programming\", submit=True)\n\n    # Extract compressed content (AX tree + markdown)\n    content = await session.extract_content()\n```\n\n### CLI\n\n```bash\n# Accessibility tree snapshot\nbrowsegrab snapshot https://example.com\n\n# JSON output\nbrowsegrab snapshot https://example.com -f json\n\n# Extract content (AX tree + markdown)\nbrowsegrab extract https://en.wikipedia.org/wiki/Python\n\n# Agentic browse (requires LLM endpoint)\nbrowsegrab browse https://example.com \"Find the about page\"\n```\n\n### MCP Server\n\n```bash\nbrowsegrab-mcp  # Start MCP server (stdio)\n```\n\nClaude Desktop / Cursor / VS Code config:\n\n```json\n{\n  \"mcpServers\": {\n    \"browsegrab\": {\n      \"command\": \"browsegrab-mcp\"\n    }\n  }\n}\n```\n\n**8 MCP tools**: `browser_navigate`, `browser_click`, `browser_type`, `browser_snapshot`, `browser_scroll`, `browser_extract_content`, `browser_go_back`, `browser_wait`\n\n## How It Works\n\n### Agent Browse Loop\n\n```mermaid\nflowchart LR\n    A[\"🌐 URL + Goal\"] --> B[\"Navigate\"]\n    B --> C[\"AX Tree Snapshot\\n~200–500 tokens\"]\n    C --> D{\"LLM\\nDecision\"}\n    D -->|\"click / type / scroll\"| E[\"Execute Action\"]\n    E --> C\n    D -->|\"goal reached\"| F[\"Extract Content\\n(MarkGrab)\"]\n    F --> G[\"✅ Result\"]\n```\n\n### Token Efficiency\n\nbrowsegrab separates **structure** (accessibility tree) from **content** (MarkGrab markdown), sending only what the LLM needs:\n\n```mermaid\nflowchart TD\n    A[\"Raw HTML\"] --> B[\"Accessibility Tree\"]\n    A --> C[\"MarkGrab Markdown\"]\n    B --> D[\"Structure: ~200–500 tokens\\nInteractive elements with ref IDs\"]\n    C --> E[\"Content: ~300–800 tokens\\nClean markdown · on-demand\"]\n    D --> F[\"Combined: ~500–1,300 tokens/step\\n⚡ 5–8× fewer than browser-use\"]\n    E --> F\n```\n\n### Token efficiency (measured)\n\n| Page | Interactive elements | Tokens | browser-use equivalent |\n|------|---------------------|--------|----------------------|\n| example.com | 1 | ~60 | ~500+ |\n| Wikipedia article | 452 | ~1,254 | ~10,000+ |\n\n## Architecture\n\n```\nbrowsegrab/\n├── config.py                 # Dataclass configs (env var loading)\n├── result.py                 # Result types (ActionResult, BrowseResult, ...)\n├── session.py                # BrowseSession orchestrator\n├── browser/\n│   ├── manager.py            # Playwright lifecycle (async context manager)\n│   ├── snapshot.py           # Accessibility tree + ref system\n│   ├── selectors.py          # 4-strategy selector resolver\n│   └── actions.py            # navigate, click, type, scroll, go_back, wait\n├── dom/\n│   ├── ref_map.py            # ref ID ↔ element bidirectional mapping\n│   └── compress.py           # AX tree + MarkGrab → compressed context\n├── llm/\n│   ├── base.py               # LLMProvider ABC\n│   ├── provider.py           # vLLM, Ollama, OpenAI-compatible\n│   ├── prompt.py             # System prompts (~400 tokens)\n│   └── parse.py              # 5-stage JSON fallback parser\n├── agent/\n│   ├── history.py            # Sliding window history compression\n│   ├── cache.py              # Domain-based success pattern cache\n│   └── loop_guard.py         # Duplicate action detection\n├── __main__.py               # CLI (click)\n└── mcp_server.py             # FastMCP server (8 tools)\n```\n\n## Configuration\n\nAll settings via environment variables (`BROWSEGRAB_*` prefix):\n\n```bash\n# Browser\nBROWSEGRAB_BROWSER_HEADLESS=true\nBROWSEGRAB_BROWSER_TIMEOUT_MS=30000\n\n# LLM (for agentic browse)\nBROWSEGRAB_LLM_PROVIDER=vllm          # vllm | ollama | openai\nBROWSEGRAB_LLM_BASE_URL=http://localhost:8000/v1\nBROWSEGRAB_LLM_MODEL=Qwen/Qwen3.5-32B-AWQ\n\n# Agent\nBROWSEGRAB_AGENT_MAX_STEPS=10\nBROWSEGRAB_AGENT_ENABLE_CACHE=true\n```\n\n## Part of the QuartzUnit Ecosystem\n\n| Library | Role |\n|---------|------|\n| [markgrab](https://github.com/QuartzUnit/markgrab) | Passive extraction (URL → markdown) |\n| [snapgrab](https://github.com/QuartzUnit/snapgrab) | Passive capture (URL → screenshot) |\n| [docpick](https://github.com/QuartzUnit/docpick) | Document OCR → structured JSON |\n| **browsegrab** | Active automation (goal → browser actions → results) |\n\n## Development\n\n```bash\ngit clone https://github.com/QuartzUnit/browsegrab.git\ncd browsegrab\npython -m venv .venv && source .venv/bin/activate\npip install -e \".[dev]\"\nplaywright install chromium\n\n# Unit tests (no browser needed)\npytest tests/ -m \"not e2e\"\n\n# Full suite including E2E\npytest tests/ -v\n```\n\n## License\n\n[MIT](LICENSE)\n\n<!-- mcp-name: io.github.QuartzUnit/browsegrab -->\n\n\n---\n\n<sub>Part of the [QuartzUnit](https://github.com/QuartzUnit) ecosystem — composable Python libraries for data collection, extraction, search, and AI agent safety.</sub>\n",
  "bytes": 6700,
  "sha": "cbc318fe0412aee00af1464dccd638932821e7ea61e8ff0cb2ed9973a18d7fe9",
  "repo_slug": "quartzunit/browsegrab",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_arknill_browsegrab_4d0b8038/readme"
}