Implementation Guide

How to integrate Clawptcha into your bot or website

Quick Start

Get started with Clawptcha in 3 steps:

  1. Fetch a challenge from the API
  2. Solve it (factor the product into primes)
  3. Submit the answer within 5 seconds

That's it! Bots solve this instantly. Humans are too slow.

JavaScript / Node.js

JavaScript
// Clawptcha verification for bots
const API = 'https://verify.clawptcha.com';

async function verifyAsBot() {
  // Step 1: Get a challenge
  const challenge = await fetch(`${API}/challenge`).then(r => r.json());
  console.log(challenge);
  // { id: "...", question: "Find the prime factors of 301", product: 301 }

  // Step 2: Solve it (factor the product)
  const factors = factorize(challenge.product);
  const answer = factors.join(',');  // e.g., "7,43"

  // Step 3: Submit answer (must be < 5 seconds)
  const result = await fetch(`${API}/verify`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      challengeId: challenge.id,
      answer: answer
    })
  }).then(r => r.json());

  if (result.success) {
    console.log('Verified!', result.token);
    return result.token;
  } else {
    console.error('Failed:', result.error);
    return null;
  }
}

// Simple prime factorization (for products of 2 primes)
function factorize(n) {
  for (let i = 2; i <= Math.sqrt(n); i++) {
    if (n % i === 0) {
      return [i, n / i].sort((a, b) => a - b);
    }
  }
  return [n]; // n is prime
}

Python

Python
import requests
import math

API = 'https://verify.clawptcha.com'

def factorize(n):
    """Factor a product of two primes."""
    for i in range(2, int(math.sqrt(n)) + 1):
        if n % i == 0:
            return sorted([i, n // i])
    return [n]

def verify_as_bot():
    # Step 1: Get challenge
    challenge = requests.get(f'{API}/challenge').json()
    print(f"Challenge: {challenge['question']}")

    # Step 2: Solve it
    factors = factorize(challenge['product'])
    answer = ','.join(map(str, factors))

    # Step 3: Submit (within 5 seconds)
    result = requests.post(f'{API}/verify', json={
        'challengeId': challenge['id'],
        'answer': answer
    }).json()

    if result.get('success'):
        print(f"Verified in {result['solveTimeMs']}ms!")
        return result['token']
    else:
        print(f"Failed: {result.get('error')}")
        return None

if __name__ == '__main__':
    token = verify_as_bot()
    print(f"Token: {token}")

cURL / Shell

Shell
# Step 1: Get a challenge
CHALLENGE=$(curl -s https://verify.clawptcha.com/challenge)
echo $CHALLENGE
# {"id":"abc123","question":"Find the prime factors of 301","product":301}

# Step 2: Extract the challenge ID
CHALLENGE_ID=$(echo $CHALLENGE | jq -r '.id')
PRODUCT=$(echo $CHALLENGE | jq -r '.product')

# Step 3: Factor the product (your bot computes this)
# For 301: factors are 7 and 43
ANSWER="7,43"

# Step 4: Submit answer
curl -X POST https://verify.clawptcha.com/verify \
  -H "Content-Type: application/json" \
  -d "{"challengeId":"$CHALLENGE_ID","answer":"$ANSWER"}"

# Response:
# {"success":true,"token":"eyJ...","solveTimeMs":127}

Website Widget

For websites, use the embeddable widget with just two lines of code:

HTML
<!-- Add the script -->
<script src="https://clawptcha.com/widget.js"></script>

<!-- Add the widget container -->
<div class="clawptcha" data-callback="onBotVerified"></div>

<script>
// Callback when verified
function onBotVerified(token, result) {
  console.log('Bot verified!', token);
  // Send token to your backend for validation
}
</script>

Widget Options

Customize the widget with data attributes:

<div class="clawptcha"
     data-theme="dark"
     data-callback="myCallback">
</div>
AttributeValuesDescription
data-themelight, darkWidget color theme (auto-detects by default)
data-callbackfunction nameCalled with (token, result) on success

Programmatic API:

// Render widget programmatically
const widget = Clawptcha.render('#container', {
  theme: 'dark',
  callback: (token, result) => console.log(token)
});

// Auto-solve (for bots)
const token = await Clawptcha.solve(widget);

// Reset widget
widget.reset();

// Check verification status
if (widget.isVerified()) {
  const token = widget.getToken();
}

For Site Owners

Want to protect a route so only bots can access it? Here's the flow:

  1. Bot gets verified through Clawptcha (gets a token)
  2. Bot sends the token to your API
  3. Your server validates the token with Clawptcha
  4. If valid → grant access. If invalid → reject or redirect.

The API returns a simple yes/no:

  • { "success": true } = verified bot
  • { "success": false } = invalid (human, expired, or fake token)
JavaScript
// Express.js middleware example
async function requireBot(req, res, next) {
  const token = req.headers['x-clawptcha-token'];

  // No token? Redirect to verification
  if (!token) {
    return res.status(401).json({
      error: 'Bot verification required',
      verify: 'https://verify.clawptcha.com/challenge'
    });
  }

  // Validate token with Clawptcha
  const check = await fetch(
    `https://verify.clawptcha.com/success?token=${token}`
  ).then(r => r.json());

  if (check.success) {
    next(); // ✅ Verified bot - allow access
  } else {
    res.status(403).json({ error: 'Invalid token' });
  }
}

// Protect your route
app.get('/api/bot-only-data', requireBot, (req, res) => {
  res.json({ secret: 'Only bots can see this!' });
});

Security Best Practices

Server-Side Validation
Always validate tokens on your server using the /success endpoint. Never trust client-side verification alone.

Token Expiry
Tokens expire after 1 hour. Request new verification for long-running sessions.

Rate Limiting
The API rate limits to 10 attempts per IP per 5 minutes. Implement your own limits too.

Time Window
Bots must solve within 5 seconds. This naturally filters out humans.