CaptchaShield

Overview

CaptchaShield is a modern CAPTCHA solution designed to protect your web applications from bots and automated attacks while providing a seamless experience for legitimate users. This documentation covers everything you need to integrate CaptchaShield into your application.

Integration involves two key steps:

  1. Frontend Integration: Embed the CaptchaShield widget in your forms
  2. Backend Verification: Validate the CAPTCHA token on your server
Security First: Always verify CAPTCHA tokens server-side. Never trust client-side validation alone.

Quick Start

Get started with CaptchaShield in under 5 minutes. This guide shows you the minimal setup required.

Step 1: Get Your API Keys

Sign up at captchashield.com to obtain:

  • Site Key (public key for frontend)
  • Secret Key (private key for backend)

Step 2: Add Widget to Your Form

Insert this HTML in your form:

<form action="/submit" method="POST">
    <!-- Your form fields -->
    <input type="text" name="email" placeholder="Email">

    <!-- CaptchaShield Widget -->
    <div class="captchashield"
         data-sitekey="YOUR_SITE_KEY"
         data-api="https://captchashield.com"
         data-theme="auto"
         data-lang="auto"></div>

    <button type="submit">Submit</button>
</form>

<!-- Load CaptchaShield Script -->
<script src="https://captchashield.com/widget.js" async defer></script>

Step 3: Verify on Server

When your form is submitted, verify the CAPTCHA token:

// PHP Example
$captchaToken = $_POST['captchaToken'];
$secretKey = 'YOUR_SECRET_KEY';

$response = file_get_contents('https://captchashield.com/v1/siteverify', false, stream_context_create([
    'http' => [
        'method' => 'POST',
        'header' => 'Content-Type: application/x-www-form-urlencoded',
        'content' => http_build_query([
            'secret' => $secretKey,
            'response' => $captchaToken,
            'remoteip' => $_SERVER['REMOTE_ADDR']
        ])
    ]
]));

$result = json_decode($response);

if ($result->success) {
    // CAPTCHA verified - process form
} else {
    // CAPTCHA failed - show error
}

That's it! You're now protected by CaptchaShield.

Frontend Widget

The CaptchaShield widget is a customizable component that handles user verification on the client side.

Basic Usage

<div class="captchashield"
     data-sitekey="YOUR_SITE_KEY"
     data-api="https://captchashield.com"></div>

<script src="https://captchashield.com/widget.js" async defer></script>

Widget Attributes

Customize the widget behavior with these data attributes:

data-sitekey (required)

Your public site key obtained from the CaptchaShield dashboard.

data-sitekey="YOUR_SITE_KEY"

data-api (optional)

API endpoint URL. Default: https://captchashield.com

data-api="https://captchashield.com"

data-theme (optional)

Visual theme for the widget. Options: auto, light, dark. Default: auto

<div class="captchashield" data-sitekey="YOUR_SITE_KEY" data-theme="dark"></div>

data-lang (optional)

Language for widget text. Options: auto, en, tr. Default: auto

<div class="captchashield" data-sitekey="YOUR_SITE_KEY" data-lang="en"></div>

data-callback (optional)

Global function name to call when CAPTCHA is successfully completed.

<script>
function onCaptchaSuccess(token) {
    console.log('CAPTCHA token:', token);
    // Auto-submit form or enable submit button
    document.getElementById('myForm').submit();
}
</script>

<div class="captchashield"
     data-sitekey="YOUR_SITE_KEY"
     data-callback="onCaptchaSuccess"></div>

Privacy & Terms Links (optional)

Add links to your privacy policy, terms of service, and GDPR information.

<div class="captchashield"
     data-sitekey="YOUR_SITE_KEY"
     data-privacy="https://yoursite.com/privacy"
     data-terms="https://yoursite.com/terms"
     data-gdpr="https://yoursite.com/gdpr"></div>

Multiple Widgets on One Page

You can render multiple CaptchaShield widgets on the same page. Each will generate its own token.

<form id="loginForm">
    <div class="captchashield" data-sitekey="YOUR_SITE_KEY"></div>
</form>

<form id="registerForm">
    <div class="captchashield" data-sitekey="YOUR_SITE_KEY"></div>
</form>
Token Submission: When the CAPTCHA is completed, the widget automatically adds a hidden input field named captchaToken to the form.

Server Verification

Always verify the CAPTCHA token on your server before processing protected actions. Client-side validation alone is insufficient for security.

Verification Endpoint

POST https://captchashield.com/v1/siteverify

Request Parameters

Send these parameters as form data or JSON:

Parameter Required Description
secret Yes Your secret key from CaptchaShield dashboard
response Yes The CAPTCHA token from the widget
remoteip No User's IP address (recommended)

Response Format

The API returns a JSON response:

{
  "success": true,
  "challenge_ts": "2024-01-27T12:34:56Z",
  "hostname": "yoursite.com",
  "error_codes": []
}
Field Type Description
success boolean true if verification passed
challenge_ts string Timestamp of CAPTCHA completion
hostname string Hostname where CAPTCHA was solved
error_codes array Error codes if verification failed

Verification Flow

  1. User completes CAPTCHA on frontend
  2. Widget generates captchaToken (one-time use)
  3. Form submits to your server with token
  4. Your server sends token to CaptchaShield API for verification
  5. If success: true, process the request
  6. If success: false, reject the request and show error
Security Critical: Tokens are single-use only. Always verify immediately upon receipt and never reuse tokens. Store your secret key securely and never expose it in client-side code.

Security Best Practices

  • Never expose your secret key in frontend code, version control, or logs
  • Verify every token server-side before processing protected actions
  • Tokens are one-time use - verify immediately and don't cache
  • Use HTTPS for all communications
  • Pass user IP via remoteip parameter for enhanced security
  • Implement rate limiting on your endpoints to prevent abuse
  • Handle errors gracefully and provide user-friendly messages
  • Monitor for suspicious patterns like repeated failures

Code Examples

Complete integration examples for popular languages and frameworks.

PHP
Laravel
Node.js
Ruby
Python
Go
Java
.NET
WordPress

PHP with cURL

<?php

function verifyCaptcha($token, $secretKey, $remoteIp = null) {
    $url = 'https://captchashield.com/v1/siteverify';

    $data = [
        'secret' => $secretKey,
        'response' => $token
    ];

    if ($remoteIp) {
        $data['remoteip'] = $remoteIp;
    }

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    $response = curl_exec($ch);
    curl_close($ch);

    return json_decode($response, true);
}

// Usage in form handler
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $captchaToken = $_POST['captchaToken'] ?? '';
    $secretKey = 'YOUR_SECRET_KEY';

    $result = verifyCaptcha(
        $captchaToken,
        $secretKey,
        $_SERVER['REMOTE_ADDR']
    );

    if ($result['success']) {
        // CAPTCHA verified - process form
        echo "Form submitted successfully!";
    } else {
        // CAPTCHA failed
        $errors = $result['error_codes'] ?? [];
        echo "CAPTCHA verification failed: " . implode(', ', $errors);
    }
}
?>

Laravel Controller

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Http;

class ContactController extends Controller
{
    public function submit(Request $request)
    {
        // Validate form fields
        $validated = $request->validate([
            'email' => 'required|email',
            'message' => 'required|string',
            'captchaToken' => 'required|string',
        ]);

        // Verify CAPTCHA
        $response = Http::asForm()->post('https://captchashield.com/v1/siteverify', [
            'secret' => config('services.captchashield.secret'),
            'response' => $validated['captchaToken'],
            'remoteip' => $request->ip(),
        ]);

        $result = $response->json();

        if (!$result['success']) {
            return back()->withErrors([
                'captcha' => 'CAPTCHA verification failed. Please try again.'
            ]);
        }

        // Process form (save to DB, send email, etc.)
        // ...

        return redirect()->route('contact.success')
            ->with('message', 'Your message has been sent!');
    }
}
?>

Add to config/services.php:

'captchashield' => [
    'sitekey' => env('CAPTCHASHIELD_SITE_KEY'),
    'secret' => env('CAPTCHASHIELD_SECRET_KEY'),
],

Node.js with Express

const express = require('express');
const axios = require('axios');
const app = express();

app.use(express.json());
app.use(express.urlencoded({ extended: true }));

async function verifyCaptcha(token, remoteIp) {
    try {
        const response = await axios.post(
            'https://captchashield.com/v1/siteverify',
            new URLSearchParams({
                secret: process.env.CAPTCHASHIELD_SECRET_KEY,
                response: token,
                remoteip: remoteIp
            })
        );

        return response.data;
    } catch (error) {
        console.error('CAPTCHA verification error:', error);
        return { success: false, error_codes: ['network-error'] };
    }
}

app.post('/submit', async (req, res) => {
    const { email, message, captchaToken } = req.body;

    // Verify CAPTCHA
    const result = await verifyCaptcha(
        captchaToken,
        req.ip || req.connection.remoteAddress
    );

    if (!result.success) {
        return res.status(400).json({
            error: 'CAPTCHA verification failed',
            details: result.error_codes
        });
    }

    // Process form
    // ...

    res.json({ success: true, message: 'Form submitted successfully' });
});

app.listen(3000, () => console.log('Server running on port 3000'));

Ruby on Rails

require 'net/http'
require 'json'

class ContactsController < ApplicationController
  def create
    captcha_token = params[:captchaToken]

    if verify_captcha(captcha_token, request.remote_ip)
      # Process form
      flash[:success] = 'Form submitted successfully!'
      redirect_to root_path
    else
      flash[:error] = 'CAPTCHA verification failed'
      render :new
    end
  end

  private

  def verify_captcha(token, remote_ip)
    uri = URI('https://captchashield.com/v1/siteverify')

    params = {
      secret: ENV['CAPTCHASHIELD_SECRET_KEY'],
      response: token,
      remoteip: remote_ip
    }

    response = Net::HTTP.post_form(uri, params)
    result = JSON.parse(response.body)

    result['success'] == true
  rescue => e
    Rails.logger.error "CAPTCHA verification error: #{e.message}"
    false
  end
end

Python with Flask

from flask import Flask, request, jsonify
import requests
import os

app = Flask(__name__)

def verify_captcha(token, remote_ip):
    """Verify CAPTCHA token with CaptchaShield"""
    url = 'https://captchashield.com/v1/siteverify'

    payload = {
        'secret': os.environ.get('CAPTCHASHIELD_SECRET_KEY'),
        'response': token,
        'remoteip': remote_ip
    }

    try:
        response = requests.post(url, data=payload, timeout=5)
        result = response.json()
        return result.get('success', False)
    except Exception as e:
        print(f'CAPTCHA verification error: {e}')
        return False

@app.route('/submit', methods=['POST'])
def submit_form():
    data = request.get_json() or request.form
    captcha_token = data.get('captchaToken')

    if not captcha_token:
        return jsonify({'error': 'CAPTCHA token missing'}), 400

    # Verify CAPTCHA
    if not verify_captcha(captcha_token, request.remote_addr):
        return jsonify({'error': 'CAPTCHA verification failed'}), 400

    # Process form
    # ...

    return jsonify({'success': True, 'message': 'Form submitted'})

if __name__ == '__main__':
    app.run(debug=True)

Go with net/http

package main

import (
    "encoding/json"
    "fmt"
    "net/http"
    "net/url"
    "os"
)

type CaptchaResponse struct {
    Success     bool     `json:"success"`
    ChallengeTS string   `json:"challenge_ts"`
    Hostname    string   `json:"hostname"`
    ErrorCodes  []string `json:"error_codes"`
}

func verifyCaptcha(token, remoteIP string) (bool, error) {
    secretKey := os.Getenv("CAPTCHASHIELD_SECRET_KEY")

    resp, err := http.PostForm("https://captchashield.com/v1/siteverify",
        url.Values{
            "secret":   {secretKey},
            "response": {token},
            "remoteip": {remoteIP},
        })

    if err != nil {
        return false, err
    }
    defer resp.Body.Close()

    var result CaptchaResponse
    if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
        return false, err
    }

    return result.Success, nil
}

func submitHandler(w http.ResponseWriter, r *http.Request) {
    if r.Method != http.MethodPost {
        http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
        return
    }

    captchaToken := r.FormValue("captchaToken")
    remoteIP := r.RemoteAddr

    success, err := verifyCaptcha(captchaToken, remoteIP)
    if err != nil || !success {
        http.Error(w, "CAPTCHA verification failed", http.StatusBadRequest)
        return
    }

    // Process form
    fmt.Fprintf(w, "Form submitted successfully")
}

func main() {
    http.HandleFunc("/submit", submitHandler)
    http.ListenAndServe(":8080", nil)
}

Java with Spring Boot

package com.example.demo;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import java.util.Map;

@Service
class CaptchaService {

    @Value("${captchashield.secret}")
    private String secretKey;

    private final RestTemplate restTemplate = new RestTemplate();

    public boolean verify(String token, String remoteIp) {
        String url = "https://captchashield.com/v1/siteverify";

        MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
        params.add("secret", secretKey);
        params.add("response", token);
        params.add("remoteip", remoteIp);

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

        HttpEntity<MultiValueMap<String, String>> request =
            new HttpEntity<>(params, headers);

        try {
            ResponseEntity<Map> response = restTemplate.postForEntity(
                url, request, Map.class);
            Map<String, Object> body = response.getBody();
            return body != null &&
                   Boolean.TRUE.equals(body.get("success"));
        } catch (Exception e) {
            return false;
        }
    }
}

@RestController
class ContactController {

    private final CaptchaService captchaService;

    public ContactController(CaptchaService captchaService) {
        this.captchaService = captchaService;
    }

    @PostMapping("/submit")
    public ResponseEntity<String> submit(
        @RequestParam String captchaToken,
        @RequestHeader("X-Forwarded-For") String remoteIp) {

        if (!captchaService.verify(captchaToken, remoteIp)) {
            return ResponseEntity
                .badRequest()
                .body("CAPTCHA verification failed");
        }

        // Process form
        return ResponseEntity.ok("Form submitted successfully");
    }
}

.NET with ASP.NET Core

using Microsoft.AspNetCore.Mvc;
using System.Text.Json;

public class CaptchaService
{
    private readonly IConfiguration _configuration;
    private readonly IHttpClientFactory _httpClientFactory;

    public CaptchaService(
        IConfiguration configuration,
        IHttpClientFactory httpClientFactory)
    {
        _configuration = configuration;
        _httpClientFactory = httpClientFactory;
    }

    public async Task<bool> VerifyAsync(string token, string remoteIp)
    {
        var client = _httpClientFactory.CreateClient();
        var secretKey = _configuration["CaptchaShield:SecretKey"];

        var parameters = new Dictionary<string, string>
        {
            { "secret", secretKey },
            { "response", token },
            { "remoteip", remoteIp }
        };

        var content = new FormUrlEncodedContent(parameters);

        try
        {
            var response = await client.PostAsync(
                "https://captchashield.com/v1/siteverify",
                content);

            var json = await response.Content.ReadAsStringAsync();
            var result = JsonSerializer.Deserialize<CaptchaResponse>(json);

            return result?.Success ?? false;
        }
        catch
        {
            return false;
        }
    }
}

public class CaptchaResponse
{
    public bool Success { get; set; }
    public string? ChallengeTs { get; set; }
    public string? Hostname { get; set; }
    public string[]? ErrorCodes { get; set; }
}

[ApiController]
[Route("[controller]")]
public class ContactController : ControllerBase
{
    private readonly CaptchaService _captchaService;

    public ContactController(CaptchaService captchaService)
    {
        _captchaService = captchaService;
    }

    [HttpPost("submit")]
    public async Task<IActionResult> Submit([FromForm] string captchaToken)
    {
        var remoteIp = HttpContext.Connection.RemoteIpAddress?.ToString();

        if (!await _captchaService.VerifyAsync(captchaToken, remoteIp))
        {
            return BadRequest("CAPTCHA verification failed");
        }

        // Process form
        return Ok("Form submitted successfully");
    }
}

WordPress Plugin

<?php
/**
 * Plugin Name: CaptchaShield Integration
 * Description: Adds CaptchaShield protection to forms
 */

function captchashield_verify_token($token) {
    $secret_key = get_option('captchashield_secret_key');

    $response = wp_remote_post('https://captchashield.com/v1/siteverify', [
        'body' => [
            'secret' => $secret_key,
            'response' => $token,
            'remoteip' => $_SERVER['REMOTE_ADDR']
        ]
    ]);

    if (is_wp_error($response)) {
        return false;
    }

    $body = json_decode(wp_remote_retrieve_body($response), true);

    return !empty($body['success']);
}

// Add widget to comment form
function captchashield_comment_form() {
    $site_key = get_option('captchashield_site_key');
    echo '<div class="captchashield" data-sitekey="' . esc_attr($site_key) . '" data-api="https://captchashield.com"></div>';
}
add_action('comment_form_after_fields', 'captchashield_comment_form');

// Add widget script to footer
function captchashield_enqueue_script() {
    wp_enqueue_script(
        'captchashield',
        'https://captchashield.com/widget.js',
        [],
        null,
        true
    );
}
add_action('wp_enqueue_scripts', 'captchashield_enqueue_script');

// Verify on comment submission
function captchashield_verify_comment($commentdata) {
    if (is_user_logged_in()) {
        return $commentdata; // Skip for logged-in users
    }

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

    if (!captchashield_verify_token($token)) {
        wp_die('CAPTCHA verification failed. Please go back and try again.');
    }

    return $commentdata;
}
add_filter('preprocess_comment', 'captchashield_verify_comment');
?>

Rules

What are Rules?

Rules let you control how CaptchaShield reacts to visitors. For each request we check basic signals like IP, IP range (CIDR), Country, ASN (ISP / hosting network), and User-Agent. If a rule matches, we apply the action you chose: Allow, Challenge, or Block.

Simple idea: “If traffic matches X → do Y”. Example: “If ASN is a datacenter → Challenge” or “If IP is on allowlist → Allow”.

Actions

  • Allow — Let the request pass normally. Easy captcha.
  • Challenge — Show a Hard CAPTCHA. The visitor must solve the challenge to continue.
  • BlockCompletely denied. The request is rejected immediately and is not bypassable (no CAPTCHA is shown).
Important: Block is final — once a visitor matches a Block rule, they cannot proceed. If you’re not 100% sure, use Challenge first and only Block when you are confident.

Common rule types

Allowlist by IP (single IP)

Use this when you want to skip captcha for your own office/VPN/admin access.

If IP equals 203.0.113.10 → Allow

Allowlist by IP range (CIDR)

Allow a whole subnet (e.g., your server network or trusted provider range).

If IP is in 203.0.113.0/24 → Allow

Challenge by ASN

ASN represents the network/ISP (often used to detect hosting/datacenter traffic). You can force captcha for suspicious ASNs.

If ASN is in [13335, 16509, 8075] → Challenge

Block by country

If you don’t serve certain regions or you’re under attack from a region, block it.

If Country is in ["RU", "KP"] → Block

Challenge “everything else”

Example policy: allow your trusted traffic, block obvious bad traffic, and challenge the rest.

Default action → Challenge
Supported signals (typical): IP, IP Range (CIDR), Country, ASN, User-Agent, Referrer/Origin (if provided).

Best practices

  • Start with Challenge rules before using Block (reduce false positives).
  • Keep allowlists strict (only your known IPs/ranges).
  • Use ASN rules to challenge datacenter traffic without blocking real users.
  • Review Logs to confirm your rules are doing what you expect.

Logs

CaptchaShield logs important events so you can monitor attack patterns, measure conversions, and debug false positives. Logs are organized per Site and contain request context such as country, ASN, user agent signals, latency, and verification outcomes.

Events

Common event types you may see:

Event Meaning Notes
challenge A captcha challenge was issued Includes risk tier + rule result
solve User attempted to solve a challenge Records solve time & heuristics
siteverify Backend token verification One-time token usage is enforced
blocked Request blocked by rule or security checks Typically includes an error_code
Best debug flow: If a customer complains, search logs by site → filter by time range → inspect challenge and siteverify events, then check whether a rule or heuristic forced an unexpected action.

Fields

Logs typically include the following fields:

Field Description
site_id Site that produced the event
event Event type (challenge, solve, siteverify, blocked)
success Whether the event succeeded (1/0)
error_code Failure reason (e.g., invalid token, duplicate, cooldown)
latency_ms API response latency (challenge/siteverify)
solve_ms Solve duration reported by widget
country Detected country (ISO 3166-1 alpha-2)
asn Autonomous System Number (ISP/hosting network)
ip_hash Hashed IP (privacy-safe correlation)
ua_hash Hashed user agent fingerprint
Privacy note: CaptchaShield stores hashed identifiers (like ip_hash) so you can correlate abuse without storing raw IPs long-term.

Filters

Use filters to isolate problems quickly. Recommended filters:

  • Site (always start here)
  • Event (challenge / solve / siteverify / blocked)
  • Success (failed only is great for debugging)
  • Country / ASN (spot datacenter/bot clusters)
  • Time range (last 15m / 1h / 24h)

Common investigations

  • Users stuck: filter solve failures and check error_code
  • Too many challenges: compare challenge volume vs solve success rate
  • Bot wave: group by ASN/country and check failure clustering

Analytics

Use Analytics to track performance and security effectiveness:

  • Challenge → Solve conversion rate (higher is better for UX)
  • Fail rate per ASN (high fail from datacenters is normal)
  • Latency (should remain low; spikes can indicate network issues)
  • Top referrers (detect abuse sources / leaked forms)
Pro tip: If “challenge issued” is high but “siteverify success” is low, it usually means bots can load the widget but cannot complete the solve — that’s good. If both are high from a suspicious ASN, tighten rules.

Troubleshooting

Common issues and their solutions.

Widget Not Appearing

  • Verify the widget script is loaded: <script src="https://captchashield.com/widget.js">
  • Check browser console for JavaScript errors
  • Ensure data-sitekey attribute is set correctly
  • Verify your domain is authorized in CaptchaShield dashboard

Verification Always Fails

  • Invalid Secret Key: Double-check your secret key matches the dashboard
  • Token Already Used: Tokens are single-use only. Don't verify the same token twice
  • Token Expired: Tokens have a short validity period. Verify immediately after form submission
  • Wrong Site Key: Ensure frontend site key matches the secret key's site
  • Network Issues: Check firewall rules allow outbound HTTPS to captchashield.com

Common Error Codes

Error Code Description Solution
missing-input-secret Secret key not provided Add secret key to request
invalid-input-secret Secret key is invalid Verify secret key in dashboard
missing-input-response CAPTCHA token not provided Ensure token is sent in request
invalid-input-response Token is invalid or expired Request new CAPTCHA from user
timeout-or-duplicate Token expired or already used Don't reuse tokens, verify immediately

Testing & Debugging

// Add console logging to debug widget
<script>
function onCaptchaSuccess(token) {
    console.log('CAPTCHA completed:', token);
}
</script>

<div class="captchashield"
     data-sitekey="YOUR_SITE_KEY"
     data-callback="onCaptchaSuccess"></div>
Clock Skew Issues: If you see timeout errors, ensure your server's system clock is synchronized with NTP servers. Clock differences can cause token validation to fail.

FAQ

What is a CAPTCHA token?

A CAPTCHA token (also called captchaToken) is a unique, encrypted string generated by the CaptchaShield widget when a user successfully completes the CAPTCHA challenge. This token is sent to your server and verified through the CaptchaShield API to confirm the user is legitimate.

How long is a CAPTCHA token valid?

Tokens are valid for a short period (typically 2 minutes) and are single-use only. After verification, the token cannot be reused. Always verify tokens immediately upon receipt.

Can I use the same token for multiple verifications?

No. Tokens are single-use only. Each form submission requires a new CAPTCHA completion and generates a new token.

Do I need to verify on both frontend and backend?

No. The widget handles the user interaction on the frontend, but you must only verify server-side. Client-side validation can be bypassed, making server-side verification essential for security.

What themes are available?

CaptchaShield supports three themes:

  • auto - Matches user's system preference
  • light - Light background theme
  • dark - Dark background theme

What languages are supported?

Currently supported languages:

  • auto - Detect from browser language
  • en - English
  • tr - Turkish

More languages are being added regularly.

Can I customize the widget appearance?

The widget uses the theme specified via data-theme. For advanced customization, you can apply CSS to the container, but internal widget styling is managed by CaptchaShield to ensure consistent security and functionality.

How do I add privacy policy links?

Use the optional data attributes:

<div class="captchashield"
     data-sitekey="YOUR_SITE_KEY"
     data-privacy="https://yoursite.com/privacy"
     data-terms="https://yoursite.com/terms"
     data-gdpr="https://yoursite.com/gdpr"></div>

Is CaptchaShield GDPR compliant?

Yes. CaptchaShield is designed with privacy in mind and provides options to link to your privacy policy and GDPR information. No personal data is stored without consent, and all processing complies with GDPR requirements.

What happens if the verification API is down?

If the verification endpoint is unreachable, your server should handle it gracefully by rejecting the request and showing a user-friendly error message. Consider implementing retry logic with exponential backoff for transient network issues.

Can I test integration without affecting production?

Yes. Create separate site keys for development and production environments in your CaptchaShield dashboard. Use environment-specific keys in your application configuration.

Support

Need help integrating CaptchaShield or experiencing issues? We're here to assist.

Resources

Contact

Found a bug? Report security issues to [email protected]. We take security seriously and respond promptly to all reports.