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

apira-guard

v0.1.0

Published

Catches bots, abuse, and broken flows after Cloudflare, before PostHog.

Readme

Apira

Catches bots, abuse, and broken flows after Cloudflare, before PostHog.

Detect fake signups, risky actions, API abuse, and silent backend failures — locally, with no API key.

npm install apira-guard

Apira is a local, no-network layer. watchActions() and watchAccess() attach riskScore, riskLevel, and reasons to matched form submits and HTTP requests. watchSignups() / watchForms() listen for conversion submits and fire signupguard:submit with intent metadata (no risk payload). protectForms() blocks obvious bad email and phone values before submit.

No account. No dashboard. No outbound calls.


Common use cases

Use Apira to:

  • block or flag fake or junk signups (protectForms, then optional watchActions risk)
  • detect disposable emails and fake-looking phones at submit time (protectForms)
  • score checkout, password reset, account update, invite, waitlist, demo request, and contact sales forms (watchActions — match by form copy or data-signup-guard-form)
  • detect forms submitted unrealistically fast (watchActions)
  • detect repeated form submissions (watchActions)
  • add request-risk scoring to Express, Next.js, or Node APIs
  • detect request velocity
  • detect sudden traffic spikes
  • detect simple API enumeration like /api/users/1, /api/users/2, /api/users/3
  • send risk events to your own logs, database, Sentry, PostHog, or analytics stack

Add one line

Signup forms

import { watchSignups } from "apira-guard";

watchSignups();

Auto-detects signup forms with email or phone fields and fires signupguard:submit on submit (detail: intent, timestamp, metadata). It does not inject signupGuardRisk — use watchActions({ action: "signup" }) (plus matching form text or data-signup-guard-form="signup") when you want the same risk JSON on signup flows.

Use protectForms() if you want to block obvious bad submissions (invalid / disposable email, bad phone shapes).


Important actions

Protect conversion-critical forms like checkout, password reset, account update, invite, waitlist, demo request, and contact sales.

import { watchActions } from "apira-guard";

watchActions({ action: "checkout" });

Apira watches the matching form, computes risk on submit, injects signupGuardRisk into the form body, and fires signupguard:action.

watchActions({
  action: "checkout",
  onAction(event) {
    console.log(event.action, event.risk);
  }
});

Target a form explicitly:

<form data-signup-guard-form="checkout">
  ...
</form>

API routes

Watch server-side requests for lightweight API abuse signals.

import { watchAccess } from "apira-guard/server";

app.use(watchAccess());

Apira attaches risk directly to the request:

app.get("/api/users/:id", (req, res) => {
  if (req.signupGuardRisk?.riskLevel === "high") {
    return res.status(429).json({ error: "rate limited" });
  }

  res.json({ ok: true });
});

Configure velocity and spike detection:

watchAccess({
  velocityThreshold: 60,
  spikeThreshold: 20,
  velocityWindowMs: 60_000
});

Risk output

watchActions() and watchAccess() both use the same payload shape:

{
  riskScore: 85,
  riskLevel: "high",
  reasons: ["velocity", "fast_action", "enumeration"]
}

| Reason | Where | What it means | | ------------------------ | -------------- | ------------- | | velocity | forms (watchActions), APIs | Too many submits or requests in the sliding window (default 60 s on the server; client watchActions uses a stricter per-form threshold) | | fast_action | forms (watchActions) | Submitted faster than the fast-action threshold after the watcher attached | | retry | forms (watchActions) | Same form submitted again | | enumeration | APIs | Sequential numeric IDs in the URL path (run ≥ 3) | | spike | APIs | Burst of requests in a 10 s window | | endpoint_concentration | APIs | Same normalised endpoint hit repeatedly in the velocity window | | probing | APIs | High 4xx rate from this client (after enough samples) | | flow_anomaly | APIs | Write request with no prior read on the same key (bot-style shortcut) |

Score thresholds: low < 40 · medium 40–69 · high ≥ 70.


Can Apira block risk?

Yes. Apira can run as a signal layer or a blocking layer.

Signal mode: watchActions() injects a hidden signupGuardRisk JSON field on submit; watchAccess() sets req.signupGuardRisk on each request.

const risk = JSON.parse(req.body.signupGuardRisk ?? "{}");

Block mode stops obvious bad activity before it continues.

import { protectForms } from "apira-guard";

protectForms();

For APIs, block high-risk requests in middleware:

app.use(watchAccess());

app.use((req, res, next) => {
  if (req.signupGuardRisk?.riskLevel === "high") {
    return res.status(429).json({ error: "Too many suspicious requests" });
  }

  next();
});

Apira can reduce obvious abuse. It does not guarantee fraud prevention or stop sophisticated attackers.


Reading risk on the server

watchActions() injects a hidden field on matched forms:

app.post("/checkout", (req, res) => {
  const risk = JSON.parse(req.body.signupGuardRisk ?? "{}");

  if (risk.riskLevel === "high") {
    return res.status(422).json({ error: "Suspicious request" });
  }

  res.json({ ok: true });
});

API routes get risk directly:

req.signupGuardRisk;

For TypeScript Express apps:

declare global {
  namespace Express {
    interface Request {
      signupGuardRisk?: import("apira-guard/server").RiskResult;
    }
  }
}

Signup-first, conversion-ready

watchSignups() is shorthand for:

watchForms({ intent: "signup" });

For any conversion-critical form, use watchForms():

import { watchForms } from "apira-guard";

watchForms({
  intent: "demo_request",
  metadata: { page: "pricing" },
  onSubmit(event) {
    console.log(event.intent, event.timestamp, event.metadata);
  }
});

Opt a form in or out:

<form data-signup-guard-form="checkout">...</form>
<form data-signup-guard-ignore>...</form>

What protectForms() blocks

import { protectForms } from "apira-guard";

protectForms();

Blocks obvious garbage at submit time using browser validation messages:

  • invalid email formats
  • disposable email domains
  • invalid phone formats
  • fake-looking phones like 0000000000, 1234567890, and 555-01xx

What ships in npm

  • watchSignups()
  • watchForms()
  • watchActions()
  • protectForms()
  • watchAccess()
  • shared risk payloads
  • local scoring rules
  • reason codes
  • TypeScript types

Everything runs inside your app. Apira does not call external services.


What is not included

Not included today:

  • hosted dashboard
  • shared reputation network
  • external IP reputation checks
  • external email verification APIs
  • ML fraud models

These may become optional later. The npm package works without them.


What Apira is not

Apira is not a CAPTCHA, identity verification system, hosted fraud platform, or replacement for server-side validation.

It is a local first line of defense for forms, actions, and API routes — the layer between edge protection and your analytics/logging stack.