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
GkCaptchaErroron 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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dbced6a630d3b245733ec808281692a40170b07ca571317dba3118f444086b9f
|
|
| MD5 |
24a0ba7538c251fa4a8765d0783594d5
|
|
| BLAKE2b-256 |
54c9e1020ffdccd3102faa5b99dc09cb1e18e222b50cd6030fd1f9be8d538c90
|
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9632bd4d32cb5e9a0a47b80ded670e84ca66fe58530aa484c7e58b0a7d98f87b
|
|
| MD5 |
fe88aba866dce70ae09141f01605cb4a
|
|
| BLAKE2b-256 |
c9940a3386e4bcc107960929d17d9ba69bbdada0b32db15d9868e19e2f031c8b
|