> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/TecharoHq/Anubis/llms.txt
> Use this file to discover all available pages before exploring further.

# Bot Policy Configuration

> Bot detection rules and action configuration structs

## Overview

Bot policy configuration defines rules for identifying and handling different types of traffic. Each rule specifies matching criteria and an action to take when traffic matches.

## BotConfig

Defines a bot detection rule with matching criteria and action.

### Type Definition

```go theme={null}
type BotConfig struct {
    UserAgentRegex *string           `json:"user_agent_regex,omitempty" yaml:"user_agent_regex,omitempty"`
    PathRegex      *string           `json:"path_regex,omitempty" yaml:"path_regex,omitempty"`
    HeadersRegex   map[string]string `json:"headers_regex,omitempty" yaml:"headers_regex,omitempty"`
    Expression     *ExpressionOrList `json:"expression,omitempty" yaml:"expression,omitempty"`
    Challenge      *ChallengeRules   `json:"challenge,omitempty" yaml:"challenge,omitempty"`
    Weight         *Weight           `json:"weight,omitempty" yaml:"weight,omitempty"`
    GeoIP          *GeoIP            `json:"geoip,omitempty"`
    ASNs           *ASNs             `json:"asns,omitempty"`
    Name           string            `json:"name" yaml:"name"`
    Action         Rule              `json:"action" yaml:"action"`
    RemoteAddr     []string          `json:"remote_addresses,omitempty" yaml:"remote_addresses,omitempty"`
}
```

### Fields

<ParamField path="Name" type="string" required>
  Unique identifier for this bot rule. Used in logs and metrics.
</ParamField>

<ParamField path="Action" type="Rule" required>
  Action to take when traffic matches this rule. See [Rule enum](#rule-enum).
</ParamField>

<ParamField path="UserAgentRegex" type="*string">
  Regular expression to match against the User-Agent header. Cannot be used with `PathRegex`.
</ParamField>

<ParamField path="PathRegex" type="*string">
  Regular expression to match against the request path. Cannot be used with `UserAgentRegex`.
</ParamField>

<ParamField path="HeadersRegex" type="map[string]string">
  Map of header names to regular expressions. All specified headers must match for the rule to apply.
</ParamField>

<ParamField path="Expression" type="*ExpressionOrList">
  CEL (Common Expression Language) expression for advanced matching logic. See [ExpressionOrList](#expressionorlist).
</ParamField>

<ParamField path="RemoteAddr" type="[]string">
  List of CIDR ranges to match against the client IP address (e.g., `"192.168.1.0/24"`).
</ParamField>

<ParamField path="Challenge" type="*ChallengeRules">
  Challenge configuration when `Action` is `CHALLENGE`. See [challenge-rules](/api/config/challenge-rules).
</ParamField>

<ParamField path="Weight" type="*Weight">
  Weight adjustment when `Action` is `WEIGH`. If not set, defaults to `{Adjust: 5}`.
</ParamField>

<ParamField path="GeoIP" type="*GeoIP">
  Geographic IP matching configuration. See [GeoIP](#geoip).
</ParamField>

<ParamField path="ASNs" type="*ASNs">
  Autonomous System Number matching configuration. See [ASNs](#asns).
</ParamField>

### Validation Rules

* Must set `Name`
* Must set at least one matching criterion: `UserAgentRegex`, `PathRegex`, `HeadersRegex`, `RemoteAddr`, `Expression`, `GeoIP`, or `ASNs`
* Cannot set both `UserAgentRegex` and `PathRegex`
* Regular expressions must not end with newline (use `>-` in YAML instead of `>`)
* `RemoteAddr` entries must be valid CIDR notation
* If `Action` is `CHALLENGE`, must set `Challenge`
* If `Action` is `WEIGH` and `Weight` is nil, defaults to `{Adjust: 5}`

### Example

```yaml theme={null}
bots:
  - name: Block malicious crawlers
    user_agent_regex: >(MJ12bot|AhrefsBot|SemrushBot)
    action: DENY

  - name: Challenge suspicious bots
    expression: weight > 10
    action: CHALLENGE
    challenge:
      algorithm: fast
      difficulty: 20

  - name: Weigh Russian IPs
    geoip:
      countries: ["ru"]
    action: WEIGH
    weight:
      adjust: 15
```

## Rule Enum

Defines actions to take when traffic matches a bot rule.

### Type Definition

```go theme={null}
type Rule string

const (
    RuleUnknown   Rule = ""
    RuleAllow     Rule = "ALLOW"
    RuleDeny      Rule = "DENY"
    RuleChallenge Rule = "CHALLENGE"
    RuleWeigh     Rule = "WEIGH"
    RuleBenchmark Rule = "DEBUG_BENCHMARK"
)
```

### Values

<ParamField path="ALLOW" type="string">
  Immediately allow the request without further checks.
</ParamField>

<ParamField path="DENY" type="string">
  Block the request with a configured status code.
</ParamField>

<ParamField path="CHALLENGE" type="string">
  Present a proof-of-work challenge to the client. Requires `Challenge` configuration.
</ParamField>

<ParamField path="WEIGH" type="string">
  Add weight to the client's score. When thresholds are exceeded, triggers challenges or blocks.
</ParamField>

<ParamField path="DEBUG_BENCHMARK" type="string">
  Debug action for performance testing. Logs timing without affecting traffic.
</ParamField>

## ExpressionOrList

Flexible expression matching supporting single expressions or logical combinations.

### Type Definition

```go theme={null}
type ExpressionOrList struct {
    Expression string   `json:"-" yaml:"-"`
    All        []string `json:"all,omitempty" yaml:"all,omitempty"`
    Any        []string `json:"any,omitempty" yaml:"any,omitempty"`
}
```

### Fields

<ParamField path="Expression" type="string">
  Single CEL expression. Can be set directly as a string in YAML/JSON.
</ParamField>

<ParamField path="All" type="[]string">
  List of CEL expressions that must all evaluate to true (logical AND).
</ParamField>

<ParamField path="Any" type="[]string">
  List of CEL expressions where at least one must evaluate to true (logical OR).
</ParamField>

### Validation Rules

* Must set either `Expression`, `All`, or `Any`
* Cannot set both `All` and `Any`

### Example

```yaml theme={null}
# Single expression
expression: "weight > 10"

# All expressions must match (AND)
expression:
  all:
    - "weight > 5"
    - "request.headers['User-Agent'].contains('bot')"

# Any expression can match (OR)
expression:
  any:
    - "geoip.country == 'CN'"
    - "geoip.country == 'RU'"
```

## GeoIP

Geographic IP address matching based on country codes.

### Type Definition

```go theme={null}
type GeoIP struct {
    Countries []string `json:"countries"`
}
```

### Fields

<ParamField path="Countries" type="[]string" required>
  List of two-letter ISO 3166-1 alpha-2 country codes (case-insensitive).
</ParamField>

### Validation Rules

* Country codes must be exactly 2 letters matching `[a-zA-Z]{2}`
* Country codes are normalized to lowercase

### Example

```yaml theme={null}
geoip:
  countries: ["cn", "ru", "kp"]
```

## ASNs

Autonomous System Number (ASN) matching for network-based rules.

### Type Definition

```go theme={null}
type ASNs struct {
    Match []uint32 `json:"match"`
}
```

### Fields

<ParamField path="Match" type="[]uint32" required>
  List of ASNs to match against the client's network.
</ParamField>

### Validation Rules

* ASNs must not be in private use ranges (RFC 6996):
  * 64512-65534
  * 4200000000-4294967294

### Example

```yaml theme={null}
asns:
  match: [15169, 16509]  # Google and Amazon
```

## Weight

Score adjustment for traffic matching a `WEIGH` rule.

### Type Definition

```go theme={null}
type Weight struct {
    Adjust int `json:"adjust" yaml:"adjust"`
}
```

### Fields

<ParamField path="Adjust" type="int" required>
  Integer value to add to the client's weight score. Can be negative to reduce weight.
</ParamField>

### Example

```yaml theme={null}
weight:
  adjust: 10
```

## ImportStatement

Import bot rules from external files.

### Type Definition

```go theme={null}
type ImportStatement struct {
    Import string      `json:"import"`
    Bots   []BotConfig
}
```

### Fields

<ParamField path="Import" type="string" required>
  Path to YAML file containing bot rules. Use `(data)/` prefix to load from embedded data.
</ParamField>

### Example

```yaml theme={null}
bots:
  - import: "(data)/botPolicies.yaml"
  - name: Custom rule
    user_agent_regex: "CustomBot"
    action: DENY
```

## Errors

```go theme={null}
var (
    ErrNoBotRulesDefined                 = errors.New("config: must define at least one (1) bot rule")
    ErrBotMustHaveName                   = errors.New("config.Bot: must set name")
    ErrBotMustHaveUserAgentOrPath        = errors.New("config.Bot: must set either user_agent_regex, path_regex, headers_regex, or remote_addresses")
    ErrBotMustHaveUserAgentOrPathNotBoth = errors.New("config.Bot: must set either user_agent_regex, path_regex, and not both")
    ErrUnknownAction                     = errors.New("config.Bot: unknown action")
    ErrInvalidUserAgentRegex             = errors.New("config.Bot: invalid user agent regex")
    ErrInvalidPathRegex                  = errors.New("config.Bot: invalid path regex")
    ErrInvalidHeadersRegex               = errors.New("config.Bot: invalid headers regex")
    ErrInvalidCIDR                       = errors.New("config.Bot: invalid CIDR")
    ErrRegexEndsWithNewline              = errors.New("config.Bot: regular expression ends with newline (try >- instead of > in yaml)")
    ErrNotCountryCode                    = errors.New("config.Bot: invalid country code")
    ErrPrivateASN                        = errors.New("bot.ASNs: you have specified a private use ASN")
)
```
