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

seorank

v0.2.0

Published

seo.rank: a free, open-source on-page SEO audit. Web app, JSON API, CLI, TUI and an MCP server (stdio, no API key).

Readme

seo.rank

A free, open-source on-page SEO audit. Paste a URL, get a 0–100 score and the fixes that matter most, in the order to make them. Web app, JSON API, CLI, TUI and an MCP server for AI agents.

seo.rank is a Moshpit site. It is listed on pit.world at pit.world/b/seo.rank.

# the CLI and TUI
bunx seorank audit example.com
bunx seorank audit example.com --local   # on your machine, no daily limit
bunx seorank                             # interactive

# your agent
claude mcp add seorank -- bunx seorank mcp

What it checks

About 25 checks, weighted by how much they matter to search engines:

| Group | Checks | | --- | --- | | Crawlability | HTTP status, noindex (meta and X-Robots-Tag), robots.txt (does it block this page for Googlebot?), XML sitemap, canonical | | Security | HTTPS, http→https redirect, HSTS | | Content | title length, meta description length, one H1, heading outline, word count, whether the most repeated phrase is in the title or H1, image alt coverage, internal links | | Mobile & markup | viewport, lang, charset, favicon | | Social & rich results | Open Graph, X/Twitter card, JSON-LD types (and broken JSON-LD), hreflang | | Speed | time to first byte, HTML size, compression |

Plus the top words and two-to-three word phrases on the page, with density.

The score is the weighted share of checks passed (a warning earns half). The fix list is sorted by what each fix is worth.

How it stays free

  • No paid APIs, no headless browser. One audit is a handful of HTTP requests (the page, robots.txt, a sitemap, the http check) and a few milliseconds of parsing with Bun's built-in HTMLRewriter.
  • 10 audits per visitor per day, enforced on the server. A visitor is an HMAC of their IP under a secret held only in memory and replaced at every UTC midnight, when the counts reset.
  • A global cap (2,000 fresh audits a day by default) as a cost circuit breaker, and at most 8 audits in flight at once.
  • A one-hour cache per URL; re-opening a recent result does not use an audit.
  • Over the limit: the page says so, the API answers 429 with Retry-After. Or run it yourself with --local, without limits.

Privacy

No cookies (the server strips Set-Cookie from every response), no accounts, no analytics, no JavaScript on the pages, no third-party requests. nginx keeps no access log for the site and the app logs nothing per request. Strict CSP, Referrer-Policy: no-referrer.

Safe fetching

seo.rank fetches URLs that strangers give it, so src/fetch.ts only fetches http(s) on ports 80/443, refuses credentials in URLs, checks that every address a name resolves to is public (no loopback, RFC 1918, link-local, CGNAT, ULA, multicast, v4-mapped or NAT64 forms of those), follows at most five redirects by hand and re-checks every hop, only lets the page redirect within its own site, and enforces a timeout and a 2 MB cap.

API

| | | | --- | --- | | GET /api/audit?url=example.com (or POST {"url": …}) | the full audit: score, grade, checks[], fixes[], page, robotsTxt, sitemap, keywords, cached, quota | | GET /api/quota | { limit, used, remaining, resetAt } | | GET /health | { ok, version, today, keyed } |

Add fields=summary (and optionally top=N, default 5, max 25) for a small answer: url, finalUrl, status, score, grade, summary, the top N fixes, checkedAt, cached, quota.

Headers X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset. CORS open, no key needed.

API keys (trusted callers)

SEORANK_API_KEYS lists keys for our own services, comma-separated, each name:key or a bare key (16+ characters). A request with Authorization: Bearer <key> or X-API-Key: <key>:

  • skips the per-visitor free limit and does not count against the public global cap;
  • has its own daily cap per key, SEORANK_KEY_DAILY_LIMIT (default 50,000), reported in the same X-RateLimit-* headers and by GET /api/quota with the key;
  • runs behind its own concurrency gate, SEORANK_KEY_CONCURRENCY (default 4), so keyed batches and public visitors cannot starve each other.

A wrong key is a 401, never a quiet fall back to the free tier. Keys are compared in constant time and never logged; /health reports per-key usage by name only. The CLI and MCP server send SEORANK_API_KEY when it is set.

Surfaces

The house rule: everything ships a TUI, a CLI, an MCP and an API.

| | | | --- | --- | | Web + API | bun src/server.ts (PORT, default 8790; SEORANK_DAILY_LIMIT, SEORANK_GLOBAL_DAILY_CAP, SEORANK_CONCURRENCY, SEORANK_API_KEYS, SEORANK_KEY_DAILY_LIMIT, SEORANK_KEY_CONCURRENCY, PIT_VERIFY) | | CLI | seorank audit URL [--json] [--local] [--fixes], seorank quota, seorank open URL, seorank serve | | TUI | seorank | | MCP | seorank mcp: tools audit (url, format text/json) and quota. SEORANK_LOCAL=1 runs audits in-process |

The CLI, TUI and MCP server talk to https://seo.rank (or SEORANK_URL). Because seo.rank is a Moshpit name, the client resolves it with your system resolver if you are on the Moshpit network, otherwise through the Moshpit DNS-over-HTTPS resolver, and verifies the certificate against the Moshpit Root CA bundled in the package (public/moshpit-root-ca.crt). If the instance cannot be reached at all, the CLI and MCP server run the audit locally.

MCP config

{ "mcpServers": { "seorank": { "command": "bunx", "args": ["seorank", "mcp"] } } }

Run your own

git clone https://github.com/moshcoder/seo.rank && cd seo.rank
bun install
bun src/server.ts        # http://127.0.0.1:8790
bun test

Production runs on bare metal with bin/install.sh (OpenInstall): a systemd unit running bun behind nginx.

More

  • What AI crawlers and answer engines can read on a page: CrawlProof.
  • A site built for you, with every check passing: pit.world/build.

License

MIT