@niksbanna/bot-detector 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +245 -0
- package/dist/bot-detector.cjs.js +2629 -0
- package/dist/bot-detector.cjs.js.map +7 -0
- package/dist/bot-detector.esm.js +2609 -0
- package/dist/bot-detector.esm.js.map +7 -0
- package/dist/bot-detector.iife.js +2631 -0
- package/dist/bot-detector.iife.js.map +7 -0
- package/dist/bot-detector.iife.min.js +1 -0
- package/package.json +57 -0
- package/src/core/BotDetector.js +284 -0
- package/src/core/ScoringEngine.js +134 -0
- package/src/core/Signal.js +181 -0
- package/src/core/VerdictEngine.js +132 -0
- package/src/index.js +273 -0
- package/src/signals/automation/PhantomJSSignal.js +137 -0
- package/src/signals/automation/PlaywrightSignal.js +129 -0
- package/src/signals/automation/PuppeteerSignal.js +117 -0
- package/src/signals/automation/SeleniumSignal.js +151 -0
- package/src/signals/automation/index.js +8 -0
- package/src/signals/behavior/InteractionTimingSignal.js +170 -0
- package/src/signals/behavior/KeyboardPatternSignal.js +235 -0
- package/src/signals/behavior/MouseMovementSignal.js +215 -0
- package/src/signals/behavior/ScrollBehaviorSignal.js +236 -0
- package/src/signals/behavior/index.js +8 -0
- package/src/signals/environment/HeadlessSignal.js +97 -0
- package/src/signals/environment/NavigatorAnomalySignal.js +117 -0
- package/src/signals/environment/PermissionsSignal.js +76 -0
- package/src/signals/environment/WebDriverSignal.js +58 -0
- package/src/signals/environment/index.js +8 -0
- package/src/signals/fingerprint/AudioContextSignal.js +158 -0
- package/src/signals/fingerprint/CanvasSignal.js +133 -0
- package/src/signals/fingerprint/PluginsSignal.js +106 -0
- package/src/signals/fingerprint/ScreenSignal.js +157 -0
- package/src/signals/fingerprint/WebGLSignal.js +146 -0
- package/src/signals/fingerprint/index.js +9 -0
- package/src/signals/timing/DOMContentTimingSignal.js +159 -0
- package/src/signals/timing/PageLoadSignal.js +165 -0
- package/src/signals/timing/index.js +6 -0
package/README.md
ADDED
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
# Bot Detector
|
|
2
|
+
|
|
3
|
+
A production-grade, signal-based JavaScript library for detecting automated browsers and bots. Uses accumulation-based detection where multiple weak signals combine to form strong evidence.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🎯 **Signal-based Detection**: No single check determines bot status
|
|
8
|
+
- ⚖️ **Weighted Scoring**: Each signal contributes based on reliability
|
|
9
|
+
- 🔌 **Extensible Architecture**: Easy to add custom detection signals
|
|
10
|
+
- 🛡️ **Defensive by Default**: Non-blocking, fail-safe checks
|
|
11
|
+
- 🔒 **Privacy-Conscious**: No network calls, no persistent storage, no PII
|
|
12
|
+
- 📦 **Zero Dependencies**: Pure JavaScript, works in any browser
|
|
13
|
+
|
|
14
|
+
## Quick Start
|
|
15
|
+
|
|
16
|
+
### Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install @niksbanna/bot-detector
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### Basic Usage
|
|
23
|
+
|
|
24
|
+
```javascript
|
|
25
|
+
import { detect, detectInstant } from '@niksbanna/bot-detector';
|
|
26
|
+
|
|
27
|
+
// Quick detection (includes behavioral analysis)
|
|
28
|
+
const result = await detect();
|
|
29
|
+
console.log(result.verdict); // 'human', 'suspicious', or 'bot'
|
|
30
|
+
console.log(result.score); // 0-100
|
|
31
|
+
|
|
32
|
+
// Instant detection (no waiting for user interaction)
|
|
33
|
+
const instant = await detectInstant();
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Custom Configuration
|
|
37
|
+
|
|
38
|
+
```javascript
|
|
39
|
+
import { createDetector } from '@niksbanna/bot-detector';
|
|
40
|
+
|
|
41
|
+
const detector = createDetector({
|
|
42
|
+
humanThreshold: 15, // Score < 15 = human
|
|
43
|
+
suspiciousThreshold: 40, // Score 15-40 = suspicious, >= 40 = bot
|
|
44
|
+
detectionTimeout: 3000, // Timeout in ms
|
|
45
|
+
includeInteractionSignals: true, // Include mouse/keyboard tracking
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
const result = await detector.detect();
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Browser Script Tag
|
|
52
|
+
|
|
53
|
+
```html
|
|
54
|
+
<script type="module">
|
|
55
|
+
import { detect } from './dist/bot-detector.esm.js';
|
|
56
|
+
|
|
57
|
+
const result = await detect();
|
|
58
|
+
if (result.verdict === 'bot') {
|
|
59
|
+
// Handle bot detection
|
|
60
|
+
}
|
|
61
|
+
</script>
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Detection Result
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
interface DetectionResult {
|
|
68
|
+
verdict: 'human' | 'suspicious' | 'bot';
|
|
69
|
+
score: number; // 0-100 bot probability score
|
|
70
|
+
confidence: string; // 'low', 'medium', or 'high'
|
|
71
|
+
reason: string; // Human-readable explanation
|
|
72
|
+
triggeredSignals: string[]; // Array of triggered signal IDs
|
|
73
|
+
signals: object; // Detailed results per signal
|
|
74
|
+
detectionTimeMs: number; // Detection duration
|
|
75
|
+
totalSignals: number; // Total signals evaluated
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Signal Categories
|
|
80
|
+
|
|
81
|
+
### Environment Signals
|
|
82
|
+
Detect automation environment indicators:
|
|
83
|
+
- `webdriver` - Detects `navigator.webdriver` flag
|
|
84
|
+
- `headless` - Detects headless browser indicators
|
|
85
|
+
- `navigator-anomaly` - Detects navigator property inconsistencies
|
|
86
|
+
- `permissions` - Detects Permissions API anomalies
|
|
87
|
+
|
|
88
|
+
### Behavioral Signals
|
|
89
|
+
Detect non-human interaction patterns:
|
|
90
|
+
- `mouse-movement` - Tracks mouse patterns (linear paths, teleportation)
|
|
91
|
+
- `keyboard-pattern` - Analyzes keystroke timing
|
|
92
|
+
- `interaction-timing` - Measures time to first interaction
|
|
93
|
+
- `scroll-behavior` - Detects programmatic scrolling
|
|
94
|
+
|
|
95
|
+
### Fingerprint Signals
|
|
96
|
+
Detect inconsistent browser features:
|
|
97
|
+
- `plugins` - Checks for empty/suspicious plugin lists
|
|
98
|
+
- `webgl` - Detects WebGL rendering anomalies
|
|
99
|
+
- `canvas` - Detects canvas fingerprint blocking
|
|
100
|
+
- `audio-context` - Checks AudioContext anomalies
|
|
101
|
+
- `screen` - Detects unusual screen dimensions
|
|
102
|
+
|
|
103
|
+
### Timing Signals
|
|
104
|
+
Detect automation execution patterns:
|
|
105
|
+
- `page-load` - Analyzes page load timing
|
|
106
|
+
- `dom-content-timing` - Analyzes DOM ready patterns
|
|
107
|
+
|
|
108
|
+
### Automation Framework Signals
|
|
109
|
+
Detect specific automation tools:
|
|
110
|
+
- `puppeteer` - Detects Puppeteer artifacts
|
|
111
|
+
- `playwright` - Detects Playwright artifacts
|
|
112
|
+
- `selenium` - Detects Selenium WebDriver
|
|
113
|
+
- `phantomjs` - Detects PhantomJS
|
|
114
|
+
|
|
115
|
+
## Custom Signals
|
|
116
|
+
|
|
117
|
+
Create your own detection signals:
|
|
118
|
+
|
|
119
|
+
```javascript
|
|
120
|
+
import { Signal, BotDetector } from '@niksbanna/bot-detector';
|
|
121
|
+
|
|
122
|
+
class CustomSignal extends Signal {
|
|
123
|
+
static id = 'my-custom-signal';
|
|
124
|
+
static category = 'custom';
|
|
125
|
+
static weight = 0.7; // 0.1 to 1.0
|
|
126
|
+
static description = 'Detects custom bot behavior';
|
|
127
|
+
|
|
128
|
+
async detect() {
|
|
129
|
+
const suspicious = /* your detection logic */;
|
|
130
|
+
const evidence = { /* any data to include */ };
|
|
131
|
+
const confidence = 0.8; // 0 to 1
|
|
132
|
+
|
|
133
|
+
return this.createResult(suspicious, evidence, confidence);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const detector = new BotDetector();
|
|
138
|
+
detector.registerSignal(new CustomSignal());
|
|
139
|
+
const result = await detector.detect();
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## Scoring System
|
|
143
|
+
|
|
144
|
+
The final score is calculated as:
|
|
145
|
+
|
|
146
|
+
```
|
|
147
|
+
score = Σ(signal.weight × signal.confidence × triggered) / Σ(signal.weight) × 100
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Where:
|
|
151
|
+
- `weight`: Signal importance (0.1 to 1.0)
|
|
152
|
+
- `confidence`: Detection certainty (0 to 1)
|
|
153
|
+
- `triggered`: 1 if detected, 0 otherwise
|
|
154
|
+
|
|
155
|
+
### Verdict Thresholds
|
|
156
|
+
|
|
157
|
+
| Score | Verdict |
|
|
158
|
+
|-------|---------|
|
|
159
|
+
| < 20 | `human` |
|
|
160
|
+
| 20-50 | `suspicious` |
|
|
161
|
+
| ≥ 50 | `bot` |
|
|
162
|
+
|
|
163
|
+
## API Reference
|
|
164
|
+
|
|
165
|
+
### Functions
|
|
166
|
+
|
|
167
|
+
#### `detect(options?)`
|
|
168
|
+
Run full detection with all signals.
|
|
169
|
+
|
|
170
|
+
#### `detectInstant()`
|
|
171
|
+
Run detection without waiting for interaction signals.
|
|
172
|
+
|
|
173
|
+
#### `createDetector(options?)`
|
|
174
|
+
Create a configured detector instance.
|
|
175
|
+
|
|
176
|
+
### Classes
|
|
177
|
+
|
|
178
|
+
#### `BotDetector`
|
|
179
|
+
Main orchestrator class.
|
|
180
|
+
|
|
181
|
+
```javascript
|
|
182
|
+
const detector = new BotDetector(options);
|
|
183
|
+
detector.registerSignal(signal); // Add signal
|
|
184
|
+
detector.unregisterSignal(id); // Remove signal
|
|
185
|
+
await detector.detect(); // Run detection
|
|
186
|
+
detector.getScore(); // Get last score
|
|
187
|
+
detector.reset(); // Reset state
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
#### `Signal`
|
|
191
|
+
Base class for detection signals. Extend this to create custom signals.
|
|
192
|
+
|
|
193
|
+
### Options
|
|
194
|
+
|
|
195
|
+
```javascript
|
|
196
|
+
{
|
|
197
|
+
humanThreshold: 20, // Score below = human
|
|
198
|
+
suspiciousThreshold: 50, // Score above = bot
|
|
199
|
+
detectionTimeout: 5000, // Max detection time (ms)
|
|
200
|
+
includeInteractionSignals: true, // Include behavioral signals
|
|
201
|
+
weightOverrides: { // Override signal weights
|
|
202
|
+
'webdriver': 0.5,
|
|
203
|
+
},
|
|
204
|
+
instantBotSignals: [ // Signals that instantly flag as bot
|
|
205
|
+
'webdriver',
|
|
206
|
+
'puppeteer',
|
|
207
|
+
],
|
|
208
|
+
}
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
## Security Considerations
|
|
212
|
+
|
|
213
|
+
⚠️ **Important**: This library is for client-side detection only. It should be used as one layer in a defense-in-depth strategy.
|
|
214
|
+
|
|
215
|
+
1. **Evasion is possible**: Sophisticated bots can spoof signals
|
|
216
|
+
2. **Server-side validation**: Always validate critical actions server-side
|
|
217
|
+
3. **Rate limiting**: Combine with server-side rate limiting
|
|
218
|
+
4. **Obfuscation**: Consider obfuscating detection code in production
|
|
219
|
+
|
|
220
|
+
## Browser Support
|
|
221
|
+
|
|
222
|
+
- Chrome 80+
|
|
223
|
+
- Firefox 75+
|
|
224
|
+
- Safari 13+
|
|
225
|
+
- Edge 80+
|
|
226
|
+
|
|
227
|
+
## Development
|
|
228
|
+
|
|
229
|
+
```bash
|
|
230
|
+
# Install dependencies
|
|
231
|
+
npm install
|
|
232
|
+
|
|
233
|
+
# Build
|
|
234
|
+
npm run build
|
|
235
|
+
|
|
236
|
+
# Run tests
|
|
237
|
+
npm test
|
|
238
|
+
|
|
239
|
+
# Watch mode
|
|
240
|
+
npm run dev
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
## License
|
|
244
|
+
|
|
245
|
+
MIT
|