Open Source Β· Free Forever Β· No API Keys Β· No Limits

Stop bots.
No CAPTCHAs. No Keys.
No Cost.

SilentShield watches 12 invisible detection layers β€” mouse entropy, biometrics, fingerprinting, font enumeration, proof-of-work β€” and blocks bots before they touch your backend.

βœ“ No API key βœ“ No rate limits βœ“ MIT licensed βœ“ Self-hostable βœ“ 12 detection layers βœ“ 30-second setup
silentshield β€” live analysis (this browser)
πŸ–±οΈ Mouse entropy
--
⛏️ Proof-of-Work
--
🎨 Canvas FP
--
πŸ”€ Font enum
--
πŸ—£οΈ Speech voices
--
πŸ–₯️ WebGL renderer
--
βš™οΈ Environment
--
⌨️ Keyboard biom.
--

No API Key.
Just drop it in.

Unlike reCAPTCHA or hCaptcha, SilentShield works completely anonymously β€” no registration, no dashboard, no approval process required.

πŸ”“
Fully anonymousOne script tag. No key, no account, no sign-up needed.
♾️
No rate limits, ever10 or 10 million requests β€” same price: free.
πŸ‘οΈ
Invisible to usersNo puzzles, no checkboxes. Users never know it's there.
πŸ€–
Self-learningBot patterns auto-update every 10 minutes from live traffic.
index.html β€” the complete integration
<!-- 1. Add script to <head> -->
<script
  src="https://cdn.jsdelivr.net/npm/silentshield@latest/dist/silentshield.min.js"
></script>

<!-- 2. Tag your form (no key needed) -->
<form data-silentshield action="/submit" method="POST">
  <input type="email" name="email" />
  <button type="submit">Submit</button>
</form>

<!-- 3. Verify on your server -->
// POST https://sh.krl.kr/api/verify
// body: { "token": req.body._ss_token }
// response: { "valid": true, "score": 91 }

How SilentShield detects bots

Each layer adds independent signal. Combined score 0–100. β‰₯70 = human, 45–69 = suspicious, <45 = bot.

1

Proof of Work

Browser solves SHA256(challenge+nonce).startsWith("000") in background. Real browsers: ~100–500ms. Pre-computed/spoofed: <5ms = -25pts. Missing PoW = -35pts. Valid = +15pts.

+15 / -35
2

Mouse Path Entropy

Measures angle-change variance across all mouse positions. Humans move in organic curves (variance >0.01 rad/event). Bots move linearly or not at all. Linear path with >10 events = -18pts.

+12 / -18
3

Mouse Speed Variance

Calculates pixel/ms speed between consecutive mouse samples and measures its variance. Humans constantly accelerate and decelerate. Scripted mouse movement has near-constant speed.

+5
4

Keyboard Biometrics

Tracks inter-keystroke intervals (up to 120). Variance >5000 = very human. Variance <10 with >3 keys = definitely scripted (-45pts). Form fill <300ms = -55pts.

+18 / -55
5

Canvas Fingerprinting

Renders gradient + multi-font text + arc to a canvas, reads the last 80 PNG bytes. Headless Chromium and SwiftShader produce known artifact patterns. Match = -25pts. Unique render = +10pts.

+10 / -25
6

WebGL Renderer

Reads UNMASKED_RENDERER_WEBGL. Software renderers (SwiftShader, llvmpipe, Mesa, ANGLE) = -35pts. Also reads MAX_TEXTURE_SIZE for additional GPU fingerprinting.

+12 / -35
7

Audio Fingerprinting

Creates an AudioContext, routes triangle oscillator through AnalyserNode, captures 50-point FFT. Headless lacks real audio pipeline β€”returns errors or flat zero. Error = -8pts. Valid = +8pts.

+8 / -8
8

Font Enumeration

Renders 28 known fonts via canvas, detects which are installed by comparing pixel widths. Real desktops have 15–25 fonts. Headless on a bare VPS has 0β€”. fontCount = 0 β†’ -8pts, >15 β€”+10pts.

+10 / -8
9

Speech Synthesis

speechSynthesis.getVoices().length β€”real desktop browsers return 5β€”0 OS TTS voices. Headless Chrome on a Linux VPS returns 0. Zero voices = -5pts. >5 voices = +10pts.

+10 / -5
10

Environment Flags

Checks 20+ API signals: navigator.webdriver (-70), plugin count, window.chrome (+8), localStorage, IndexedDB, Web Workers, Notification API, Service Worker, Battery API, Bluetooth, innerWidth/screenWidth ratio.

up to +45 / -70
11

Rotating Honeypot

Injects a CSS-invisible field with one of 25 rotating names (website, company_url, phone2β€”. Name rotates every page load to defeat bot learning. Field filled = -100pts β€”automatic bot.

-100 if triggered
12

Spam + UA Matching

Content filter checks 25+ spam keywords. UA matching blocks 23+ known bot clients (curl, wget, Selenium, Scrapy, etc.) and learned patterns from the 10-minute bot learning job.

-50 to -80 (spam) / -50 (UA)

How we compare

Feature SilentShield reCAPTCHA v3 hCaptcha Turnstile ALTCHA
Completely freeβœ… Always1M/mo1M/moFree tierβœ…
No API key neededβœ…βŒβŒβŒβŒ
Invisible to usersβœ…βœ…πŸ”² (checkbox)βœ…βœ…
Open source / MITβœ…βŒβŒβŒβœ…
Self-hostableβœ…βŒβŒβŒβœ…
Font enumerationβœ…βŒβŒβŒβŒ
Keyboard biometricsβœ…βŒβŒβŒβŒ
Speech voice detectionβœ…βŒβŒβŒβŒ
Mouse entropy scoringβœ…βœ…βœ…~❌
Bot auto-learningβœ… every 10minGoogle MLProprietaryProprietary❌
GDPR / no user trackingβœ…βŒβŒβŒβœ…
Fake Success modeβœ…βŒβŒβŒβŒ

Complete Reference

Everything you need to integrate, configure, and self-host SilentShield.

Installation

SilentShield has two parts: a JavaScript SDK that runs in the browser, and a server that verifies tokens. You can use the hosted server at sh.krl.kr or self-host.

CDN (recommended β€” no build step)

HTML
<script
  src="https://cdn.jsdelivr.net/npm/silentshield@latest/dist/silentshield.min.js"
></script>

Served globally via jsDelivr CDN. Cached with immutable headers. ~13KB minified, zero external dependencies.

npm

Terminal
npm install silentshield
ES Module
import SilentShield from 'silentshield';
βœ… No API key needed. Works out of the box without any registration.

Quick Start

The fastest way to add SilentShield to any HTML form.

Step 1 β€” Add the script

HTML head
<script src="https://cdn.jsdelivr.net/npm/silentshield@latest/dist/silentshield.min.js"></script>

Step 2 β€” Tag your form

HTML
<form data-silentshield action="/submit" method="POST">
  <input type="text" name="name" />
  <input type="email" name="email" />
  <button type="submit">Submit</button>
</form>

<!-- SilentShield auto-inits all [data-silentshield] forms -->

Step 3 β€” Verify on your server

On form submit, SilentShield injects a hidden _ss_token field. POST it to /api/verify:

Node.js
const r = await fetch('https://sh.krl.kr/api/verify', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ token: req.body._ss_token })
});
const { valid, score, verdict } = await r.json();
if (!valid) return res.status(403).send('Bot');
Tokens are one-time use. Calling /api/verify twice on the same token returns valid: false.

SDK Configuration

All options are optional. SilentShield works with zero configuration.

OptionDefaultDescription
apiUrl'https://sh.krl.kr'API endpoint. Set to your self-hosted URL to use your own server.
publicKeynullOptional site identifier for analytics grouping. No security value β€”purely for dashboard.
threshold45Score below which to trigger bot handling. Range 0–100. Recommended: 45 (balanced), 60 (strict).
fakeSuccesstrueShow fake "Sent successfully!" to blocked bots. Silently discards their submission.
onBotnullCallback function called when a bot is detected. Receives {score, verdict}.
Full example
const shield = new SilentShield({
  apiUrl: 'https://sh.krl.kr',
  threshold: 45,
  fakeSuccess: true,
  onBot: (r) => console.log('Blocked bot, score:', r.score)
});
shield.protect('#contact-form');

// Or use the static auto-init (protects all [data-silentshield] forms):
SilentShield.init({ apiUrl: 'https://sh.krl.kr' });

/api/signal

POST/api/signal

Called automatically by the JS SDK when a form is submitted. Accepts all collected behavioral signals and returns a one-time token.

You never need to call this endpoint directly β€” the SDK handles it automatically.

Key Request Fields

FieldTypeDescription
mouseEventsnumberNumber of mousemove events recorded
mouseEntropynumberAngle-change variance of mouse path
mouseSpeedVariancenumberSpeed variance along mouse path
keystrokeIntervalsnumber[]Array of inter-keystroke delays (ms)
formFillMsnumberTotal form fill duration
powChallengestringPoW challenge string
powNoncenumberSolved PoW nonce
powHashstringResulting SHA-256 hash
canvasFingerprintstringLast 80 bytes of canvas PNG (base64)
webglRendererstringGPU renderer string
fontCountnumberNumber of detected installed fonts
speechVoiceCountnumberNumber of speech synthesis voices
siteIdstring|nullOptional public key for analytics

Response

// 200 OK { "token": "550e8400-e29b-41d4-a716-446655440000", "score": 91, "verdict": "human" // "human" | "suspicious" | "bot" }

/api/verify

POST/api/verify

Your backend calls this to validate a token before processing a form submission.

Request

{ "token": "550e8400-e29b-41d4-a716-446655440000" }

Response

// Human { "valid": true, "score": 91, "verdict": "human", "timestamp": "2025-01-01T12:00:00.000Z" } // Bot or invalid token { "valid": false, "score": 22, "verdict": "bot" } // Already used { "valid": false, "error": "Token already used" }
Tokens expire after first use. Store them only until verified β€” never reuse.

PHP Example

PHP
$data = json_decode(file_get_contents('https://sh.krl.kr/api/verify', false,
  stream_context_create(['http' => [
    'method'  => 'POST',
    'header'  => 'Content-Type: application/json',
    'content' => json_encode(['token' => $_POST['_ss_token']])
  ]])
), true);
if (!$data['valid']) { http_response_code(403); exit; }

/api/register

POST/api/register

Register your domain to get analytics keys. Completely optional β€”SilentShield works without any registration.

Request

{ "domain": "mysite.com", "name": "My Project" // optional }

Response

{ "message": "Site registered β€” dashboard analytics enabled", "public_key": "pk_abc123...", "secret_key": "sk_xyz789..." }
The public key is for analytics grouping only. The secret key unlocks /api/analytics/* and the dashboard.

/api/analytics

All analytics endpoints require header: x-secret-key: sk_...

GET /api/analytics/overview

Returns 7-day traffic stats, bot rate, detection breakdown by layer.

{ "total": 15420, "human": 14100, "suspicious": 820, "bot": 500, "botRate": "3.24%", "avgScore": 84.2, "daily": [...] }

GET /api/analytics/patterns

Returns learned bot patterns with confidence scores.

GET /api/analytics/recent

Returns the 50 most recent submissions with scores and verdicts.

GET /api/analytics/admin

Returns all sites, system stats. Requires x-admin-secret header matching ADMIN_SECRET env var.

Score System

Every submission gets a score from 0 to 100. Score starts at 50 and is adjusted by each detection layer.

Score RangeVerdictMeaning
70–100humanStrong signals of real human browser. Process normally.
45–69suspiciousSome bot-like signals but not conclusive. You can require additional verification or silently log for review.
0–44botStrong bot indicators. Reject, show fake success, or challenge.

Layer Weights (approximate)

LayerMax PositiveMax Negative
Proof of Work+15-35
Mouse path entropy+12-18
Keyboard biometrics + fill time+18-55
Canvas fingerprint+10-25
WebGL renderer+12-35
Audio fingerprint+8-8
Font enumeration+10-8
Speech voices+10-5
Environment flags+45-70
Honeypot🍯-100
Spam content🚫-80
User agent+10-50

The final score is clamped to 0–100. navigator.webdriver = true is an immediate -70 (nearly always bot verdict).

Signal Reference

Complete list of signals collected by the SDK v2.1:

Interaction Signals

SignalTypeDescription
mouseEventsnumberTotal mousemove events (capped at 300 samples)
scrollEventsnumberScroll events
clickEventsnumberClick events
dblClickEventsnumberDouble-click events
contextMenuEventsnumberRight-click (contextmenu) events
mouseDownEventsnumberMousedown events
mouseEntropynumberAngle-change variance of mouse path
mouseSpeedVariancenumberSpeed variance (px/ms) along path
keystrokeIntervalsnumber[]Last 120 inter-keystroke delays
backspaceCountnumberBackspace key presses
pasteCountnumberPaste events
formFillMsnumberDuration from first keystroke to submit

Environment Signals

SignalTypeDescription
webdriverbooleannavigator.webdriver (true = definitive bot)
pluginCountnumbernavigator.plugins.length
hardwareConcurrencynumberCPU core count
deviceMemorynumberRAM in GB (rounded)
hasChromebooleanwindow.chrome defined
fontCountnumberInstalled fonts detected via canvas
speechVoiceCountnumberspeechSynthesis.getVoices().length
hasLocalStoragebooleanlocalStorage available and writable
hasIndexedDBbooleanIndexedDB available
hasWebWorkerbooleanWeb Workers available
hasBatterybooleannavigator.getBattery available
hasWebBluetoothbooleannavigator.bluetooth available
pointerFineboolean(pointer: fine) CSS media match
hoverCapableboolean(hover: hover) CSS media match
perfPrecisionnumberMinimum performance.now() increment
innerWidth / innerHeightnumberWindow inner dimensions
screenWidth / screenHeightnumberScreen dimensions

Self-Hosting

SilentShield is designed to be self-hosted. One command on any Ubuntu 22.04 VPS.

bash β€” Ubuntu 22.04
curl -fsSL \
  https://raw.githubusercontent.com/3289david/silentshield/main/deploy.sh \
  | bash

This installs Node.js 20, PM2, clones the repo, builds the SDK, and starts the server.

Add SSL (nginx)

bash
apt install nginx certbot python3-certbot-nginx
certbot --nginx -d your-domain.com
cp nginx.conf /etc/nginx/sites-available/silentshield
ln -s /etc/nginx/sites-available/silentshield /etc/nginx/sites-enabled/
nginx -t && systemctl reload nginx

Point your SDK at your server

JavaScript
new SilentShield({
  apiUrl: 'https://your-domain.com'
}).protect('#my-form');
βœ… Requirements: Ubuntu 22.04+, 512MB RAM, ports 80 and 443 open. Node.js 20 is auto-installed.

Environment Variables

Configure via server/.env (auto-created by deploy script).

VariableDefaultDescription
PORT3000Server listen port
DB_PATH./silentshield.dbSQLite database file path
ADMIN_SECRET(random 32-byte hex)Admin dashboard password
CORS_ORIGINS*Allowed CORS origins (comma-separated)
RATE_LIMIT_MAX200Max requests per window
RATE_LIMIT_WINDOW_MS60000Rate limit window in ms
NODE_ENVdevelopmentSet to production on VPS

Framework Guides

React

React hook
import { useEffect, useRef } from 'react';
import SilentShield from 'silentshield';

export function ContactForm() {
  const formRef = useRef();

  useEffect(() => {
    const shield = new SilentShield({
      apiUrl: 'https://sh.krl.kr'
    });
    shield.protect(formRef.current);
  }, []);

  return <form ref={formRef} onSubmit={handleSubmit}>...</form>;
}

Next.js (App Router)

Next.js API route β€” app/api/submit/route.js
export async function POST(req) {
  const { token, ...formData } = await req.json();
  const r = await fetch('https://sh.krl.kr/api/verify', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ token })
  });
  const { valid } = await r.json();
  if (!valid) return Response.json({ error: 'Bot' }, { status: 403 });
  // process form...
}

WordPress / PHP

PHP
// In functions.php or plugin:
function ss_verify($token) {
  $r = wp_remote_post('https://sh.krl.kr/api/verify', [
    'body' => json_encode(['token' => $token]),
    'headers' => ['Content-Type' => 'application/json']
  ]);
  $data = json_decode(wp_remote_retrieve_body($r), true);
  return !empty($data['valid']);
}

Own your infrastructure.

Deploy to any Linux VPS in 5 minutes. One command. Full control over your data.

1
Get a VPSUbuntu 22.04, 512MB RAM. DigitalOcean/Hetzner from $5/month.
2
Run deploy scriptOne command installs Node.js 20, builds the SDK, starts PM2.
3
Add nginx + SSLFree SSL via Certbot. Config file included in the repo.
4
Point your SDK at itChange apiUrl to your domain. Done.
One-command deploy
# Paste on your VPS as root:
curl -fsSL \
  https://raw.githubusercontent.com/3289david/silentshield/main/deploy.sh \
  | bash

βœ… SilentShield is running!
  URL: http://YOUR_IP:3000

# Add SSL:
apt install nginx certbot python3-certbot-nginx
certbot --nginx -d your-domain.com

# Use your own server:
new SilentShield({
  apiUrl: 'https://your-domain.com'
}).protect('#my-form');
Requirements: Ubuntu 22.04+, 512MB RAM, ports 80/443 open.

Free to use. Help keep it alive.

Built and maintained by one developer. If SilentShield saves you money on reCAPTCHA fees, consider a coffee.

Get Your API Keys

Register your domain for free to unlock the analytics dashboard. No account, no email β€” instant keys.

Common questions

Yes. Completely unlimited, forever. No paid tiers, no credit card, no rate limits enforced by the hosted server. SilentShield is open source MIT software. You can use sh.krl.kr for free or self-host for $0.
No. Registration and API keys are completely optional (they only enable analytics). Just add the script tag and it works instantly, anonymously.
SilentShield never sends PII. IPs are base64 hashed (not reversible). No cross-site tracking, no user profiling, no data sold. All collected signals are behavioral and anonymous.
Very low. Score-based thresholds (β‰₯70 human, 45–69 suspicious, <45 bot) let you tune sensitivity. Default settings are conservative β€”real users consistently score 75β€”5.
The bot learning job runs every 10 minutes, analyzing recent traffic and updating detection thresholds. You can also self-host and tune scorer.js weights for your specific threat profile.
Yes. Install via npm and import as an ES module. Works with any framework. See the Frameworks section in the docs above.
ALTCHA focuses on Proof-of-Work as the primary signal. SilentShield adds 11 more layers: mouse entropy, keyboard biometrics, font enumeration, speech synthesis detection, canvas/WebGL/audio fingerprinting, honeypot, spam filter, and bot learning. Both are open source and free.