Python SDK
Server-side captcha token verification for Python.
Installation
pip install crovlySupports Python 3.9+. Uses httpx for HTTP requests.
Basic Usage
from crovly import Crovly
client = Crovly("crvl_secret_YOUR_API_KEY")
result = client.verify(token, expected_ip=request.remote_addr)
if not result.is_human():
return {"error": "Captcha failed"}, 403Async Usage
from crovly import AsyncCrovly
client = AsyncCrovly("crvl_secret_YOUR_API_KEY")
result = await client.verify(token, expected_ip=request.client.host)API
Crovly(secret_key, base_url?, timeout?)
| Parameter | Type | Default | Description |
|---|---|---|---|
secret_key | str | — | Your API key (required) |
base_url | str | https://api.crovly.com | API base URL |
timeout | float | 10.0 | Request timeout in seconds |
client.verify(token, expected_ip?)
Returns a VerifyResponse:
result.success # bool
result.score # float (0.0–1.0)
result.ip # str
result.solved_at # int (Unix ms)
result.error # str | None
result.is_human() # bool — shorthand for result.successDjango Example
# views.py
from crovly import Crovly
from django.conf import settings
from django.http import JsonResponse
crovly = Crovly(settings.CROVLY_SECRET_KEY)
def contact(request):
if request.method != "POST":
return JsonResponse({"error": "Method not allowed"}, status=405)
token = request.POST.get("crovly-token", "")
ip = request.META.get("HTTP_X_FORWARDED_FOR", "").split(",")[0] or request.META.get("REMOTE_ADDR", "")
result = crovly.verify(token, expected_ip=ip)
if not result.is_human():
return JsonResponse({"error": "Verification failed"}, status=403)
# Process the form...
return JsonResponse({"ok": True})# settings.py
CROVLY_SITE_KEY = env("CROVLY_SITE_KEY")
CROVLY_SECRET_KEY = env("CROVLY_SECRET_KEY")Flask Example
from flask import Flask, request, jsonify
from crovly import Crovly
app = Flask(__name__)
crovly = Crovly("crvl_secret_YOUR_API_KEY")
@app.post("/api/contact")
def contact():
token = request.form.get("crovly-token", "")
result = crovly.verify(token, expected_ip=request.remote_addr)
if not result.is_human():
return jsonify(error="Verification failed"), 403
return jsonify(ok=True)FastAPI Example
from fastapi import FastAPI, Request, HTTPException
from crovly import AsyncCrovly
app = FastAPI()
crovly = AsyncCrovly("crvl_secret_YOUR_API_KEY")
@app.post("/api/contact")
async def contact(request: Request):
data = await request.json()
result = await crovly.verify(
data["token"],
expected_ip=request.client.host,
)
if not result.is_human():
raise HTTPException(status_code=403, detail="Verification failed")
return {"ok": True}Error Handling
from crovly import Crovly
from crovly.errors import AuthenticationError, RateLimitError, TimeoutError
try:
result = crovly.verify(token)
except AuthenticationError:
# Invalid API key
except RateLimitError:
# Too many requests
except TimeoutError:
# Request timed out| Exception | Description |
|---|---|
AuthenticationError | Invalid or missing API key |
ValidationError | Invalid request data |
RateLimitError | Rate limit exceeded |
TimeoutError | Request timed out |
NetworkError | Network connectivity issue |