Skip to content

Node SDK

The WebDecoy Node SDK provides server-side bot detection and threat intelligence for Node.js applications. It enables deep integration with Express, Next.js, Fastify, and other Node.js frameworks.

Note: The Node SDK is currently in development. This documentation reflects the planned API and features.

FeatureDescription
Bot DetectionAnalyze requests for automation signals
Threat ScoringCalculate unified threat scores
IP IntelligenceAccess reputation and geolocation data
TLS FingerprintingJA3/JA4 fingerprint analysis
Detection SubmissionSend detections to WebDecoy
Framework MiddlewareExpress, Next.js, Fastify integration
Use CaseSDK Benefit
Custom Node.js appsFull control over detection logic
API protectionServer-side request analysis
High-traffic sitesEfficient server-side processing
Sensitive endpointsDeep request inspection
Custom integrationsProgrammatic access to detections

Terminal window
npm install webdecoy
# or
yarn add webdecoy
Terminal window
# Express
npm install @webdecoy/express
# Next.js
npm install @webdecoy/nextjs
# Fastify
npm install @webdecoy/fastify
  • Node.js 16.x or later
  • npm 7.x or later
  • WebDecoy API key

const { WebDecoyClient } = require('webdecoy');
const client = new WebDecoyClient({
apiKey: process.env.WEBDECOY_API_KEY,
// Optional settings
baseUrl: 'https://api.webdecoy.com',
timeout: 10000,
retries: 3
});
.env
WEBDECOY_API_KEY=sk_live_your_api_key_here
WEBDECOY_ORGANIZATION_ID=org_optional_override
const { WebDecoyClient, BotDetector } = require('webdecoy');
const client = new WebDecoyClient({
apiKey: process.env.WEBDECOY_API_KEY
});
const detector = new BotDetector({
sensitivity: 'medium',
allowSearchEngines: true
});
// In your request handler
async function handleRequest(req, res) {
// Analyze the request
const result = await detector.analyze({
ip: req.ip,
userAgent: req.headers['user-agent'],
headers: req.headers,
url: req.url,
method: req.method
});
// Check if should block
if (result.shouldBlock(75)) {
return res.status(403).json({ error: 'Access denied' });
}
// Continue with request
// ...
}
const result = await detector.analyze(request);
// Properties
result.score // 0-100 unified threat score
result.threatLevel // 'MINIMAL', 'LOW', 'MEDIUM', 'HIGH', 'CRITICAL'
result.botScore // 0-100 bot likelihood score
result.flags // Array of detection flags
result.isBot // Boolean: likely a bot
result.isGoodBot // Boolean: known legitimate bot
result.botName // Name if identified (e.g., 'Googlebot')
result.botCategory // Category (e.g., 'search_engine')
result.confidence // 0.0-1.0 confidence level
// Methods
result.shouldBlock(threshold) // true if score >= threshold
result.shouldChallenge(threshold)// true if score in challenge range
result.shouldLog() // true if score warrants logging
result.isLegitimate() // true if score < 20
// Submit a detection to WebDecoy
await client.submitDetection({
source: 'sdk',
ipAddress: req.ip,
userAgent: req.headers['user-agent'],
url: req.url,
method: req.method,
threatScore: result.score,
flags: result.flags,
metadata: {
customField: 'value'
}
});

const express = require('express');
const { webDecoyMiddleware } = require('@webdecoy/express');
const app = express();
// Apply globally
app.use(webDecoyMiddleware({
apiKey: process.env.WEBDECOY_API_KEY,
sensitivity: 'medium',
blockThreshold: 75,
allowSearchEngines: true,
excludePaths: ['/health', '/metrics']
}));
// Or apply to specific routes
app.post('/api/login',
webDecoyMiddleware({ blockThreshold: 60 }),
loginHandler
);
app.listen(3000);
OptionDefaultDescription
apiKeyRequiredYour WebDecoy API key
sensitivity’medium’Detection sensitivity
blockThreshold75Score threshold to block
challengeThreshold50Score threshold to challenge
allowSearchEnginestrueBypass for search bots
allowSocialBotstrueBypass for social bots
excludePaths[]Paths to skip
excludeMethods[‘OPTIONS’]HTTP methods to skip
onDetectionnullCustom detection handler
onBlocknullCustom block handler
middleware.js
import { withWebDecoy } from '@webdecoy/nextjs';
export default withWebDecoy({
apiKey: process.env.WEBDECOY_API_KEY,
blockThreshold: 75,
matcher: ['/api/:path*', '/login']
});
export const config = {
matcher: ['/api/:path*', '/login']
};
pages/api/protected.js
import { withBotProtection } from '@webdecoy/nextjs';
async function handler(req, res) {
res.json({ message: 'Protected content' });
}
export default withBotProtection(handler, {
blockThreshold: 70
});
const fastify = require('fastify')();
const webDecoyPlugin = require('@webdecoy/fastify');
fastify.register(webDecoyPlugin, {
apiKey: process.env.WEBDECOY_API_KEY,
sensitivity: 'medium',
blockThreshold: 75
});
fastify.get('/protected', async (request, reply) => {
// Detection info available on request
const botScore = request.webDecoy.score;
return { score: botScore };
});
fastify.listen({ port: 3000 });

const { SignalCollector } = require('webdecoy');
const collector = new SignalCollector();
// Collect signals from request
const signals = collector.collect({
ip: req.ip,
userAgent: req.headers['user-agent'],
headers: req.headers,
// Optional additional signals
tlsFingerprint: req.socket.ja3,
cookies: req.cookies,
bodySize: req.body ? Buffer.byteLength(JSON.stringify(req.body)) : 0
});
// Use with detector
const result = await detector.analyze(signals);
const { IPIntelligence } = require('webdecoy');
const intel = new IPIntelligence(client);
const info = await intel.lookup('192.168.1.100');
// Returns
{
ip: '192.168.1.100',
country: 'US',
city: 'New York',
asn: 12345,
isp: 'Example ISP',
isProxy: false,
isVPN: true,
isTor: false,
isHosting: false,
abuseScore: 25,
riskLevel: 'low'
}
const { TLSFingerprinter } = require('webdecoy');
// In your HTTPS server
const server = https.createServer(options, app);
server.on('secureConnection', (tlsSocket) => {
const fingerprint = TLSFingerprinter.fromSocket(tlsSocket);
// Store fingerprint for later use
tlsSocket.ja3 = fingerprint.ja3;
tlsSocket.ja4 = fingerprint.ja4;
});
const { RateLimiter } = require('webdecoy');
const limiter = new RateLimiter({
windowMs: 60000, // 1 minute
maxRequests: 100,
keyGenerator: (req) => req.ip,
onRateLimit: async (req, key) => {
// Submit as detection
await client.submitDetection({
source: 'sdk',
ipAddress: key,
flags: ['rate_limit_exceeded'],
threatScore: 60
});
}
});
app.use(limiter.middleware());

const client = new WebDecoyClient(options);
// Methods
client.testConnection() // Verify API key
client.submitDetection(detection) // Submit detection
client.getDetections(filters) // Query detections
client.blockIP(ip, hours, reason) // Manual IP block
client.unblockIP(ip) // Remove IP block
const detector = new BotDetector(options);
// Methods
detector.analyze(request) // Analyze request
detector.setConfig(options) // Update configuration
detector.getSignalCollector() // Get signal collector
const detection = {
source: 'sdk',
ipAddress: '192.168.1.100',
userAgent: 'Mozilla/5.0...',
url: '/api/endpoint',
method: 'POST',
threatScore: 75,
botScore: 80,
flags: ['headless_browser', 'missing_headers'],
mitreTactic: {
id: 'TA0043',
name: 'Reconnaissance'
},
metadata: {
// Custom fields
}
};

const { WebDecoyError, RateLimitError, AuthError } = require('webdecoy');
try {
await client.submitDetection(detection);
} catch (error) {
if (error instanceof AuthError) {
console.error('Invalid API key');
} else if (error instanceof RateLimitError) {
console.error('Rate limited, retry after:', error.retryAfter);
} else if (error instanceof WebDecoyError) {
console.error('API error:', error.message);
} else {
throw error;
}
}

  • Initialize client once, reuse across requests
  • Use async/await for non-blocking detection
  • Cache IP intelligence lookups
  • Use exclude patterns for static assets
  • Store API key in environment variables
  • Validate detection results before blocking
  • Log detection decisions for audit
  • Set appropriate timeout values
  • Start with logging mode before blocking
  • Monitor false positive rates
  • Adjust thresholds based on traffic
  • Combine with client-side bot scanner

const express = require('express');
const { WebDecoyClient, BotDetector } = require('webdecoy');
const { webDecoyMiddleware } = require('@webdecoy/express');
const app = express();
// Initialize client
const client = new WebDecoyClient({
apiKey: process.env.WEBDECOY_API_KEY
});
// Global protection (logging mode)
app.use(webDecoyMiddleware({
apiKey: process.env.WEBDECOY_API_KEY,
blockThreshold: 90, // Only block very high scores
onDetection: (req, result) => {
console.log(`Detection: ${req.ip} - Score: ${result.score}`);
}
}));
// Stricter protection for sensitive endpoints
app.post('/api/login',
webDecoyMiddleware({
apiKey: process.env.WEBDECOY_API_KEY,
blockThreshold: 60,
sensitivity: 'high'
}),
async (req, res) => {
// Login logic
}
);
// Custom detection logic
app.post('/api/checkout', async (req, res) => {
const detector = new BotDetector({ sensitivity: 'high' });
const result = await detector.analyze({
ip: req.ip,
userAgent: req.headers['user-agent'],
headers: req.headers
});
if (result.shouldBlock(70)) {
await client.submitDetection({
source: 'sdk',
ipAddress: req.ip,
url: '/api/checkout',
threatScore: result.score,
flags: result.flags
});
return res.status(403).json({ error: 'Request blocked' });
}
// Process checkout
});
app.listen(3000);