
重み付けスコアリング、行動分析、ブラウザフィンガープリンティング、設定可能なしきい値を備えたクライアントサイドのボットおよび自動化検出ライブラリ。ヘッドレスブラウザ、Selenium、Puppeteer、Playwright、CDPベースのツール、ステルス自動化フレームワークを検出します。
v2.1.0 — アンチ検出ハニーポット、GPU安定なキャンバスフィンガープリンティング、強化された行動分析、遅延初期化、サーバーサイド改ざん検出、リクエストフィンガープリントバインディング、レート制限。
human、suspicious、bot に対応するフリクションアクション(monitor、challenge、block)Browser Your Server
┌──────────────────────────┐ ┌──────────────────────┐
│ Collector (singleton) │ POST │ Express Middleware │
│ ├─ 28 detection modules│ signals │ ├─ NonceManager │
│ ├─ BehaviorTracker │ + nonce │ ├─ RateLimiter │
│ ├─ HoneypotTraps │───────────▶│ ├─ TamperDetector │
│ ├─ Stack trace traps │ │ ├─ computeVerdict() │
│ └─ IframeContext │ │ └─ Proof-of-Work │
│ │ verdict │ │
│ ↓ collect() → │ + proof │ Returns: │
│ DetectionResult[] │◀───────────│ { verdict, score, │
└──────────────────────────┘ │ confidence, proof, │
│ tamperScore } │
└──────────────────────┘
│
▼
Session-gated endpoint
(login, checkout, etc.)
validates proof before
granting access
主要な原則: ブラウザは生の DetectionResult[] シグナルのみを収集します。サーバーが秘密の重みテーブルを使用して最終判定を計算します。クライアントで計算された判定は決して信頼されません。
npm install
npm run build
dist/ に出力:
botdetect.min.js (ポリフィル付き, ~151 KB)botdetect-clean.min.js (最新ブラウザのみ, ~74 KB)<script src="/path/to/botdetect.min.js"></script>
<script>
BotDetect.collector.enableTraps();
BotDetect.collector.enableBehavioralTracking();
BotDetect.collector.enableHoneypots();
</script>
cd server
npm install express cors express-session
node example-integration.js
async function onLogin() {
const { nonce } = await (await fetch('/api/botdetect/nonce')).json();
BotDetect.collector.setNonce(nonce);
const signals = await BotDetect.collector.collect();
const resp = await fetch('/api/botdetect/verify', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ signals, nonce })
});
const { verdict, score, proof, friction } = await resp.json();
document.getElementById('botdetect-proof').value = proof;
document.getElementById('login-form').submit();
}
app.post('/api/login', (req, res) => {
const bd = req.session.botdetect;
if (!bd) return res.status(403).json({ error: 'no_verification' });
if (bd.verdict === 'bot') return res.status(403).json({ error: 'access_denied' });
if (bd.verdict === 'suspicious') return challengeCaptcha(req, res);
res.json({ success: true });
});
import Collector from './collector/Collector';
// またはグローバル: BotDetect.collector
| メソッド | 戻り値 | 説明 |
|---|---|---|
getInstance(config?) | Collector | シングルトンアクセサー |
configure(config) | void | 実行時に設定を更新 |
getConfig() | CollectorConfig | 現在の設定 |
init() | void | トラップ、トラッキング、ハニーポットを遅延初期化 |
enableTraps() | void | DOM APIにスタックトレーストラップをインストール |
enableBehavioralTracking() | void | マウス/キーボード/スクロールの監視を開始 |
enableHoneypots(container?) | void | ハニーポットフィールドをインストール |
collect() | Promise<DetectionResult[]> | すべての検出を実行 |
setNonce(nonce) | void | サーバー発行のnonceを保存 |
getSessionId() | string | 一意のセッション識別子 |
getFingerprint() | string | セッションのフィンガープリントハッシュ |
resetBehavioralData() | void | 行動データをクリア |
destroy() | void | すべてのリスナーとDOM要素をクリーンアップ |
import Detector from './detector/Detector';
| メソッド | 戻り値 | 説明 |
|---|---|---|
getInstance(config?) | Detector | シングルトンアクセサー |
configure(config) | void | 設定を更新 |
analyze(results) | DetectionVerdict | スコアリング + 分類(ローカルデバッグのみ) |
handleError(error) | DetectionVerdict | エラー時のフォールバック判定 |
警告:
analyze()はブラウザ内で完全に実行されます。本番環境の判断にその出力を使用しないでください。
interface DetectionResult {
name: string; // Module name
score: number; // 0.0 – 1.0
weight: number; // 1 – 10 (importance)
detail?: string; // Human-readable description
}
interface DetectionVerdict {
verdict: 'bot' | 'suspicious' | 'human';
score: number; // 0.0 – 1.0
confidence: number; // 0.0 – 1.0
signals: DetectionResult[];
threshold: number;
friction: 'monitor' | 'challenge' | 'block';
}
interface CollectorConfig {
detectionTimeoutMs: number; // per-module timeout (default: 3000)
enableTraps: boolean;
enableBehavioralTracking: boolean;
enableHoneypots: boolean;
thresholds: { strict: number; balanced: number; relaxed: number };
}
const { createBotDetectEndpoint } = require('./server');
const { router, generateProofOfWork, cleanup } = createBotDetectEndpoint({
secretSalt: process.env.BOTDETECT_SALT,
scoring: {
threshold: 'balanced', // 'strict' | 'balanced' | 'relaxed' | number
minSignals: 2,
signalBoostThreshold: 0.8,
frictionThresholds: { monitor: 0.2, challenge: 0.5, block: 0.8 }
},
nonce: { ttl: 300000 }, // 5-minute nonce expiry
noScript: { timeout: 10000 }, // 10s no-script window
rateLimit: { maxRequests: 10, windowMs: 60000 },
noScriptPaths: ['/api/login', '/api/checkout', '/api/register']
});
app.use('/api', router);
| エンドポイント | メソッド | 目的 |
|---|---|---|
/api/botdetect/nonce | GET | 使い捨てnonceを発行 |
/api/botdetect/verify | POST | シグナルを送信し、署名付き判定を受け取る |
/api/botdetect/midcycle | POST | セッション途中での再検証 |
{
"verdict": "human",
"score": 0.125,
"confidence": 0.85,
"tamperScore": 0,
"friction": "monitor",
"threshold": 0.5,
"proof": "a1b2c3d4e5f6..."
}
const { computeVerdict, RateLimiter, NonceManager } = require('./scoring');
const verdict = computeVerdict(signals, {
threshold: 'balanced',
minSignals: 2,
signalBoostThreshold: 0.8,
frictionThresholds: { monitor: 0.2, challenge: 0.5, block: 0.8 }
});
// verdict.tamperScore > 0 if signal tampering detected