Bot Detection & Credential Stuffing Prevention with IP Intelligence
Automated bot attacks and credential stuffing cost enterprises $2.8M annually on average. This technical guide shows you how to implement IP-based bot detection, real-time filtering, and credential stuffing prevention using geolocation intelligence and reputation scoring.
Attack Prevention Metrics
The Threat Landscape
Credential stuffing attacks increased 273% in 2025, with botnets automating login attempts across thousands of compromised IP addresses. IP intelligence provides the most reliable signal for detecting automated attacks before they reach your authentication systems, blocking 97%+ of bot traffic with minimal user impact.
Understanding Automated Bot Attack Patterns
Bot attacks follow predictable patterns that IP intelligence can identify. Understanding these attack vectors is critical for designing effective defenses.
Credential Stuffing
Attackers automate login attempts using username/password pairs from previous data breaches across multiple websites.
Rapid login attempts from hosting providers, datacenter IPs, or residential proxy services with inconsistent geolocation patterns.
Account Enumeration
Bots systematically test usernames, email addresses, or phone numbers to identify valid accounts for targeted attacks.
Systematic form submissions from automated sources, repetitive timing patterns, and requests originating from known botnet infrastructure.
Credential Spraying
Low-and-slow attacks that try a few common passwords across many accounts to avoid rate limiting and detection.
Correlation of failed login attempts across unrelated accounts from the same ASN or IP prefix, with patterns indicating automated testing.
Automated Scraping
Bots systematically harvest content, pricing data, or user information from your platforms at scale.
Requests from cloud hosting providers, absence of browser headers, and access patterns indicating systematic content retrieval.
IP-Based Bot Detection Methods
IP intelligence provides multiple orthogonal signals for bot detection. Combining these methods creates a robust defense system that adapts to evolving attack patterns.
1. Infrastructure Classification
Bots typically operate from hosting providers, datacenters, or cloud infrastructure rather than residential networks. Identifying connection types provides the strongest bot signal.
// Infrastructure-based bot detection
async function detectInfrastructureBot(
ipAddress: string
): Promise<BotSignal> {
const ipData = await ipInfoClient.security(ip);
const signals = {
isDatacenter: ipData.connection_type === 'hosting',
isCloudProvider: [
'amazon', 'google', 'microsoft', 'digitalocean',
'linode', 'vultr', 'hetzner', 'ovh'
].some(provider =>
ipData.isp.toLowerCase().includes(provider)
),
isVPS: ipData.is_vps,
isTor: ipData.is_tor,
isHosting: ipData.is_hosting
};
// Calculate bot probability
let botScore = 0;
if (signals.isDatacenter) botScore += 0.6;
if (signals.isCloudProvider) botScore += 0.3;
if (signals.isVPS) botScore += 0.4;
if (signals.isTor) botScore += 0.8;
return {
isBot: botScore > 0.5,
confidence: Math.min(botScore, 1.0),
signals
};
}Datacenter, cloud, VPS infrastructure
Hosting providers, business networks
Residential broadband, mobile networks
2. IP Reputation Scoring
Aggregate historical behavior data to build reputation scores for IP prefixes and ASNs. Known botnet infrastructure receives low scores, flagging requests for additional scrutiny.
// IP reputation scoring
interface IPReputation {
score: number; // 0-100, higher is better
risk: 'low' | 'medium' | 'high' | 'critical';
factors: ReputationFactor[];
}
async function calculateIPReputation(
ipAddress: string,
asn: number,
ipPrefix: string
): Promise<IPReputation> {
const factors: ReputationFactor[] = [];
// Historical fraud rate for this ASN
const asnFraudRate = await reputationDB.getASNRate(asn);
factors.push({
name: 'asn_fraud_history',
impact: asnFraudRate > 0.05 ? -30 : 0,
value: asnFraudRate
});
// Recent bot activity from this /24 prefix
const prefixBotRate = await reputationDB.getPrefixBotRate(ipPrefix);
factors.push({
name: 'prefix_bot_activity',
impact: prefixBotRate > 0.1 ? -40 : 0,
value: prefixBotRate
});
// Age of IP allocation (new IPs more suspicious)
const ipAge = await ipInfoDB.getAllocationAge(ipPrefix);
factors.push({
name: 'ip_allocation_age',
impact: ipAge < 30 ? -20 : 10,
value: ipAge
});
// Calculate aggregate score
const baseScore = 80;
const totalImpact = factors.reduce((sum, f) => sum + f.impact, 0);
const finalScore = Math.max(0, Math.min(100, baseScore + totalImpact));
return {
score: finalScore,
risk: finalScore > 70 ? 'low' :
finalScore > 50 ? 'medium' :
finalScore > 30 ? 'high' : 'critical',
factors
};
}3. Behavioral Pattern Analysis
Analyze request patterns across IP addresses to identify automated behavior. Bots exhibit distinct timing, sequencing, and correlation patterns that differ from human users.
// Behavioral bot detection
interface BehaviorScore {
isAutomated: boolean;
confidence: number;
signals: string[];
}
function analyzeRequestBehavior(
ipRequests: Request[]
): BehaviorScore {
const signals: string[] = [];
let confidence = 0;
// Check for robotic timing patterns
const intervals = calculateIntervals(ipRequests);
const coefficient = stdDev(intervals) / mean(intervals);
if (coefficient < 0.1) {
signals.push('constant_timing_highly_suspicious');
confidence += 0.4;
}
// Check for sequential user IDs/emails
if (detectSequentialTargets(ipRequests)) {
signals.push('sequential_account_targeting');
confidence += 0.3;
}
// Check for identical user-agent strings
const uniqueAgents = new Set(
ipRequests.map(r => r.userAgent)
).size;
if (uniqueAgents === 1 && ipRequests.length > 10) {
signals.push('identical_user_agents');
confidence += 0.2;
}
// Check for form submission without page views
const formSubmissions = ipRequests.filter(
r => r.method === 'POST'
).length;
const pageViews = ipRequests.filter(
r => r.method === 'GET' && r.isPageView
).length;
if (formSubmissions > 5 && pageViews === 0) {
signals.push('form_submission_without_browse');
confidence += 0.3;
}
return {
isAutomated: confidence > 0.5,
confidence: Math.min(confidence, 1.0),
signals
};
}4. Proxy and VPN Detection
Sophisticated bot operators route attacks through proxy networks to bypass IP-based blocking. Modern detection identifies both commercial VPN services and residential proxy infrastructures.
// Proxy and VPN detection
async function detectProxyInfrastructure(
ipAddress: string
): Promise<ProxyDetection> {
const [geoData, securityData] = await Promise.all([
ipInfoClient.geolocation(ipAddress),
ipInfoClient.security(ipAddress)
]);
const detection = {
isProxy: securityData.is_proxy,
proxyType: securityData.proxy_type, // 'vpn', 'tor', 'residential', 'datacenter'
isResidentialProxy: false,
proxyScore: 0
};
// Residential proxy detection
// (ISP claims residential but hosting detected)
if (geoData.connection_type === 'isp' &&
securityData.is_hosting) {
detection.isResidentialProxy = true;
detection.proxyScore += 0.7;
}
// Commercial VPN detection
if (securityData.is_vpn) {
detection.proxyScore += 0.5;
// Check against known VPN exit nodes
const isKnownVPN = await vpnDB.checkExitNode(ipAddress);
if (isKnownVPN) {
detection.proxyScore += 0.3;
}
}
// Tor network detection
if (securityData.is_tor) {
detection.proxyScore += 0.9;
}
// Datacenter proxy detection
if (securityData.is_hosting && !securityData.is_mobile) {
detection.proxyScore += 0.6;
}
return {
...detection,
isProxy: detection.proxyScore > 0.4,
confidence: Math.min(detection.proxyScore, 1.0)
};
}Real-Time Bot Detection Architecture
Production bot detection requires multi-layered architecture that filters traffic before it reaches critical systems. Here is the proven pattern for high-scale platforms.
Multi-Layer Bot Filtering Pipeline
Implementation Example: Middleware Filter
// Express/Next.js middleware for bot detection
import { LRUCache } from 'lru-cache';
const ipCache = new LRUCache<string, BotDecision>({
max: 10000,
ttl: 1000 * 60 * 5, // 5 minutes
});
export async function botDetectionMiddleware(
req: Request,
res: Response,
next: NextFunction
) {
const clientIP = getClientIP(req);
const userAgent = req.headers['user-agent'];
// Check cache first
const cached = ipCache.get(clientIP);
if (cached) {
return handleDecision(cached, req, res, next);
}
// Parallel IP intelligence fetch
const [geoData, securityData, reputation] = await Promise.all([
ipInfoClient.geolocation(clientIP),
ipInfoClient.security(clientIP),
reputationService.score(clientIP)
]);
// Layer 1: Hard block (known bad actors)
if (reputation.score < 30) {
const decision: BotDecision = {
action: 'block',
reason: 'known_malicious_ip',
ttl: 3600
};
ipCache.set(clientIP, decision);
return handleDecision(decision, req, res, next);
}
// Layer 2: Infrastructure filtering
if (securityData.is_hosting || securityData.is_tor) {
// For sensitive endpoints, block; others challenge
const isSensitiveEndpoint =
req.path.includes('/login') ||
req.path.includes('/api/auth');
const decision: BotDecision = isSensitiveEndpoint ? {
action: 'block',
reason: 'hosting_infrastructure',
ttl: 1800
} : {
action: 'challenge',
reason: 'suspicious_infrastructure',
ttl: 900
};
ipCache.set(clientIP, decision);
return handleDecision(decision, req, res, next);
}
// Layer 3: Behavioral analysis (for tracked IPs)
const ipHistory = await requestHistory.get(clientIP);
if (ipHistory && ipHistory.length > 10) {
const behavior = analyzeBehavior(ipHistory);
if (behavior.isAutomated && behavior.confidence > 0.7) {
const decision: BotDecision = {
action: 'block',
reason: 'automated_behavior_pattern',
ttl: 3600
};
ipCache.set(clientIP, decision);
return handleDecision(decision, req, res, next);
}
}
// Layer 4: Rate limiting by IP
const rateLimitStatus = await rateLimiter.check(clientIP);
if (!rateLimitStatus.allowed) {
const decision: BotDecision = {
action: 'challenge',
reason: 'rate_limit_exceeded',
ttl: 600
};
ipCache.set(clientIP, decision);
return handleDecision(decision, req, res, next);
}
// Passed all checks
const decision: BotDecision = {
action: 'allow',
reason: 'all_checks_passed',
ttl: 300
};
ipCache.set(clientIP, decision);
return handleDecision(decision, req, res, next);
}
function handleDecision(
decision: BotDecision,
req: Request,
res: Response,
next: NextFunction
) {
switch (decision.action) {
case 'block':
res.status(403).json({
error: 'Access denied',
message: 'Your request has been blocked.'
});
return;
case 'challenge':
// Redirect to CAPTCHA or JavaScript challenge
res.redirect('/challenge?token=' + generateChallengeToken());
return;
case 'allow':
// Track request for behavioral analysis
requestHistory.track(getClientIP(req), {
path: req.path,
method: req.method,
userAgent: req.headers['user-agent'],
timestamp: Date.now()
});
next();
return;
}
}Credential Stuffing Prevention Strategies
Credential stuffing attacks require specialized detection beyond general bot filtering. These attacks exploit compromised credentials from other breaches and require IP-aware authentication security.
Attack Pattern Recognition
Credential stuffing exhibits distinct IP-level patterns that differ from normal login behavior.
IP-Aware Authentication Security
Strengthen authentication using IP intelligence without adding user friction.
Credential Stuffing Detection Implementation
// Credential stuffing detection service
class CredentialStuffingDetector {
private redis: Redis;
private ipInfo: IPInfoClient;
async checkLoginAttempt(
username: string,
password: string, // hashed
ipAddress: string,
userAgent: string
): Promise<LoginDecision> {
const [ipData, failedAttempts] = await Promise.all([
this.ipInfo.security(ipAddress),
this.getRecentFailedLogins(ipAddress, 3600)
]);
const riskFactors: RiskFactor[] = [];
// Check 1: Multiple failed attempts from this IP
const uniqueAccounts = new Set(
failedAttempts.map(a => a.username)
).size;
if (uniqueAccounts >= 5) {
riskFactors.push({
factor: 'multiple_account_attempts',
weight: 0.8,
description: `IP attempted logins to ${uniqueAccounts} accounts`
});
}
// Check 2: Proxy/VPN usage
if (ipData.is_proxy || ipData.is_vpn) {
riskFactors.push({
factor: 'proxy_infrastructure',
weight: ipData.is_tor ? 0.9 : 0.5,
description: 'Login from anonymous proxy network'
});
}
// Check 3: Datacenter/hosting IP
if (ipData.is_hosting) {
riskFactors.push({
factor: 'hosting_infrastructure',
weight: 0.7,
description: 'Login from datacenter IP'
});
}
// Check 4: Geographic velocity (if user has history)
const userHistory = await this.getUserLocationHistory(username);
if (userHistory.lastLocation) {
const velocity = this.calculateVelocity(
userHistory.lastLocation,
ipData.coordinates,
userHistory.lastLoginTime
);
if (velocity > 900) { // Faster than commercial flight
riskFactors.push({
factor: 'impossible_travel',
weight: 0.95,
description: 'Impossible travel velocity detected'
});
}
}
// Calculate aggregate risk
const totalRisk = riskFactors.reduce(
(sum, factor) => Math.max(sum, factor.weight),
0
);
// Make decision
if (totalRisk >= 0.8) {
return {
allowed: false,
reason: 'high_risk_credential_stuffing',
requireMFA: false,
blockIP: true,
riskFactors
};
}
if (totalRisk >= 0.5) {
return {
allowed: true,
reason: 'medium_risk_require_verification',
requireMFA: true,
blockIP: false,
riskFactors
};
}
return {
allowed: true,
reason: 'normal_login',
requireMFA: false,
blockIP: false,
riskFactors: []
};
}
private async getRecentFailedLogins(
ip: string,
seconds: number
): Promise<FailedLogin[]> {
const key = `failed_logins:${ip}`;
const attempts = await this.redis.zrangebyscore(
key,
Date.now() - (seconds * 1000),
Date.now()
);
return attempts.map(JSON.parse);
}
private calculateVelocity(
from: Coordinates,
to: Coordinates,
timestampMs: number
): number {
const distance = haversine(from, to); // km
const hours = (Date.now() - timestampMs) / 3600000;
return distance / hours; // km/h
}
}Real-World Implementation Results
| Metric | Before IP Detection | After IP Detection | Improvement |
|---|---|---|---|
| Successful Account Takeovers | 247/month | 18/month | -92.7% |
| Credential Stuffing Attempts | 2.3M/month | Blocked (97.3%) | Prevented |
| False Positive Rate | N/A | 0.01% | Minimal Impact |
| Average Detection Latency | Post-login only | 8ms (pre-login) | Proactive |
| Support Tickets (Access Issues) | Baseline | +0.8% | Negligible |
Case Study: B2B SaaS Platform (50K Users)
Implemented IP-based bot detection and credential stuffing prevention in January 2025. Results measured over 6-month period showing 92.7% reduction in successful account takeovers while maintaining 0.01% false positive rate. System now blocks 2.2M credential stuffing attempts monthly before reaching authentication servers. Total implementation cost: $12K/month in IP API costs, preventing an estimated $2.8M in potential fraud losses.
Production Best Practices
Do This
- ✓Implement progressive challenges: Start with invisible checks, escalate to CAPTCHA only when necessary
- ✓Cache IP decisions: Store bot classifications for 5-15 minutes to reduce API calls and latency
- ✓Monitor false positives: Alert on legitimate users incorrectly flagged and whitelist their IPs
- ✓Rate limit by IP prefix: Block entire /24 or /32 subnets when attack patterns emerge
- ✓Log all decisions: Maintain audit trails for blocked requests to review and improve detection
- ✓Test in shadow mode: Run detection without blocking for 2 weeks to measure accuracy
Avoid This
- ✗Don't rely solely on IP: Combine with behavioral signals, device fingerprinting, and request patterns
- ✗Don't block legitimate VPNs: Many remote workers use corporate VPNs; whitelist known business ranges
- ✗Don't ignore mobile networks: Mobile IP addresses change frequently; use wider tolerance for cellular connections
- ✗Don't set block TTLs too long: Legitimate users may share IPs (NAT) or get recycled addresses
- ✗Don't forget geographic diversity: Adjust thresholds for regions with different network characteristics
- ✗Don't skip user communication: Tell users why they were challenged and how to resolve it
Stop Bot Attacks Before They Reach Your App
Get started with IP-based bot detection in under 10 minutes. Test with 1,000 free requests and see the difference.
Frequently Asked Questions
How accurate is IP-based bot detection?
IP-based detection achieves 97%+ accuracy when combining infrastructure classification, reputation scoring, and behavioral analysis. False positive rates typically stay below 0.01% when properly configured. The key is using multiple signals rather than relying on a single detection method.
Won't blocking datacenter IPs block legitimate users who work from cloud offices?
Yes, which is why smart implementations use challenge flows rather than hard blocks for datacenter IPs. Legitimate users can complete a CAPTCHA or JavaScript challenge, while automated bots cannot. For known corporate ranges, implement whitelisting based on ASN or organization name.
How do you handle bot attacks from residential proxy networks?
Residential proxies are detected by correlating IP behavior patterns across many requests. Look for: (1) rapid request rates inconsistent with human behavior, (2) lack of browser headers or JavaScript execution, (3) sequential targeting patterns, and (4) correlation with known proxy service IP ranges. Reputation databases also track identified residential proxy exit nodes.
What is the performance impact of IP-based bot detection on login latency?
With proper caching and parallel API calls, bot detection adds 5-15ms to request processing (P95). Cache hit rates typically exceed 80% for residential IPs, eliminating API calls for most legitimate users. The performance cost is minimal compared to the fraud prevention benefits.
Should I implement IP detection at CDN or application level?
Both. CDN-level filtering blocks known bad IPs and hosting infrastructure before requests reach your servers. Application-level detection handles more sophisticated analysis including behavioral patterns, credential stuffing detection, and user-specific risk scoring. The layered approach provides defense in depth.
Related Articles
Account Takeover Prevention 2024
Comprehensive guide to protecting user accounts from modern attacks.
Real-Time ML Fraud Detection with IP Intelligence
Building ML systems that detect fraud in under 50ms.
VPN Detection for E-commerce Fraud Prevention
Technical guide to identifying anonymous proxy traffic patterns.