# Bot Management API

## Workers: BotManagement Interface

```typescript
interface BotManagement {
  score: number // 1-99 (Enterprise), 0 if not computed
  verifiedBot: boolean // Is verified bot
  staticResource: boolean // Serves static resource
  ja3Hash: string // JA3 fingerprint (Enterprise, HTTPS only)
  ja4: string // JA4 fingerprint (Enterprise, HTTPS only)
  jsDetection?: {
    passed: boolean // Passed JS detection (if enabled)
  }
  detectionIds: number[] // Heuristic detection IDs
  corporateProxy?: boolean // From corporate proxy (Enterprise)
}

// DEPRECATED: Use botManagement.score instead
// request.cf.clientTrustScore (legacy, duplicate of botManagement.score)

// Access via request.cf
import type { IncomingRequestCfProperties } from '@cloudflare/workers-types'

export default {
  async fetch(request: Request): Promise<Response> {
    const cf = request.cf as IncomingRequestCfProperties | undefined
    const botMgmt = cf?.botManagement

    if (!botMgmt) return fetch(request)
    if (botMgmt.verifiedBot) return fetch(request) // Allow verified bots
    if (botMgmt.score === 1) return new Response('Blocked', { status: 403 })
    if (botMgmt.score < 30) return new Response('Challenge required', { status: 429 })

    return fetch(request)
  },
}
```

## WAF Fields Reference

```txt
# Score fields
cf.bot_management.score                    # 0-99 (0 = not computed)
cf.bot_management.verified_bot             # boolean
cf.bot_management.static_resource          # boolean
cf.bot_management.ja3_hash                 # string (Enterprise)
cf.bot_management.ja4                      # string (Enterprise)
cf.bot_management.detection_ids            # array
cf.bot_management.js_detection.passed      # boolean
cf.bot_management.corporate_proxy          # boolean (Enterprise)
cf.verified_bot_category                   # string

# Workers equivalent
request.cf.botManagement.score
request.cf.botManagement.verifiedBot
request.cf.botManagement.ja3Hash
request.cf.botManagement.ja4
request.cf.botManagement.jsDetection.passed
request.cf.verifiedBotCategory
```

## JA4 Signals (Enterprise)

```typescript
import type { IncomingRequestCfProperties } from '@cloudflare/workers-types'

interface JA4Signals {
  // Ratios (0.0-1.0)
  heuristic_ratio_1h?: number // Fraction flagged by heuristics
  browser_ratio_1h?: number // Fraction from real browsers
  cache_ratio_1h?: number // Fraction hitting cache
  h2h3_ratio_1h?: number // Fraction using HTTP/2 or HTTP/3
  // Ranks (relative position in distribution)
  uas_rank_1h?: number // User-Agent diversity rank
  paths_rank_1h?: number // Path diversity rank
  reqs_rank_1h?: number // Request volume rank
  ips_rank_1h?: number // IP diversity rank
  // Quantiles (0.0-1.0, percentile in distribution)
  reqs_quantile_1h?: number // Request volume quantile
  ips_quantile_1h?: number // IP count quantile
}

export default {
  async fetch(request: Request): Promise<Response> {
    const cf = request.cf as IncomingRequestCfProperties | undefined
    const ja4Signals = cf?.ja4Signals as JA4Signals | undefined

    if (!ja4Signals) return fetch(request) // Not available for HTTP or Worker routing

    // Check for anomalous behavior
    // High heuristic_ratio or low browser_ratio = suspicious
    const heuristicRatio = ja4Signals.heuristic_ratio_1h ?? 0
    const browserRatio = ja4Signals.browser_ratio_1h ?? 0

    if (heuristicRatio > 0.5 || browserRatio < 0.3) {
      return new Response('Suspicious traffic', { status: 403 })
    }

    return fetch(request)
  },
}
```

## Common Patterns

See [patterns.md](./patterns.md) for Workers examples: mobile app allowlisting, corporate proxy exemption, datacenter detection, conditional delay, and more.

## Bot Analytics

### Access Locations

- Dashboard: Security > Bots (old) or Security > Analytics > Bot analysis (new)
- GraphQL API for programmatic access
- Security Events & Security Analytics
- Logpush/Logpull

### Available Data

- **Enterprise BM**: Bot scores (1-99), bot score source, distribution
- **Pro/Business**: Bot groupings (automated, likely automated, likely human)
- Top attributes: IPs, paths, user agents, countries
- Detection sources: Heuristics, ML, AD, JSD
- Verified bot categories

### Time Ranges

- **Enterprise BM**: Up to 1 week at a time, 30 days history
- **Pro/Business**: Up to 72 hours at a time, 30 days history
- Real-time in most cases, adaptive sampling (1-10% depending on volume)

## Logpush Fields

```txt
BotScore              # 1-99 or 0 if not computed
BotScoreSrc           # Detection engine (ML, Heuristics, etc.)
BotTags               # Classification tags
BotDetectionIDs       # Heuristic detection IDs
```

**BotScoreSrc values:**

- `"Heuristics"` - Known fingerprint
- `"Machine Learning"` - ML model
- `"Anomaly Detection"` - Baseline anomaly
- `"JS Detection"` - JavaScript check
- `"Cloudflare Service"` - Zero Trust
- `"Not Computed"` - Score = 0

Access via Logpush (stream to cloud storage/SIEM), Logpull (API to fetch logs), or GraphQL API (query analytics data).

## Testing with Miniflare

Miniflare provides mock botManagement data for local development:

**Default values:**

- `score: 99` (human)
- `verifiedBot: false`
- `corporateProxy: false`
- `ja3Hash: "25b4882c2bcb50cd6b469ff28c596742"`
- `staticResource: false`
- `detectionIds: []`

**Override in tests:**

```typescript
import { getPlatformProxy } from 'wrangler'

const { cf, dispose } = await getPlatformProxy()
// cf.botManagement is frozen mock object
expect(cf.botManagement.score).toBe(99)
```

For custom test data, mock request.cf in your test setup.
