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()
}
}
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
}
}
}
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" }
}