Documentation

Integrate AirCaptcha in minutes. Keep it invisible for low-risk traffic and show a friendly challenge only when needed.

Overview

AirCaptcha combines lightweight interaction challenges with behavioral signals to distinguish humans from bots. It’s designed to be user-friendly and intentionally visible when needed.

Key Features:

  • User-friendly challenges that are quick (and fun) to solve
  • Adaptive difficulty based on risk signals
  • Encrypted communication (AES-256-GCM)
  • Behavioral signals (mouse movement, timing patterns)
  • Optional proof-of-work for suspicious traffic
  • Automation detection (Selenium, Puppeteer, etc.)

Installation

To use AirCaptcha on your website, you’ll need:

  1. Create an API key pair from your dashboard
  2. Include the client-side script with your Site Key (public)
  3. Verify tokens on your server using your Secret Key (private)

Key Types:

  • ac_site_... - Site Key (public) - Safe to include in frontend code
  • ac_secret_... - Secret Key (private) - Keep secure, only use server-side

Quick start

Here’s the same integration pattern used by the working demo on the demo page (recommended):

<script src="/api/captcha/script.js"></script>

<form id="my-form">
    <input type="email" name="email" required>
    <button id="submit-btn" type="submit" disabled>Submit</button>
</form>

<script>
const submitBtn = document.getElementById('submit-btn');
const form = document.getElementById('my-form');

const captcha = new AirCaptcha({
    apiEndpoint: '/api/captcha',
    encryptionEnabled: true,
    debug: false
});

captcha.on('ready', () => {
    submitBtn.disabled = false;
});

captcha.on('error', () => {
    submitBtn.disabled = true;
});

captcha.init();

form.addEventListener('submit', async (e) => {
    e.preventDefault();

    submitBtn.disabled = true;

    const result = await captcha.execute();
    if (!result.success) {
        submitBtn.disabled = false;
        return;
    }

    submitBtn.disabled = false;
});
</script>

Client-side setup

The client-side script provides the AirCaptcha class. It will present a user-friendly challenge when needed and return a verification token.

const captcha = new AirCaptcha({
    apiEndpoint: '/api/captcha',    // Required: Your captcha API endpoint
    encryptionEnabled: true,        // Recommended: required by this server build
    debug: false                    // Enable console logging
});

Available Methods:

  • init() - Initialize the captcha (call once on page load)
  • execute() - Run verification and get a token
  • reset() - Reset the captcha state
  • on(event, callback) - Listen for events

Events:

  • ready - Captcha initialized and ready
  • success - Verification successful
  • error - An error occurred

Server-side verification

After getting a token from the client, verify it on your server by calling /api/captcha/validate-token.

⚠️ Important: Never expose your Secret Key (ac_secret_...) in client-side code. Only use it on your server.

Server-to-server (recommended): send your secret key in the Authorization header.

# Python example (server-to-server)
import requests

def verify_captcha(token, secret_key, client_ip=None):
    headers = {"Authorization": f"Bearer {secret_key}"}
    payload = {"token": token}
    if client_ip:
        payload["client_ip"] = client_ip  # optional

    response = requests.post(
        "https://your-domain.com/api/captcha/validate-token",
        json=payload,
        headers=headers,
        timeout=5
    )
    data = response.json()
    return data.get("valid", False)
// Node.js example (server-to-server)
const axios = require('axios');

async function verifyCaptcha(token, secretKey, clientIp) {
  const res = await axios.post(
    'https://your-domain.com/api/captcha/validate-token',
    { token, client_ip: clientIp }, // client_ip optional
    { headers: { Authorization: `Bearer ${secretKey}` }, timeout: 5000 }
  );
  return res.data.valid === true;
}

API reference

POST /api/captcha/init

Initialize a new captcha challenge.

Request:
{
    "fingerprint": { ... }  // Browser fingerprint data
}

Response:
{
    "success": true,
    "challenge": {
        "challenge_id": "abc123",
        "type": "interactive",
        "expires_at": 1234567890000
    }
}

POST /api/captcha/verify

Verify a challenge solution.

Request:
{
    "challenge_id": "abc123",
    "solution": { ... },
    "fingerprint": { ... },
    "behavior": { ... }
}

Response:
{
    "success": true,
    "token": "eyJ...",
    "score": 0.15,
    "risk_level": "low"
}

POST /api/captcha/validate-token

Validate a token on your server.

Request:
{
    "token": "eyJ...",
    "client_ip": "203.0.113.10" // optional (useful for server-to-server)
}

Headers (server-to-server):
Authorization: Bearer ac_secret_...

Response:
{
    "valid": true,
    "payload": {
        "challenge_id": "abc123",
        "score": 0.15,
        "verified_at": 1234567890000
    }
}

Configuration

Server-side configuration options (environment variables):

# Security
CAPTCHA_SECRET=your-secret-key-here
CORS_ORIGINS=https://your-domain.com

# Difficulty
POW_DIFFICULTY=4
POW_MAX_DIFFICULTY=6

# Timing
CHALLENGE_EXPIRY_SECONDS=120
TOKEN_EXPIRY_SECONDS=300

# Rate Limiting
RATE_LIMIT_REQUESTS=30
RATE_LIMIT_WINDOW=60

Security best practices

  • Always verify tokens server-side - Never trust client-side verification alone
  • Use HTTPS - All communication should be encrypted
  • Keep your secret key safe - Never expose it in client-side code
  • Monitor your traffic - Watch for unusual patterns
  • Set appropriate rate limits - Prevent brute force attacks
  • Use the risk score - Implement graduated responses based on score

Risk Score Guidelines:

  • 0.0 - 0.2 - Very likely human, allow immediately
  • 0.2 - 0.4 - Probably human, allow with logging
  • 0.4 - 0.6 - Suspicious, consider additional verification
  • 0.6 - 0.8 - Likely bot, show fallback challenge or block
  • 0.8 - 1.0 - Almost certainly bot, block request

Troubleshooting

Captcha not initializing

Check that:

  • The script URL is correct and accessible
  • Your site key is valid
  • There are no JavaScript errors in the console
  • CORS is properly configured on the server

High false positive rate

If legitimate users are being blocked:

  • Lower your score threshold
  • Check that behavioral data is being collected
  • Ensure users have time to interact before verification
  • Adjust your score threshold and consider a friendlier challenge for borderline cases

Token validation failing

Verify that:

  • Tokens are being sent within the expiry window
  • Your secret key matches on client and server
  • The token hasn't been tampered with
  • Client IP hasn't changed between challenge and verification