Integrations → cURL / REST
cURL & raw REST reference
Protocol-level reference. Use this for Go, Ruby, Rust, Laravel, or any language that can make an HTTP request.
The one call you need
# Screen one visitor against the full ZeroBot pipeline curl -s "https://api.zerobot.info/v3/openapi" \ --data-urlencode "license=YOUR_LICENSE_KEY" \ --data-urlencode "ip=8.8.8.8" \ --data-urlencode "domain=yoursite.com" \ --data-urlencode "useragent=Mozilla/5.0" # → {"is_bot": true, "reason": "DATACENTER", "risk_score": 60, ...}
The API accepts GET or POST. For GET, pass parameters in the query string; for POST, use application/x-www-form-urlencoded.
Parameters
| Name | Required | Description |
|---|---|---|
license | Yes | Your license key from the ZeroBot dashboard. |
ip | Yes | Visitor IP (IPv4 or IPv6). |
domain | Yes | Host visitor is on. Must be in your account's authorized domains. |
useragent | Recommended | Visitor User-Agent header. Used by the heuristic layer. |
allowed_countries | Optional | all or comma-separated ISO codes (e.g. US,GB,DE). Non-matching countries get is_bot=true, reason="Country Denied (XX)". |
vpn | Optional | 1 (default) blocks VPN traffic; 0 allows it. |
datacenter | Optional | 1 (default) blocks datacenter IPs; 0 allows them. |
Response fields
{
"username": // encrypted account id (opaque)
"is_bot": // bool — final verdict
"reason": // e.g. "TOR", "VPN", "DATACENTER", "Country Denied (NL)", "ISP", "Clean"
"risk_score": // 0–100
"country_code": // ISO 2-letter lowercase
"country_name": // e.g. "United States"
"asn": // e.g. "AS15169"
"isp": // e.g. "Google LLC"
"hostname": // reverse DNS
"tor": // bool — is a Tor exit node
"vpn": // bool — matched a known VPN range
"datacenter": // bool — matched a known datacenter ASN
"left": // license days remaining
"plan": // plan name
}
Go example
package main import ( "encoding/json" "net/http" "net/url" ) type Verdict struct { IsBot bool `json:"is_bot"` Reason string `json:"reason"` } func check(ip, ua string) (Verdict, error) { q := url.Values{ "license": {"YOUR_KEY"}, "ip": {ip}, "domain": {"yoursite.com"}, "useragent": {ua}, } r, err := http.Get("https://api.zerobot.info/v3/openapi?" + q.Encode()) if err != nil { return Verdict{}, err } defer r.Body.Close() var v Verdict json.NewDecoder(r.Body).Decode(&v) return v, nil }
Ruby example
require 'net/http' require 'json' require 'uri' def zerobot_check(ip, ua) uri = URI('https://api.zerobot.info/v3/openapi') uri.query = URI.encode_www_form( license: ENV['ZEROBOT_KEY'], ip: ip, domain: 'yoursite.com', useragent: ua ) res = Net::HTTP.get_response(uri) JSON.parse(res.body) rescue {} end verdict = zerobot_check(request.remote_ip, request.user_agent) halt 403, "Blocked: #{verdict['reason']}" if verdict['is_bot']
Error codes
| HTTP | Meaning | Most likely cause |
|---|---|---|
200 | OK | Normal response. Inspect is_bot. |
400 | Bad Request | Missing or invalid parameter. Check the error reason. |
401 | Unauthorized | License key missing or invalid. |
403 | Forbidden | Usually "Unauthorized domain" — the domain param isn't in your account's authorized list. |
429 | Rate-limited | Temporary per-license cap reached. Back off for 60s. |
5xx | Server error | Rare. Your client should fail open (treat as is_bot=false) and log. |
More
Full endpoint catalog, auth reference, and the interactive tester live in the API Reference. For ready-made wrappers, see PHP, Node.js, Python, or drop in the WordPress plugin.