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

@sentineld/browser

v1.3.2

Published

Browser SDK for Sentinel fraud detection and device fingerprinting

Downloads

796

Readme

@sentinel-sdk/browser

Browser SDK for Sentinel fraud detection and device fingerprinting. Identify visitors, detect bots, and assess fraud risk in real-time.

Installation

npm install @sentinel-sdk/browser

Or via CDN:

<script src="https://unpkg.com/@sentinel-sdk/browser@latest/dist/sentinel.min.js"></script>

Quick Start

ES Modules

import Sentinel from '@sentinel-sdk/browser';

// Initialize with your API key
Sentinel.init({
  endpoint: 'https://sentinel.yourdomain.com/api',
  apiKey: 'pk_live_xxxxxxxxxxxxx',
});

// Identify the current visitor
const result = await Sentinel.identify();

console.log(result.visitor_id);    // Unique visitor ID
console.log(result.is_new);       // First time seeing this visitor

// Send visitor_id to your backend -- fetch risk scores
// server-side using the sk_live_* secret key API

Script Tag

<script src="https://unpkg.com/@sentinel-sdk/browser@latest/dist/sentinel.min.js"></script>
<script>
  Sentinel.init({
    endpoint: 'https://sentinel.yourdomain.com/api',
    apiKey: 'pk_live_xxxxxxxxxxxxx',
  });

  Sentinel.identify().then(function(result) {
    console.log('Visitor ID:', result.visitor_id);
  });
</script>

Configuration

Sentinel.init({
  endpoint: string,   // Your Sentinel API endpoint
  apiKey: string,      // Your public API key (pk_live_xxx)
});

| Option | Type | Required | Description | |--------|------|----------|-------------| | endpoint | string | Yes | Your Sentinel API base URL | | apiKey | string | Yes | Public API key (pk_live_ prefix). Used for request signing, encryption, and Proof-of-Work authentication. |

API Reference

Sentinel.init(config)

Initialize the SDK. Must be called before other methods.

Calling init() eagerly starts background work so that identify() is fast:

  • Fingerprint collection (canvas, WebGL, audio, fonts)
  • WebRTC network signal gathering
  • WASM crypto module loading (signing, encryption, PoW solver)
  • Anti-debug monitoring

Sentinel.identify(params?)

Identify the current visitor and get risk assessment.

A single call handles the full pipeline: collecting signals, fetching and solving a Proof-of-Work challenge, encrypting and signing the payload, and sending it to the server. No separate setup steps are needed.

const result = await Sentinel.identify({
  sessionId: 'optional-session-id',  // Auto-generated if not provided
  accountId: 'user-123',             // Optional: link to your user ID
});

// Returns:
{
  visitor_id: string,     // Stable visitor identifier
  confidence: number,     // Fingerprint confidence (0-1)
  method: string,         // Resolution method ("fingerprint")
  is_new: boolean,        // First time seeing this visitor
  visit_count: number,    // Total visits from this device
}

// Risk and automation scores are NOT returned to the browser.
// Fetch them server-side using your sk_live_* key:
// GET /api/v1/visitors/{visitor_id}/events

Sentinel.track(params)

Track a custom event (e.g., login, purchase, signup).

const result = await Sentinel.track({
  type: 'login',                // Event type
  accountId: 'user-123',        // Optional: your user ID
  metadata: {                   // Optional: custom data
    method: 'password',
    success: true,
  },
});

Sentinel.getVisitorId()

Get the current visitor's fingerprint hash without making an API call.

const visitorId = await Sentinel.getVisitorId();

Sentinel.detectIncognito()

Detect if the browser is in incognito/private mode.

const isIncognito = await Sentinel.detectIncognito();

What Happens Under the Hood

When you call identify() or track(), the SDK performs these steps in parallel for minimal latency:

  1. Collect signals — fingerprint (canvas, WebGL, audio, fonts), network (WebRTC), behavior (mouse/keyboard patterns), integrity (headless/stealth/VM/extension detection), and validation signals (UA, screen, timezone, languages).

  2. Fetch & solve Proof-of-Work — requests a challenge from GET /v1/challenge and solves it using a native WASM SHA-256 loop. The solution is attached as X-Pow-Id and X-Pow-Nonce headers. This runs concurrently with signal collection so it adds zero extra latency.

  3. Encrypt & sign — the payload is AES-GCM encrypted and HMAC-SHA256 signed using the pk_live_ API key. Both operations use the WASM crypto module when available.

  4. POST — sends the encrypted, signed payload with PoW headers. The server decrypts, verifies the signature, validates the PoW solution, cross-references HTTP headers against SDK-reported values, and returns the risk assessment.

init()                      identify()
  │                            │
  ├─ Load WASM crypto          ├─ Collect signals ──────┐
  ├─ Start fingerprinting      ├─ Fetch PoW challenge ──┤ (parallel)
  ├─ Start network probes      │                        │
  ├─ Start anti-debug          │  Solve PoW (WASM) ─────┘
  │                            │
  │                            ├─ Sign + Encrypt payload
  │                            ├─ POST /v1/identify
  │                            └─ Return risk result

Security Features

Proof-of-Work

Every identify() and track() call requires solving a SHA-256 Proof-of-Work challenge before the server accepts it. This raises the cost of automation — a bot farm must burn real CPU per request.

  • Default difficulty: 16 leading zero bits (~65K SHA-256 hashes, ~30-50ms)
  • Adaptive difficulty: repeated failures from the same IP increase difficulty (up to +8 bits, making it 256x harder)
  • The solver runs inside a compiled WASM binary with integrity verification — there is no JavaScript fallback to reverse-engineer

Payload Encryption & Signing

All request bodies are AES-GCM encrypted and HMAC-SHA256 signed. The server decrypts and verifies signatures before processing. Replay attacks are prevented by unique nonces and timestamps.

HTTP Header Validation

The server cross-references actual HTTP headers against SDK-reported values:

| Check | What it catches | |-------|----------------| | User-Agent mismatch | curl with spoofed payload | | Accept-Language mismatch | Forged language signals | | Sec-CH-UA mismatch | Wrong browser family claims | | Missing Sec-Fetch-Site | Non-browser HTTP clients | | Missing Sec-CH-UA | Automation tools omitting client hints | | Connection: keep-alive | HTTP/1.1 libraries pretending to be browsers |

Anti-Debug & Anti-Tampering

The SDK detects and deters reverse engineering:

  • Passive detection — timing API integrity checks, Image.id getter traps for DevTools, native function code-length monitoring, requestAnimationFrame cadence analysis, stack depth anomaly detection
  • Active deterrencedebugger statement bombing only activates after high-confidence detection (score-based system with threshold)
  • Anti-tampering — self-defending function wrappers, environment verification, code integrity checks, prototype modification detection
  • Stealth detection — catches puppeteer-stealth, playwright-stealth, and similar plugins through Function.toString anomalies, iframe isolation checks, Chrome runtime inconsistencies, and Proxy wrapper detection

Bot & Automation Detection

Signals collected and scored server-side:

  • WebDriver / navigator.webdriver flag
  • Headless browser indicators (missing plugins, languages, WebGL, Chrome runtime)
  • CDP markers (Puppeteer, Playwright, Selenium, ChromeDriver)
  • VM detection (VMware, VirtualBox, Parallels, QEMU)
  • Canvas and WebGL manipulation detection
  • Privacy/automation extension detection
  • VPN, proxy, and datacenter IP detection (MaxMind GeoIP + datacenter CIDR lists)

Risk Scores

| Score Range | Risk Level | Description | |-------------|------------|-------------| | 0-20 | Low | Likely legitimate user | | 21-50 | Medium | Some suspicious signals | | 51-80 | High | Likely fraudulent | | 81-100 | Critical | Strong fraud indicators |

Common Risk Reason Codes

| Code | Description | |------|-------------| | BOT_WEBDRIVER | WebDriver/automation detected | | BOT_HEADLESS | Headless browser detected | | BOT_CDP | Chrome DevTools Protocol automation | | BOT_STEALTH | Stealth plugin detected | | VPN_DETECTED | VPN/proxy detected | | DATACENTER_IP | IP from datacenter range | | TZ_MISMATCH | Timezone doesn't match IP location | | INCOGNITO | Private browsing mode | | HTTP_UA_MISMATCH | HTTP User-Agent doesn't match SDK-reported UA | | MISSING_CLIENT_HINTS | Browser should send Sec-CH-UA but it's missing | | MISSING_SEC_FETCH | Browser should send Sec-Fetch-Site but it's missing | | SIGNAL_INCONSISTENCY | Multiple signal cross-validation failures |

Server Configuration

The Sentinel API server is configured via environment variables:

| Variable | Default | Description | |----------|---------|-------------| | SENTINEL_PORT | 8080 | API server port | | SENTINEL_POSTGRES_DSN | — | PostgreSQL connection string (required) | | SENTINEL_REDIS_ADDR | localhost:6379 | Redis address | | SENTINEL_HMAC_SECRET | — | Server-side HMAC secret (required) | | SENTINEL_ALLOWED_ORIGINS | localhost | CORS allowed origins | | SENTINEL_POW_ENABLED | true | Enable Proof-of-Work challenges | | SENTINEL_POW_DIFFICULTY | 16 | PoW difficulty (leading zero bits) | | SENTINEL_REQUIRE_API_KEY | false | Require API keys on SDK routes | | SENTINEL_MAXMIND_CITY_PATH | — | Path to GeoLite2-City.mmdb | | SENTINEL_MAXMIND_ASN_PATH | — | Path to GeoLite2-ASN.mmdb | | SENTINEL_ENABLE_PROXY_DETECTION | true | Enable VPN/proxy risk scoring |

TypeScript

Full TypeScript support is included. Import types:

import Sentinel, {
  SentinelConfig,
  IdentifyResponse,
  EventResponse,
} from '@sentinel-sdk/browser';

Browser Support

Requires WebAssembly support (all modern browsers):

  • Chrome 57+
  • Firefox 52+
  • Safari 11+
  • Edge 16+

License

MIT