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

@pixu1980/pi-web

v0.1.6

Published

Scrape any webpage into clean, context-ready Markdown for pi.dev - fetch URLs, get readable Markdown with title/source metadata, and pull extra slices on demand

Readme

pi-web

Scrape any webpage into clean, context-ready Markdown for pi.dev. Fetch one or more URLs, get readable Markdown with title/source metadata, and pull the rest of a long page in bounded slices - everything you need to drop web content straight into the conversation context.

Inspiration: this package is inspired by pi-web-access by Nicolás Bailon and uses the same extraction stack it popularized (@mozilla/readability + turndown + linkedom). pi-web focuses on the fetch → Markdown part only and intentionally drops the search-result "curator" browser UI: a scraper is synchronous and deterministic (ask for a page, get the page), so an interactive curation layer adds friction instead of value. Web search stays covered by pi-web-access / the built-in search tools.

Install

pi install npm:@pixu1980/pi-web

Tools

pi_web_fetch - URL(s) → Markdown

Fetches one or more URLs, extracts the readable content with Readability, and converts it to Markdown with Turndown. The output is a Markdown document ready to drop into context:

# The Readable Title

> Source: https://example.com/article · Fetched: 2025-08-01T12:34:56.789Z · 45210 chars

First paragraph with meaningful content.
...
---
[Showing 12000 of 45210 chars. Use pi_web_read({ id: "lxt3k...", offset: 12000 }) to read the next slice.]

Parameters:

| Param | Description | |-------|-------------| | url / urls | Single URL or array of URLs (fetched in parallel, concurrency-capped) | | raw | Skip Readability and convert the whole page body - keeps tables and code blocks. Useful for docs/API pages. | | maxChars | Max chars of Markdown returned inline (default 12000) | | timeoutMs | Per-request timeout (default 30000) |

pi_web_read - bounded slices

Pages are cached in memory (and restored from the session on reload). Pass the id from a pi_web_fetch result plus an offset to read the next chunk:

pi_web_read({ id: "lxt3k...", offset: 12000, limit: 12000 })

How it works

  1. pi_web_fetch validates the URL (http/https only), then runs an SSRF guard: private, loopback, link-local and reserved addresses are blocked by default, and redirects are re-validated on every hop.
  2. The response is streamed with a hard byte cap and a timeout.
  3. HTML is parsed with linkedom, the article is extracted with Readability, and Turndown converts it to Markdown. If Readability finds no article (SPA shell, weird markup) it falls back to the whole body and flags the result as low-quality instead of returning nothing.
  4. The page is stored with an id and returned inline (truncated with a slice hint).

Configuration (optional)

Create ~/.pi/pi-web.json:

{
  "userAgent": "my-custom-agent/1.0",
  "timeoutMs": 30000,
  "maxResponseBytes": 2097152,
  "maxChars": 12000,
  "concurrency": 3,
  "allowRanges": ["127.0.0.1", "::1"]
}

allowRanges is the SSRF allowlist - add private/loopback ranges (CIDR or literal IPs) to permit local development servers.

Security

  • SSRF guard on by default: requests to private/reserved addresses are blocked unless explicitly allowlisted (allowRanges).
  • No JS execution: pages are parsed with linkedom, never rendered, so prompt-injected scripts can't run.
  • Byte cap + timeout on every request.

Development

pnpm test        # 18 tests: extraction, raw mode, SSRF, redirects, slicing
npx tsc --noEmit # type-check the extension

License

MIT