Python Module
The myra-eucaptcha package is the official Python client for server-side token verification. It wraps the verification API with configurable timeouts, fault-tolerance defaults, and both synchronous and asynchronous interfaces.
Using Django? See the Django Module for a higher-level integration that provides a native form field, widget, and admin-managed configuration.
- PyPI:
myra-eucaptcha - Source: github.com/Myra-Security-GmbH/eu-captcha-python
- License: BSD-2-Clause
Installation
pip install myra-eucaptcha
Or with uv:
uv add myra-eucaptcha
FastAPI example
The example below shows async verification inside a FastAPI route. The widget injects a hidden field named eu-captcha-response into the submitted form; FastAPI maps it to the eu_captcha_response parameter via the alias.
from myra_eucaptcha import MyraEuCaptchaClient, MyraEuCaptchaClientConfig
@app.post("/login", response_class=HTMLResponse)
async def login(
request: Request,
username: str = Form(...),
password: str = Form(...),
eu_captcha_response: str = Form(..., alias="eu-captcha-response"),
):
captcha_config = MyraEuCaptchaClientConfig(
sitekey="EUCAPTCHA_SITE_KEY",
secret="EUCAPTCHA_SECRET_KEY",
)
client = MyraEuCaptchaClient(config=captcha_config)
# Use X-Real-IP or X-Forwarded-For when behind a reverse proxy
remote_addr = request.headers.get("x-real-ip", "")
result = await client.avalidate(
token=eu_captcha_response,
remote_addr=remote_addr,
)
if result.success:
# proceed with login
...
else:
# result.errors contains any error details
...
Replace EUCAPTCHA_SITE_KEY and EUCAPTCHA_SECRET_KEY with the values from your sitekey configuration. Store them in environment variables — do not hardcode them.
Synchronous usage
For frameworks that do not use async/await, call .validate() instead:
result = client.validate(
token=eu_captcha_response,
remote_addr=remote_addr,
)
The return type and behaviour are identical to .avalidate().
Configuration reference
Pass a MyraEuCaptchaClientConfig instance when constructing the client.
| Parameter | Type | Default | Description |
|---|---|---|---|
sitekey |
str |
— | Your public sitekey |
secret |
str |
— | Your secret key |
connect_timeout |
float |
3 |
Seconds to wait for a connection |
read_timeout |
float |
10 |
Seconds to wait for a response |
write_timeout |
float |
10 |
Seconds to wait for a write |
pool_timeout |
float |
3 |
Seconds to wait for a connection from the pool |
default_result_on_error |
bool |
True |
Value returned when the API call fails with an exception |
suppress_exceptions |
bool |
True |
When True, exceptions are caught and not re-raised |
Result object
Both .validate() and .avalidate() return a MyraEuCaptchaResult with:
| Property | Type | Description |
|---|---|---|
success |
bool |
True if the token passed verification |
errors |
list |
Error details when verification failed or an exception occurred |
Fault tolerance
By default the client operates in permissive mode: if the verification API is unreachable or returns an error, success is True and no exception is raised. Errors are still recorded in result.errors.
This avoids locking out legitimate users during transient network issues. To change this behaviour, set default_result_on_error=False and/or suppress_exceptions=False in the config.
Choose the right trade-off for your use case:
| Scenario | Recommended setting |
|---|---|
| Contact / signup forms — prefer availability | Keep defaults (default_result_on_error=True) |
| High-security endpoints — prefer strictness | default_result_on_error=False, suppress_exceptions=False |