OpenResty
OpenResty

Installation

On your server run the following command:

1
sudo luarocks install botbye-openresty

Configuration

Add the BotBye configuration below to the http block.

server-key available inside your Project.

By default, the configuration is located /usr/local/openresty/nginx/conf/nginx.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
http {
    # ...
    resolver 8.8.8.8;
    lua_ssl_verify_depth 3;
    lua_ssl_trusted_certificate /path/to/certs/ca-certificates.crt;

    lua_shared_dict botbye_state 1m;

    init_by_lua_block {
        require("botbye").setConf({
            # Use your project server-key
            botbye_server_key = '00000000-0000-0000-0000-000000000000';
        });
    }

    init_worker_by_lua_block {
        require("botbye").initRequest()
    }
}

Make sure to replace the lua_ssl_trusted_certificate. For example, Ubuntu certificate path: /etc/ssl/certs/ca-certificates.crt

Usage

1. Add the following BotBye logic to a location block.

For some OpenResty distributions, this part is NOT located inside nginx.conf but in /usr/nginx/conf.d/default.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
server {
    # ...
    location / {
        access_by_lua_block {
            if ngx.req.is_internal() == false then
                local botbye = require("botbye")

                -- Extract the token from wherever you pass it: query param, header, body, etc.
                local token = ngx.var.arg_botbye_token or ""
                local response, _, raw_body = botbye.botValidation(token)

                if response.decision == "BLOCK" then
                    ngx.exit(403)
                end

                -- Propagate result to Level 2
                botbye.propagateResult(response, raw_body)
            end
        }
    }
}

Using ngx.req.is_internal() avoids sending requests to BotBye when the calls are internal.

2. Reload OpenResty.

The command below will gracefully reload the configuration and apply any changes while serving existing connections.

1
sudo service openresty reload

There are three evaluation types — botValidation, riskEvaluation, and fullEvaluation — each suited for a different layer of your infrastructure.

botValidation — edge-level bot check

Use at the edge (OpenResty access phase) when you only need to decide whether the visitor is a bot. The token comes from the client-side SDK.

1
2
3
4
5
6
7
8
9
10
local botbye = require('botbye')
local token = ngx.var.arg_botbye_token or ''
local response, _, raw_body = botbye.botValidation(token)

if response.decision == 'BLOCK' then
    ngx.exit(403)
end

-- Propagate result to Level 2
botbye.propagateResult(response, raw_body)

riskEvaluation — domain-level risk scoring

Use when the backend already knows the user and wants to evaluate a specific business event (login, payment, registration, etc.) without a client-side token.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
local botbye = require('botbye')
local response = botbye.riskEvaluation({
    ip = ngx.var.remote_addr,
    headers = ngx.req.get_headers(),
    user = {
        account_id = '12345',
        email = 'user@example.com',
        username = 'johndoe',
        phone = '+1234567890'
    },
    event_type = 'login',
    event_status = 'SUCCESSFUL',
    botbye_result = nil, -- if a botValidation call was made earlier, pass response.botbye_result here to link the requests; omit if there was no prior botValidation
    custom_fields = {
        region = 'EU'
    }
})

if response.decision == 'BLOCK' then
    ngx.exit(403)
end

Event statuses: SUCCESSFUL, FAILED, ATTEMPTED, UNKNOWN.

Linking botValidation and riskEvaluation events

When the same request is evaluated at two layers — for example, once at the edge (botValidation) and then again inside a backend service (riskEvaluation) — BotBye can link both events and display them as a single event in the dashboard.

Step 1 — edge layer (OpenResty access_by_lua_block): run botValidation and capture the result:

1
2
3
4
5
6
7
8
9
10
11
-- e.g. in access_by_lua_block
local botbye = require('botbye')
local token = ngx.var.arg_botbye_token or ''
local edgeResponse, _, raw_body = botbye.botValidation(token)

if edgeResponse.decision == 'BLOCK' then
    ngx.exit(403)
end

local edgeBotbyeResult = edgeResponse.botbye_result
-- Pass edgeBotbyeResult downstream — an ngx variable, shared dict, upstream header, etc.

Step 2 — domain service (auth, payment, account management): pass it as botbye_result in the riskEvaluation call:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
-- e.g. in a content_by_lua_block handling login
local botbye = require('botbye')
local riskResponse = botbye.riskEvaluation({
    ip = ngx.var.remote_addr,
    headers = ngx.req.get_headers(),
    user = { account_id = userId, email = email },
    event_type = 'login',
    event_status = loginSucceeded and 'SUCCESSFUL' or 'FAILED',
    botbye_result = edgeBotbyeResult,
})

if riskResponse.decision == 'BLOCK' then
    ngx.exit(403)
end

botbye_result is nil when absent — in that case, omit or pass nil and the events will be recorded independently.

fullEvaluation — edge check and domain scoring in one call

Use when you have both the client-side token and the user/event context available at the same point and want to run Level 1 bot validation and Level 2 risk scoring in a single request.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
local botbye = require('botbye')
local token = ngx.var.arg_botbye_token or ''
local response = botbye.fullEvaluation({
    token = token,
    ip = ngx.var.remote_addr,
    headers = ngx.req.get_headers(),
    request_method = ngx.req.get_method(),
    request_uri = ngx.var.request_uri,
    user = {
        account_id = '12345',
        email = 'user@example.com',
        username = 'johndoe',
        phone = '+1234567890'
    },
    event_type = 'login',
    event_status = 'SUCCESSFUL',
    custom_fields = {
        region = 'EU'
    }
})

if response.decision == 'BLOCK' then
    ngx.exit(403)
end

Settings

Setting Description Required Default Value
botbye_server_key Your BotBye server side key yes -
botbye_endpoint Host of the API Server no https://verify.botbye.com
botbye_connection_timeout Timeout for regular API calls no 1000 (in milliseconds)

Demo

Dockerfile with the set up and the configuration to help you to integrate BotBye.

Examples of BotBye API responses

Blocked (bot detected):

1
2
3
4
5
6
7
{
  "request_id": "f77b2abd-c5d7-44f0-be4f-174b04876583",
  "decision": "BLOCK",
  "risk_score": 0.95,
  "scores": { "bot": 0.95 },
  "signals": ["AutomationTool"]
}

Allowed:

1
2
3
4
5
6
7
{
  "request_id": "f77b2abd-c5d7-44f0-be4f-174b04876583",
  "decision": "ALLOW",
  "risk_score": 0.05,
  "scores": { "bot": 0.05, "ato": 0.02 },
  "signals": []
}

Challenge:

1
2
3
4
5
6
7
8
{
  "request_id": "f77b2abd-c5d7-44f0-be4f-174b04876583",
  "decision": "CHALLENGE",
  "risk_score": 0.65,
  "scores": { "bot": 0.65 },
  "signals": ["SuspiciousFingerprint"],
  "challenge": { "type": "captcha", "token": "..." }
}

Invalid server-key:

1
2
3
4
{
  "decision": "ALLOW",
  "error": { "message": "[BotBye] Bad Request: Invalid Server Key" }
}