Python Integration

Python integration patterns for token verification with sync and async support. Works with Django, FastAPI, and Flask.

Copy these patterns into your project to integrate gkCAPTCHA server-side verification.

Installation

terminal
pip install gkcaptcha

Requirements: Python 3.9+, httpx >= 0.25.0

Quick Start

views.py
from gkcaptcha import GkCaptchaClient

client = GkCaptchaClient(
    secret_key="sk_live_...",
    site_key="pk_live_...",
)

result = client.verify_token(request.POST.get("captchaToken"))
if not result.success:
    return HttpResponseForbidden("CAPTCHA verification failed")

Async Support

Full async support for use with FastAPI, Django async views, or any asyncio application.

async_verify.py
import asyncio
from gkcaptcha import GkCaptchaClient

client = GkCaptchaClient(secret_key="sk_live_...", site_key="pk_live_...")

async def verify(token: str):
    result = await client.verify_token_async(token)
    return result.success

Framework Integration

Django

views.py
# views.py
from django.http import HttpResponseForbidden
from gkcaptcha import GkCaptchaClient, VerifyOptions

client = GkCaptchaClient()  # reads from environment

def my_form_view(request):
    if request.method == "POST":
        token = request.POST.get("captchaToken", "")
        result = client.verify_token(token, options=VerifyOptions(
            client_ip=request.META.get("REMOTE_ADDR"),
            user_agent=request.META.get("HTTP_USER_AGENT"),
        ))
        if not result.success:
            return HttpResponseForbidden("CAPTCHA verification failed")
        # Process form...

FastAPI

captcha.py
from fastapi import Depends, HTTPException, Request
from gkcaptcha import GkCaptchaClient, GkCaptchaError, VerifyOptions

client = GkCaptchaClient()  # reads from environment

async def verify_captcha(request: Request, captcha_token: str) -> None:
    options = VerifyOptions(
        client_ip=request.client.host,
        user_agent=request.headers.get("user-agent"),
    )
    try:
        result = await client.verify_token_async(captcha_token, options=options)
    except GkCaptchaError as e:
        if e.code == "TIMEOUT":
            raise HTTPException(status_code=503, detail="CAPTCHA service timeout")
        raise
    if not result.success:
        raise HTTPException(status_code=400, detail="CAPTCHA verification failed")

@app.post("/register")
async def register(form: RegisterForm, _: None = Depends(verify_captcha)):
    ...

Response Shape

types.py
@dataclass(frozen=True)
class VerifyTokenResponse:
    success: bool           # True = human, False = bot/failed
    score: float | None     # Risk score 0.0 (human) to 1.0 (bot)
    timestamp: int | None   # Unix timestamp of verification
    error: str | None       # Error message if success=False
    reason_code: str | None # Machine-readable failure reason
    fail_open: bool         # True if network error caused pass-through

Error Handling

By default (fail-open), if the gkCAPTCHA API is unreachable, verification returns VerifyTokenResponse(success=True, fail_open=True) — your application continues rather than blocking legitimate users during an outage.

افتراضيًا (فتح عند الفشل)، إذا كانت واجهة gkCAPTCHA غير متاحة، يُرجع التحقق VerifyTokenResponse(success=True, fail_open=True) — يستمر تطبيقك بدلاً من حظر المستخدمين الشرعيين.

fail_closed.py
# Fail-closed mode: raises GkCaptchaError on network failure
client = GkCaptchaClient(secret_key="...", site_key="...", fail_closed=True)
try:
    result = client.verify_token(token)
except GkCaptchaError as e:
    if e.code == "NETWORK_ERROR":
        return HttpResponse("Service temporarily unavailable", status=503)
    raise

Environment Variables

.env
export GKCAPTCHA_SECRET_KEY=sk_live_...
export GKCAPTCHA_SITE_KEY=pk_live_...

# Then construct without arguments:
client = GkCaptchaClient()
VariableRequiredDescription
GKCAPTCHA_SECRET_KEYYesSecret key from gatekeeper.sa dashboard
GKCAPTCHA_SITE_KEYYesSite key from gatekeeper.sa dashboard
GKCAPTCHA_API_URLNoOverride API URL (default: https://gkcaptcha.gatekeeper.sa)