ray-slide-captcha
Slide puzzle captcha Python backend library.
简体中文 | English
Companion frontend: ray-captcha-react
Features
- Core service
CaptchaServicehas zero framework dependencies — works with any Python project (Flask / Django / Starlette / FastAPI, etc.) - FastAPI router shipped as an optional adapter, ready out of the box
- Background pre-generated asset pool, response < 10ms
- IP rate limiting + failure penalty + one-time token
- HMAC-SHA256 signed token, consumed once by the business layer
- Multi-source background image downloader with automatic retry on failure
Installation
# Core library (only depends on Pillow, works with any Python framework)
pip install ray-slide-captcha
# With FastAPI router adapter
pip install ray-slide-captcha[fastapi]
Quick Start
Any Python framework
from ray_slide_captcha import CaptchaService
service = CaptchaService(secret_key="your-secret-key-at-least-32-chars")
challenge = service.create_challenge(client_ip="1.2.3.4")
# Write your own routes to handle challenge / verify / consume_token
FastAPI
from fastapi import FastAPI
from ray_slide_captcha import CaptchaService
from ray_slide_captcha.fastapi import create_captcha_router
app = FastAPI()
service = CaptchaService(secret_key="your-secret-key-at-least-32-chars")
app.include_router(create_captcha_router(service), prefix="/api")
# Consume token in your business endpoint
@app.post("/login")
def login(token: str):
if not service.consume_token(token):
raise HTTPException(400, "Invalid captcha")
# ...
Run the example server
pip install -e .[dev]
cd examples
python main.py
# Server runs at http://localhost:8000
CaptchaService Configuration
| Parameter | Default | Description |
|---|---|---|
secret_key |
required | HMAC signing key, length >= 32 |
canvas_width |
320 | Canvas width |
canvas_height |
180 | Canvas height |
puzzle_width |
60 | Puzzle piece width |
puzzle_height |
60 | Puzzle piece height |
position_tolerance |
8 | Position tolerance (px) |
challenge_ttl |
120 | Challenge validity (seconds) |
token_ttl |
300 | Token validity (seconds) |
pool_size |
50 | Pre-generated pool size |
API Endpoints
GET /captcha/challenge
Fetch a new captcha challenge.
Response:
{
"code": 200,
"msg": "Captcha challenge generated",
"data": {
"id": "uuid",
"bgUrl": "data:image/png;base64,...",
"puzzleUrl": "data:image/png;base64,...",
"expires_in": 120
}
}
Note: All
msgvalues are English by default. To localize, modify theERR_MESSAGESdict infastapi.pyor pass a custommsgtook()/fail().
POST /captcha/verify
Verify the drag position and return a one-time token.
Request body:
{
"id": "uuid",
"x_position": 150,
"drag_duration_ms": 800
}
Response:
{
"code": 200,
"msg": "Verification successful",
"data": {
"success": true,
"token": "eyJjbGllbnRJZCI6IC...",
"expires_in": 300
}
}
CaptchaService.consume_token(token)
Called by the business layer to consume a token once (invalidated after consumption).
from ray_slide_captcha import CaptchaService
service = CaptchaService(secret_key="...")
if not service.consume_token(token):
raise Exception("Invalid or expired captcha")
Anti-Abuse Mechanisms
| Mechanism | Threshold | Description |
|---|---|---|
| IP rate limit | 60 / min | challenge endpoint |
| Failure penalty | 6 consecutive fails | 5s cooldown |
| Drag duration | 180ms - 60s | Too fast / too slow are rejected |
| Position tolerance | ±8px | Bot brute-force hit rate < 3% |
| Token consumption | one-time | HMAC signed, invalidated on consumption |
License
MIT
Metadata
Release files for ray-slide-captcha 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| ray_slide_captcha-1.0.0.tar.gz | 15.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| ray_slide_captcha-1.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 30.0 kB
Release files / ray_slide_captcha-1.0.0.tar.gz
| Download URL | ray_slide_captcha-1.0.0.tar.gz |
|---|---|
| Size | 15.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
3222c1cc6a4f49bc9ddab68254b75bd8b4770421edbd09daf1daf222aacb616e
|
|
BLAKE2b-256 checksum How to use checksums |
5be392fb27019605a7e24788451df1648573f8414bfe8824d08d37fe91e5841c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.10.11
|
Release files / ray_slide_captcha-1.0.0-py3-none-any.whl
| Download URL | ray_slide_captcha-1.0.0-py3-none-any.whl |
|---|---|
| Size | 14.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
15dfe8ac19611a3c6b5db46fc1c133da394f02190bc2c4effc00ee227f2c50ee
|
|
BLAKE2b-256 checksum How to use checksums |
c15faf9d77b25ebfd914d5a2b2028dd710e67bb312f30d0f8eb3492dc1b9b511
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.10.11
|