Operations

Behaviour on outage, key rotation, server examples, domains and content security policy.

Error handling & fail-open

If the CaptchaCore service is unreachable, the behavior can be configured:

Fail-open (default)

Forms are still let through. Availability > security during an outage. Recommended for most sites.

CAPTCHACORE_FAIL_OPEN=true

Fail-closed

Forms are blocked if the service does not respond. Only for highly critical systems.

CAPTCHACORE_FAIL_OPEN=false

All API calls have a 3-second timeout. On timeout, your fail-open/closed configuration takes over.

Keys & rotation

Every site has a key pair: a site key (public, in the browser) and a secret key (secret, server only).

Key formats

cc_pub_6e65b5c4597a688c93f3be6e345ee1a5...  ← 7 + 64 hex = 71 Zeichen
cc_sec_8bb043aa6424a1fdb3e048d2d3232894...  ← 7 + 64 hex = 71 Zeichen

Key rotation

On rotation, the old key is moved to rotated status and remains valid for another 24 hours. This enables rolling deployments with zero downtime.

active — current key, used for new requests
rotated — previous key, valid for another 24h (configurable)
revoked — instantly invalid, no further requests possible

Secret key security

  • The secret key is stored in the database as a SHA-256 hash
  • The plain text is shown only once after creation
  • Cannot be recovered — if lost, generate a new key
  • Never output in logs, API responses or error messages

Backend examples

The verify endpoint can be called from any backend. Here are examples for common languages:

PHP (no framework)

$token = $_POST['captchacore_token'] ?? '';

$ch = curl_init('https://api.captchacore.eu/api/v2/verify');
curl_setopt_array($ch, [
    CURLOPT_POST           => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT        => 3,
    CURLOPT_HTTPHEADER     => [
        'X-CaptchaCore-Key: cc_sec_DEIN_SECRET',
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'token'     => $token,
        'form_type' => 'contact',
    ]),
]);
$result = json_decode(curl_exec($ch), true);

if (!$result['valid']) {
    die('Bot erkannt.');
}

Node.js

const token = req.body.captchacore_token;

const res = await fetch('https://api.captchacore.eu/api/v2/verify', {
  method: 'POST',
  headers: {
    'X-CaptchaCore-Key': process.env.CAPTCHACORE_SECRET_KEY,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ token, form_type: 'register' }),
});
const { valid, risk_score, action } = await res.json();

if (!valid) return res.status(403).json({ error: 'Bot detected' });

Python

import requests

result = requests.post(
    'https://api.captchacore.eu/api/v2/verify',
    headers={'X-CaptchaCore-Key': 'cc_sec_DEIN_SECRET'},
    json={'token': token, 'form_type': 'login'},
    timeout=3,
).json()

if not result['valid']:
    raise Exception('CaptchaCore verification failed')

Infrastructure & domains

Domain architecture

Domain Purpose Type
api.captchacore.euChallenge, verify, status, versionAPI (JSON)
src-eu.captchacore.euWidget JS + Worker (EU-only CDN)CDN (default)
src.captchacore.euWidget JS + Worker (global CDN)CDN (optional)
captchacore.euWebsite, admin panel, docsFrontend

Content Security Policy (CSP)

If you use a Content Security Policy on your website, the following domains must be allowed:

# Minimal (EU-only CDN + API)
script-src  https://src-eu.captchacore.eu;
connect-src https://api.captchacore.eu https://src-eu.captchacore.eu;
worker-src  blob:;

# Mit globalem CDN (zusätzlich)
script-src  https://src.captchacore.eu;
connect-src https://src.captchacore.eu;

Why these entries?

  • script-src — The widget JS (captchacore-v2.min.js) is loaded from the CDN
  • connect-src (API) — The widget calls /api/v2/challenge via fetch()
  • connect-src (CDN) — The PoW worker is loaded from the CDN via fetch()
  • worker-src blob: — The worker is instantiated as a blob URL (avoids CORS)

CORS headers

CaptchaCore automatically sets the correct CORS headers on all API endpoints. You do not need any CORS configuration on your side. The API responds with:

Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Headers: Content-Type, Accept, X-CaptchaCore-Key

NGINX example for your website

If you have configured a strict CSP on your website:

# NGINX — CSP für CaptchaCore Widget
add_header Content-Security-Policy
  "script-src 'self' https://src-eu.captchacore.eu;
   connect-src 'self' https://api.captchacore.eu https://src-eu.captchacore.eu;
   worker-src 'self' blob:;"