Client & Server SDKs
A browser SDK that collects signals, runs the captcha, and earns session clearance — and server SDKs for Node.js, Go, and PHP that verify results, set scraper tripwires, and enforce where bots can't tamper.
// server
npm install @webdecoy/node
// browser
npm install @webdecoy/client
// framework middleware
npm install @webdecoy/expressTwo SDKs, One Loop
WebDecoy integration has two halves that work together: the client detects and proves, the server verifies and enforces.
Client Side — in the browser
@webdecoy/client collects behavioral and device signals, runs the self-hosted captcha widget, and proves the session is a real browser — the check that earns session clearance.
Prefer no code at all? The Detection Script is a one-tag client-side install with the full detection engine.
Server Side — in your backend
@webdecoy/node (plus Go and PHP) verifies tokens where bots can't tamper, adds JA4 TLS fingerprinting, sets deterministic tripwires, and makes the allow, challenge, or block call.
Client-side signals are powerful; server-side verification makes them trustworthy. You'll usually run both.
What the Server SDK Does
The Node.js SDK provides server-side utilities for working with WebDecoy detections.
Verify Detections
Server-side verification of bot scanner results to prevent client-side tampering.
Query Detections
Access your detection history and analytics data through the API.
Signed Webhooks
Every webhook is HMAC-SHA256 signed, with event-type and delivery-ID headers for routing and idempotency.
Tripwires: Deterministic Scraper Detection
Stealth scrapers that spoof a real browser fingerprint slip past identity checks. A tripwire catches them by behavior instead: plant a hidden honeytoken link, and any request to its secret path is a deterministic bot hit. Zero false positives, no API key, no network call.
Deterministic, Not Probabilistic
A tripwire hit is a fact, not a score: the client requested a URL that exists nowhere a human could find it. Un-spoofable by a better fingerprint.
Zero False Positives
The honeytoken() link is off-screen, aria-hidden, and nofollow. Real users never see it and search engines never follow it, so only scrapers trip the wire.
Runs Fully In-Process
The tripwire rule and honeytoken generator ship in the open-source @webdecoy/node package. No API key, no account, no outbound call. Local path matching only.
import { webdecoy } from '@webdecoy/express';
import { tripwire, honeytoken } from '@webdecoy/node';
// 1. Generate a hidden decoy link + its secret path
const trap = honeytoken();
// 2. One line blocks any hit on the trap (auto 403)
app.use(webdecoy({
rules: [tripwire({ paths: [trap.path] })],
skipPaths: ['/health', '/static']
}));
// 3. Inject the invisible link so scrapers find it
app.get('/', (req, res) => {
res.send(`<!doctype html><html><body>
<h1>Welcome</h1>
${trap.linkHtml}
</body></html>`);
});A tripwire hit is ground truth that session clearance (below) enforces on directly: the SDK forwards the session's clearance token with the violation, and the client is denied new clearance on every IP it rotates to — the same durable lockout a hosted decoy triggers.
Read the deep dive: Tripwires: Catch the Scrapers Fingerprinting Misses
Verify AI Agents in Your Own Middleware
@webdecoy/node verifies Web Bot Auth (RFC 9421) signatures locally — no API round trip, no network on the warm path, under 5ms at p95. A user agent claiming to be GPTBot either proves it or gets caught.
import { WebDecoy, webBotAuth } from '@webdecoy/node';
const wd = new WebDecoy({ apiKey: process.env.WEBDECOY_API_KEY });
export async function middleware(request) {
const { agent } = await wd.detectBot(request);
// 'verified' | 'claimed' | 'impersonation' | 'none'
switch (agent.verdict) {
case 'impersonation':
// Claimed a signing agent's identity and failed verification
return new Response('Forbidden', { status: 403 });
case 'verified':
// agent.name → 'ChatGPT-User', agent.category → 'agent-browser'
return allowVerifiedCrawler(agent);
}
}
// Or drop it in as a rule — DENY on impersonation by default
app.use(webdecoy({ rules: [webBotAuth()] }));No Round Trip
Key directories are fetched and cached ahead of time, so verification is a local Ed25519 check. Warm path does zero network I/O.
Curated Directories Only
A Signature-Agent header is attacker-controlled. The SDK resolves keys only from a curated list, so it can never be pointed at an arbitrary host.
Node + Vercel Edge
Full verification runs inside the Edge runtime, not just Node. Zero dependencies, so there is nothing to shim.
The verification engine is open source: github.com/WebDecoy/web-bot-auth — an Apache-2.0 Go implementation with zero dependencies, cross-validated against Cloudflare's reference vectors and live deployment.
Learn more: Agent Identity & Trust Layer
Session Clearance: The Decoy Issues the Verdict
No fingerprint or IP rule can stop a real browser automated from a residential IP without blocking the human beside it. So WebDecoy enforcement asks a different question: does this session carry valid clearance? Real users prove themselves once and pass everywhere. A client that trips a decoy is denied new clearance — on every IP it rotates to.
Step 1 · Prove
The browser passes a check
The client-side SDK verifies it's talking to a real browser — signals, headless checks, proof-of-work — with zero friction for real users.
Step 2 · Clear
The session earns clearance
A signed clearance rides with the session itself — the client, not the IP address. Rotating IPs resets nothing.
Step 3 · Enforce
Protected routes ask one question
Valid clearance? Pass. Missing on a sensitive route — login, checkout, your scraped endpoints? Challenge. Passing the challenge lets a real user self-heal.
Trip a decoy, and the story ends differently: the client's active clearance is revoked within about a minute, and new clearance is refused — so a fresh IP no longer buys a clean slate.
Clearance is graded, not binary
A clearance token no longer just means "hasn't tripped a decoy." It carries a trust level — clean, human-likely, or attested-human — plus the evidence that earned it: browser-integrity checks at the interstitial, interaction cadence that reads as a real hand, or a Turnstile verdict you already collect.
Evidence only ever raises a grade and a high threat score caps it, so a session that produces none is treated exactly as it was before. Per-route minimum trust levels are enforced today by the edge validator; SDK-side minimum-trust enforcement is in progress.
Rotation-Proof by Design
Clearance binds to the client, not the address. A residential-proxy bot cycling through thousands of home IPs carries its verdict with it to every one of them.
Zero Collateral
A real user who shares a JA4 fingerprint — or even an IP — with an attacker simply proves their own session and moves on. No blanket fingerprint block, no innocent users caught in it.
Ground Truth, Not Guesswork
Behavioral vendors estimate whether traffic is a bot. A decoy or tripwire hit is certainty — no one clicks a honeypot by accident — and only that ground truth revokes clearance. Heuristic scores never touch the deny-list.
Fingerprint and IP rules don't go away — they stay on as the cheap first layer for datacenter and scripted bots, where a fingerprint block is safe. Read the deep dive: Closed-Loop Bot Enforcement in Your Cloudflare & AWS WAF
Self-Hosted Captcha and In-Process Detection
The SDK now scores requests inside your own process. The detection engine and a proof-of-work captcha run on your server with no third-party call for scoring. Only optional IP enrichment uses the WebDecoy API.
In-Process Detection Engine
DetectionEngine scores around 40 signals across vision-AI, headless, automation, behavioral, fingerprint, JA3/JA4, and keystroke-cadence detectors into an allow, challenge, or block verdict. The JA4 fingerprint is also the correlation key for WebDecoy's cross-IP actor model. No remote call.
Proof-of-Work Captcha
HMAC-signed SHA-256 challenges with difficulty scaling, replay protection, and the signals bound into the work. Issues single-use, IP-bound session tokens. A self-hosted alternative to reCAPTCHA, hCaptcha, and Turnstile.
Browser Widget
The new @webdecoy/client package collects the signals, solves the proof-of-work, and submits to your server. Checkbox, invisible, and on-demand modes.
import { WebDecoyCaptcha } from '@webdecoy/client';
WebDecoyCaptcha.configure({
serverUrl: 'https://your-server.com'
});
// Checkbox widget
WebDecoyCaptcha.render('captcha-box', {
siteKey: 'pk_live_...',
callback: (token) => submit(token)
});
// Or protect a form invisibly
WebDecoyCaptcha.invisible({ siteKey: 'pk_live_...' });import express from 'express';
import { webdecoyCaptcha } from '@webdecoy/express';
import { Captcha } from '@webdecoy/node';
const app = express();
app.use(express.json());
// Serves /__webdecoy/challenge, /verify,
// /score, and /token/verify
app.use(webdecoyCaptcha({
secret: process.env.WEBDECOY_SECRET
}));
// Verify the token on a protected route
const captcha = new Captcha({
secret: process.env.WEBDECOY_SECRET
});
app.post('/login', (req, res) => {
const { valid } = captcha.verifyToken(
req.body.webdecoy_token,
req.ip
);
if (!valid) {
return res.status(403).json({ error: 'captcha failed' });
}
// proceed with login
});Read the deep dive: Self-Hosted Captcha for Node.js (SDK v0.3.0)
Quick Start
Initialize the SDK with your API key and start verifying bot scanner results from your backend.
API Key Authentication
Use your API key from the WebDecoy dashboard
Async/Await Support
Modern Promise-based API
TypeScript Types
Full type definitions included
import { WebDecoy } from '@webdecoy/node';
const webdecoy = new WebDecoy({
apiKey: process.env.WEBDECOY_API_KEY
});
// Check a request before processing it
app.post('/api/submit', async (req, res) => {
const { allowed, detection } = await webdecoy.protect({
method: req.method,
path: req.path,
ip: req.ip,
user_agent: req.get('user-agent'),
headers: req.headers
});
if (!allowed) {
return res.status(403).json({
error: 'Bot detected',
threat: detection.threat_level
});
}
// Process legitimate request
});import crypto from 'crypto';
app.post('/webhooks/webdecoy',
express.raw({ type: 'application/json' }),
(req, res) => {
const signature = req.headers['x-webdecoy-signature'];
const expected = 'sha256=' + crypto
.createHmac('sha256', process.env.WEBHOOK_SECRET)
.update(req.body)
.digest('hex');
const valid = signature && crypto.timingSafeEqual(
Buffer.from(signature), Buffer.from(expected)
);
if (!valid) {
return res.status(401).send('Invalid signature');
}
// Route by event type; dedupe by delivery ID
const event = req.headers['x-webdecoy-event'];
const delivery = req.headers['x-webdecoy-delivery'];
res.status(200).send('OK');
}
);Webhook Validation
Every webhook WebDecoy sends is signed with HMAC-SHA256 over the raw payload. Verifying takes a few lines of Node's built-in crypto — no extra dependency.
X-WebDecoy-Signaturecrypto.timingSafeEqualFramework-Specific Packages
Install the core SDK or use our framework-specific packages with built-in middleware.
Core SDK
npm install @webdecoy/nodeWorks with any framework
Browser Client
npm install @webdecoy/clientCaptcha widget
Express
npm install @webdecoy/expressMiddleware included
Fastify
npm install @webdecoy/fastifyPlugin included
Next.js
npm install @webdecoy/nextjsMiddleware wrapper
Express Middleware
The Express package provides middleware that automatically analyzes every request and attaches detection results.
import express from 'express';
import { webdecoy } from '@webdecoy/express';
const app = express();
// Apply globally — blocked requests get a 403
app.use(webdecoy({
threshold: 70,
skipPaths: ['/health', '/static'],
onBlocked: (req, res, detection) => {
res.status(403).json({ error: 'Blocked' });
}
}));
// Detection results attached to req.webdecoy
app.post('/api/login', (req, res) => {
const { decision, confidence, threat_level } = req.webdecoy;
if (decision === 'challenge') {
return res.status(429).json({
error: 'Please complete verification'
});
}
// Process login...
});import Fastify from 'fastify';
import webdecoyPlugin from '@webdecoy/fastify';
const fastify = Fastify();
// Register the plugin
await fastify.register(webdecoyPlugin, {
threshold: 70,
skipPaths: ['/health']
});
fastify.post('/api/checkout', async (req, reply) => {
// Detection attached to the request
const { decision, confidence, bot_detected } = req.webdecoy;
if (decision === 'block') {
return reply.code(403).send({
error: 'Request blocked'
});
}
if (decision === 'challenge') {
return reply.code(429).send({
error: 'Verification required'
});
}
// Process checkout...
});Fastify Plugin
Register WebDecoy as a Fastify plugin. Detection data is automatically attached to every request object.
Next.js Middleware
Protect your Next.js app at the edge with middleware that runs before every request.
import { withWebDecoy } from '@webdecoy/nextjs';
import { NextResponse } from 'next/server';
export default withWebDecoy({
threshold: 70,
// Customize what blocked requests receive
onBlocked: (request, detection) => {
return NextResponse.json(
{
error: 'Blocked',
threat: detection.threat_level
},
{ status: 403 }
);
}
});
export const config = {
matcher: ['/api/:path*', '/checkout/:path*']
};Detection Response
Every check returns a clear decision plus the analysis behind it.
{
"decision": "block",
"confidence": 92,
"threat_level": "HIGH",
"bot_detected": true,
"bot_type": "headless_browser",
"detection_id": "det_8f3c2a91",
"rule_enforced": true
}Threat Levels
The Decision Field
allow Pass the request throughchallenge Ask for verification — e.g. the @webdecoy/client captchablock Reject the request (middleware default: 403)Why Use Server-Side Bot Detection
Client-side detection is powerful, but server-side verification makes it tamper-proof.
Tamper-Proof Verification
Attackers cannot modify bot scores or bypass detection by manipulating client-side JavaScript. Server verification is the final authority.
TLS Fingerprinting
The SDK adds JA3/JA4 TLS fingerprint analysis that can only be done server-side, catching bots that spoof browser user agents. The JA4 identity correlates an actor across every IP it rotates through — the cheap first enforcement layer for datacenter bots, with session clearance handling the hard cases.
Real-Time Webhooks
Receive instant notifications when bots are detected. Trigger automated responses in your backend without polling.
Available SDKs
WebDecoy provides official SDKs for multiple languages and platforms.
Browser
Client-side signals, captcha widget, and session clearance. Checkbox, invisible, and on-demand modes.
npm install @webdecoy/client Or use the Detection ScriptNode.js
Express, Next.js, NestJS, Fastify. Full TypeScript support.
npm install @webdecoy/node View on GitHubLearn More About SDK Integration
Guides and tutorials for integrating WebDecoy — in the browser and in your backend.
Tripwires: Deterministic Scraper Detection
Catch stealth scrapers that beat fingerprinting with hidden honeytoken links and a zero-false-positive block.
Closed-Loop Bot Enforcement in Your WAF
How composite actor signatures, graduated actions, and session clearance make verdicts stick in Cloudflare and AWS WAF.
SDK v0.3.0: Self-Hosted Captcha
In-process detection and a proof-of-work captcha you run yourself, with a browser widget.
SDK Launch: TLS Fingerprinting
Learn how JA3/JA4 fingerprinting detects bots by analyzing TLS handshakes.
SIEM Integration Guide
Forward bot detections to Splunk, Elastic, and CrowdStrike for SOC visibility.
WebDecoy & WAAP Integration
How WebDecoy fits into your Web Application and API Protection strategy.
See also: Bot Scanner for client-side detection, Threat Scoring for automated responses, and Integrations for WAF connections.
Frequently Asked Questions
Common questions about the WebDecoy Node.js SDK.
Does WebDecoy have a client-side SDK, or only server-side?
Both, and they are designed to work together. The client side is @webdecoy/client — a browser SDK that collects behavioral and device signals, runs the self-hosted captcha widget, and earns session clearance — or the no-code Detection Script, a single tag with the full detection engine. The server side is @webdecoy/node (plus Go and PHP SDKs), which verifies results where bots cannot tamper with them and makes the allow, challenge, or block decision.
Can the SDK verify AI agents like GPTBot cryptographically?
Yes. @webdecoy/node verifies Web Bot Auth (RFC 9421) signatures locally in your middleware via detectBot(), or as a drop-in webBotAuth() rule. Key directories are cached ahead of time so the warm path does no network I/O and verification runs under 5ms at p95, on both Node and the Vercel Edge runtime. The verdict is verified, claimed, impersonation, or none — the same taxonomy the detection pipeline and the edge validator use.
What does an "impersonation" verdict mean?
It means the request claimed an identity that could be checked and failed the check — a signing agent's user agent with an invalid or missing signature, or a crawler arriving from outside its operator's published IP ranges. That is not a heuristic guess; it is a request caught in a lie, so the webBotAuth() rule denies it by default. A legitimate crawler that simply does not sign yet degrades to "claimed" and is never accused.
Why do I need server-side verification with the SDK?
Client-side bot detection can be tampered with by sophisticated attackers. The SDK allows you to verify detection tokens server-side, ensuring that bot scores have not been modified. This two-layer approach combines client-side signals with tamper-proof server verification.
Which Node.js frameworks are supported?
The SDK works with any Node.js framework including Express, Fastify, Next.js, NestJS, Koa, and Hapi. It provides simple middleware integration patterns and works with both JavaScript and TypeScript projects with full type definitions included.
How do I validate incoming webhooks from WebDecoy?
Every webhook is signed with HMAC-SHA256 over the raw request body, sent as sha256=<hex> in the X-WebDecoy-Signature header. Recompute the HMAC with your webhook secret and compare with a constant-time check (crypto.timingSafeEqual in Node). Each delivery also carries X-WebDecoy-Event for routing and a unique X-WebDecoy-Delivery ID you can use for idempotency.
What data does the detection response include?
Every check returns a decision (allow, challenge, or block), a confidence score (0-100), a threat level from MINIMAL to CRITICAL, whether a bot was detected and its type, a detection ID for cross-referencing the dashboard, and whether a response rule was enforced. You can use this data to make access control decisions in your application.
Are there SDKs for other languages besides Node.js?
Yes. WebDecoy also provides SDKs for Go and PHP (with WordPress integration). All SDKs support the same core functionality: token verification, webhook validation, and API access. See our documentation for Go and PHP integration guides.
Does the SDK send my traffic to a third party for scoring?
Not in v0.3.0. The detection engine and proof-of-work captcha run in your own process, so the allow, challenge, or block decision is made locally with no remote call. The only optional outbound request is IP enrichment (VPN, proxy, Tor, abuse score, geo) against the WebDecoy API, which you can disable.
Can WebDecoy replace reCAPTCHA, hCaptcha, or Turnstile?
Yes. v0.3.0 ships a self-hosted captcha: an HMAC-signed proof-of-work challenge plus the @webdecoy/client browser widget. You hold the signing secret and the widget posts to your own domain, so there is no third-party captcha script watching your visitors. It runs as a checkbox, invisibly, or on demand.
What is session clearance and how does it defeat IP rotation?
Session clearance flips enforcement from blocklisting bad fingerprints to allowlisting proven sessions. A real browser passes WebDecoy’s client-side checks and its session carries signed clearance that protected routes verify. Because clearance travels with the client rather than the IP address, rotating IPs resets nothing — and a client that trips a decoy is refused new clearance on any IP.
How do tripwires and session clearance work together?
A tripwire hit is deterministic proof of a bot — no one follows a hidden honeytoken link by accident. The SDK forwards the session's clearance token with the violation, and the client is denied clearance durably, on every IP — identical to tripping a hosted decoy. By design, only deception signals drive that deny-list: heuristic rules like rate limits and filters never carry the token, so enforcement stays proof-based rather than score-based.
Ready to integrate bot detection?
Install the browser and server SDKs and close the loop from detection to enforcement in minutes.
View npm Package