Skip to main content

Python SDK for gkCAPTCHA - AI-resistant CAPTCHA verification

Project description

gkcaptcha

Python SDK for gkCAPTCHA — AI-resistant CAPTCHA verification for backend services.

Quick Start

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")

Installation

pip install gkcaptcha

Requirements: Python 3.9+, httpx>=0.25.0

Async Support

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

Configuration

Constructor Parameters

Parameter Type Default Description
secret_key str env GKCAPTCHA_SECRET_KEY Your secret key
site_key str env GKCAPTCHA_SITE_KEY Your site key
api_url str env GKCAPTCHA_API_URL or https://gkcaptcha.gatekeeper.sa API base URL
timeout float 5.0 Request timeout in seconds
max_retries int 1 Max retries on network error
retry_delay float 1.0 Seconds between retries
fail_closed bool False Raise on network error instead of fail-open

Environment Variables

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

# Then construct without arguments:
client = GkCaptchaClient()

Fail-Open vs Fail-Closed

Default behavior (fail-open): If the gkCAPTCHA API is unreachable due to a network error, verification returns VerifyTokenResponse(success=True, fail_open=True). This protects legitimate users during API outages.

client = GkCaptchaClient(secret_key="...", site_key="...")
result = client.verify_token(token)
if result.fail_open:
    # Network error occurred — request was allowed through
    log.warning("CAPTCHA verification skipped due to network error")

Fail-closed mode: Raises GkCaptchaError on any 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

Timeout always raises regardless of fail_closed setting — a timeout indicates a configuration problem, not transient instability.

Note: Unlike other SDKs, Python raises GkCaptchaError on timeout instead of retrying. Set a longer timeout if needed.

Error Codes

Code When
TIMEOUT Request exceeded timeout seconds. Always raises.
NETWORK_ERROR Network failure after all retries. Only raises when fail_closed=True.
INVALID_CONFIG Missing secret_key or site_key at construction time.

Response Fields

@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

Framework Integration Examples

Django View

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

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...

Django Decorator (copy-paste, not shipped code)

# decorators.py
from functools import wraps
from django.http import HttpResponseForbidden
from gkcaptcha import GkCaptchaClient

_client = GkCaptchaClient()

def require_captcha(view_func):
    @wraps(view_func)
    def wrapper(request, *args, **kwargs):
        token = request.POST.get("captchaToken", "")
        result = _client.verify_token(token)
        if not result.success:
            return HttpResponseForbidden("CAPTCHA verification failed")
        return view_func(request, *args, **kwargs)
    return wrapper

# Usage:
@require_captcha
def register(request):
    ...

FastAPI Dependency Injection (copy-paste, not shipped code)

# 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")

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

Widget Integration

Add the gkCAPTCHA widget to your HTML form:

<form method="POST">
    <gk-captcha sitekey="pk_live_..."></gk-captcha>
    <button type="submit">Submit</button>
</form>

<script src="https://gatekeeper.sa/widget.js" async></script>

The widget emits a captchaToken field on form submission. Pass this to verify_token() on your backend.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

gkcaptcha-0.1.0.tar.gz (6.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

gkcaptcha-0.1.0-py3-none-any.whl (5.8 kB view details)

Uploaded Python 3

File details

Details for the file gkcaptcha-0.1.0.tar.gz.

File metadata

  • Download URL: gkcaptcha-0.1.0.tar.gz
  • Upload date:
  • Size: 6.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for gkcaptcha-0.1.0.tar.gz
Algorithm Hash digest
SHA256 dbced6a630d3b245733ec808281692a40170b07ca571317dba3118f444086b9f
MD5 24a0ba7538c251fa4a8765d0783594d5
BLAKE2b-256 54c9e1020ffdccd3102faa5b99dc09cb1e18e222b50cd6030fd1f9be8d538c90

See more details on using hashes here.

File details

Details for the file gkcaptcha-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: gkcaptcha-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 5.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for gkcaptcha-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 9632bd4d32cb5e9a0a47b80ded670e84ca66fe58530aa484c7e58b0a7d98f87b
MD5 fe88aba866dce70ae09141f01605cb4a
BLAKE2b-256 c9940a3386e4bcc107960929d17d9ba69bbdada0b32db15d9868e19e2f031c8b

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page