npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@danypops/pi-web-spider

v0.25.1

Published

Pi extension for web_fetch, web_search, and live browser sessions: 7 search providers (Brave, Brave LLM Context, Tavily, Exa, Serper, SerpApi, You.com) with automatic fallback, robots.txt-respecting crawl, GitHub/Wikipedia/llms.txt-aware fetching, and a d

Readme

@danypops/pi-web-spider

npm version license: MIT

Web fetch, web search, and real browser sessions for Pi — an agent-ready alternative to raw HTML scraping.

Why Web Spider

  • Zero-config search — works with no API key via a bounded keyless fallback (Firecrawl); configure any of 7 keyed providers (Brave, Brave LLM Context, Tavily, Exa, Serper, SerpApi, You.com) for higher limits, with automatic round-robin quota-spreading and fallback once you do.
  • Honest PDF extraction — bounded text-layer extraction with an automatic OCR fallback for scanned or garbled pages. A page that genuinely can't be recovered reports contentOk: false, never a false-success claim.
  • Real structured extraction, not scraping — GitHub (REST/GraphQL), MediaWiki (Wikipedia and any MediaWiki wiki), llms.txt, and .md-suffix docs (AWS-docs-style) are queried through their actual APIs.
  • A disk-backed page cache that survives restarts — every fetch is cached to SQLite (WAL) and searchable by full text, domain, tag, curated category, or date range, at zero network cost on a hit.
  • Real interactive browser sessionsweb_session for pages a single fetch can't handle: type, click, select, wait on async results, read tables, screenshot, handle native dialogs, capture downloads, or open a headed browser so a human can complete CAPTCHA/login/consent before the agent resumes the same session.
  • A standalone resource finder, not just a summarizerweb_quotes returns ranked, verbatim quotes per URL with a copy-pasteable citation link, never an LLM-digested answer.
pi install npm:@danypops/pi-web-spider

Quick Start

// Fetch a page as clean markdown
web_fetch({ url: "https://example.com/docs/getting-started" })

// Crawl one hop of same-domain links
web_fetch({ url: "https://example.com", depth: 1 })

// Search the web instead of fetching a URL
web_fetch({ searchQuery: "readability extraction library comparison" })

// Query everything already cached, no network call
web_fetch({ query: "readability extraction", domain: "github.com" })

// Open an interactive browser session for a page that needs real input
web_session({ operation: "create", name: "research" })

// Deep research: find sources, then pull exact quotes from them
web_fetch({ searchQuery: "precision time protocol clock synchronization" })
web_quotes({ query: "clock synchronization accuracy", urls: ["https://example.com/ptp-overview"] })

See docs/web-fetch-api.md for the full parameter/output reference behind these examples.

Tools

web_fetch

Fetch a URL, crawl N hops deep, or search the web — one tool, three modes:

  • Fetch: url → clean markdown, lean outline, link list, BM25F highlights, or a semantic tree. JSON/text is normalized, while PDFs get bounded text-layer extraction with pdfPageStart/pdfPageEnd (1-based, inclusive, maximum 50 pages). Empty/garbled pages get an automatic, bounded OCR fallback; a page it still can't recover reports contentOk: false honestly rather than implying success.
  • Crawl: url + depth → BFS crawl same-domain links, robots.txt-respecting and per-domain throttled, with an explicit audited ignoreRobots opt-out for a human-directed one-off.
  • Search: searchQuery instead of url → real ranked results instead of a guessed slug. Routes across whichever of Brave, Brave LLM Context, Tavily, Exa, Serper, SerpApi, and You.com you've configured, round-robining for quota spread and falling back automatically on a rate limit or empty result.
  • Cache query: omit url entirely → full-text search or filter (domain, tag, curated category, date range) over every page already fetched, disk-backed, survives restarts, zero network cost.

Structured extraction beats generic scraping where a real API exists: GitHub (REST/GraphQL), MediaWiki (Wikipedia and any MediaWiki wiki), llms.txt, and .md-suffix docs (AWS-docs-style) are recognized and queried directly.

web_session

Persistent, named browser sessions for pages that need real interaction, not a single fetch: type into search boxes, select dropdowns, wait on async results, read a table. Supports navigate/click/hover/type/select/waitFor, structured extraction (queryText/readTable), accessibility-tree snapshots, screenshots, native dialog handling, file downloads, tab management, and console/network capture. Create with headed: true (and preferably forceChromeChannel: true for anti-bot-sensitive sites) to hand a visible browser to the user for CAPTCHA/login/consent, then resume agent actions on that same cookie-bearing session.

web_category

Your own curated relevance categories over cached pages (e.g. "Code", "PTP Protocol") — distinct from a page's domain or its publisher's own tags. A page can belong to more than one category; assign, remove, rename, or list.

web_quotes

A standalone resource finder: given a query and an explicit list of URLs (typically a prior web_fetch(searchQuery=...) call's own results), fetches each one and returns ranked, verbatim BM25F quotes per URL as resource cards — never an LLM-digested summary. Every quote carries a citationUrl, a real URL Text Fragment (#:~:text=...) that scrolls to and highlights the exact quoted passage in any modern browser. maxQuotesPerUrl/maxQuotesTotal bound the per-source and combined result; a URL that fails to fetch becomes its own { url, error } card instead of failing the whole batch.

Architecture

Web Spider architecture: Pi → pi-web-spider thin client → authenticated loopback daemon → operation registry → web-spider core library (SQLite cache, HTTP client, PDF+OCR, search providers)

A supervised daemon (@danypops/web-spider-daemon) owns the SQLite page cache and every network fetch, crawl, throttle, and robots.txt check. This extension is a thin authenticated client — it never touches the network or a cache file directly, and auto-starts the daemon transparently on first use.

pi web_fetch / web_session / web_category / web_quotes
      ↓
this extension (thin client)
      ↓
authenticated loopback daemon → web-spider-daemon
      ↓
SQLite (WAL) cache · fetch/PDF/crawl/search execution · optional Papyrus ingestion

Configuring search

Search works without configuration through Firecrawl's bounded keyless fallback. For higher and more predictable limits, set a provider API key as an environment variable (BRAVE_SEARCH_API_KEY, TAVILY_API_KEY, EXA_API_KEY, SERPER_API_KEY, SERPAPI_API_KEY, YOU_API_KEY) or store it locally:

web-spider search-key set brave

Configured providers are tried before keyless Firecrawl; configuring more than one gets automatic round-robin quota spreading plus fallback — no code changes, just more keys.

Running as a service

The daemon auto-starts on first tool call. For persistence across reboots/logins (and to forward search keys into a systemd --user unit, which does not inherit the installing shell's environment):

web-spider service install

Learn more

Security

This extension executes with full system access, like any Pi extension. Review the source before installing.