--- type: reference title: Pi Web Access description: Web search, URL fetching, GitHub cloning, PDF extraction, and video understanding for Pi. Zero-config with Exa MCP. tags: - pi - package - web-search - fetch - youtube - unverified timestamp: 2026-08-28 --- # Pi Web Access **Package:** `pi-web-access` **Version:** 0.22.0 **Author:** Nico Bailon Web search, content extraction, and video understanding for Pi. It calls your self-hosted SearXNG first when one is configured, and falls through to other providers. > **Pi-era setup:** `~/.pi/web-search.json` locked search to SearXNG at `http://192.168.0.143:8081` (dankclaw), permitted LAN fetches via `ssrf.allowRanges`, and set `maxInlineContentChars` to 50000. The config file is cached in memory per process — a changed file takes effect on the next Pi session. --- ## Install ```bash pi install npm:pi-web-access ``` ## Search Providers Provider chain (in priority order, v0.22): 1. **SearXNG** (if configured) — Self-hosted, private search 2. **OpenAI** — Codex subscription or API key 3. **Exa** — Zero-config via MCP, or API key 4. **Brave** — API key 5. **Parallel** — API key 6. **TinyFish** — API key 7. **Search1API** — API key 8. **Searchinfinity** — API key 9. **Querit** — API key 10. **Tavily** — API key 11. **Jina** — API key 12. **SERPdive** — API key 13. **Kagi** — API key 14. **Bocha** — API key 15. **Ollama** — API key 16. **Perplexity** — API key 17. **Gemini API** — API key 18. **Gemini Web** — Browser-cookie access A single-provider field (`provider` or `searchProvider`) pins the default and takes precedence over `searchRouting`. `searchRouting.providers` plus `fallbackOn` define an explicit ordered fallback over typed failures (`transient`, `quota`, `network`, `invalid-response`). ## Configuration **Location:** `~/.pi/web-search.json` ```json { "searxngBaseUrl": "http://192.168.0.143:8081", "searchProvider": "searxng", "maxInlineContentChars": 50000, "workflow": "none", "ssrf": { "allowRanges": ["192.168.0.0/24"] }, "openaiApiKey": "sk-...", "braveApiKey": "BSA_...", "exaApiKey": "exa-...", "perplexityApiKey": "pplx-...", "geminiApiKey": "AIza..." } ``` Key fields: - `searxngBaseUrl` — the SearXNG instance to call. Env `SEARXNG_BASE_URL` wins over this file. The client calls `GET {base}/search?q=...&format=json` with a 30 s timeout; the base URL and its redirects stay subject to the SSRF guard. - `searchProvider` — `searxng` locks the primary provider. `auto` picks the first available. A single-provider field wins over `searchRouting`. - `maxInlineContentChars` — size of each `fetch_content` / `get_search_content` content slice. Default 30000, cap 200000. Full fetched content stays stored for later retrieval. - `ssrf.allowRanges` — LAN CIDR ranges allowed through `fetch_content`. This blocks private IPs by default. - `workflow` — `none` (raw results, no browser), `summary-review` (curator window with summary draft), or `auto-summary`. ## Capabilities ### Web Search ```typescript web_search({ query: "TypeScript best practices 2025" }) ``` ### URL Fetching ```typescript fetch_content({ url: "https://docs.example.com/guide" }) ``` ### GitHub Cloning GitHub URLs are cloned locally. The agent gets real file contents, not rendered HTML. ```typescript fetch_content({ url: "https://github.com/owner/repo" }) ``` ### Video Understanding Point at a YouTube video or local screen recording and ask questions about visual content. ```typescript // YouTube fetch_content({ url: "https://youtube.com/watch?v=...", prompt: "What book is shown?" }) // Local video fetch_content({ url: "/path/to/recording.mp4" }) ``` ### PDF Extraction ```typescript fetch_content({ url: "https://example.com/paper.pdf" }) ``` ## Optional Dependencies ```bash # Video frame extraction sudo pacman -S ffmpeg yt-dlp ``` Without these, video analysis (transcripts, visual descriptions via Gemini) still works. Frame extraction requires ffmpeg and yt-dlp. Both are installed on the workstation (verified 2026-08-28: ffmpeg n9.0.1, yt-dlp 2026.08.19). GitHub URLs get special handling: `fetch_content` clones the repo locally instead of scraping HTML (root URL returns tree + README, `/blob/` returns file contents). Repos over 350 MB get an API-based view; `forceClone: true` overrides. Clones cache per session under `/tmp/pi-github-repos` and wipe on session change. Private repos need the `gh` CLI. Disable with `githubClone.enabled: false`. ## See Also - [Pi Packages](index.md) — Package overview - [Pi Configuration](../index.md) — Pi configuration