Skip to content
Myra EU CAPTCHA Online Help Updated · 25 Aug 2026

Python

The myra-eucaptcha package verifies the token on the server. It supplies a synchronous interface and an asynchronous interface.

Requirements

The following requirements must be met:

Requirement Value
Package manager pip or uv
Credentials Public sitekey and secret from the Details view

Install the package

Install the package from PyPI:

pip install myra-eucaptcha

With the uv package manager, the command is as follows:

uv add myra-eucaptcha

Embed the widget

Add the widget to the form to protect:

<div class="eu-captcha" data-sitekey="EUCAPTCHA_SITE_KEY"></div>

Add the script link to the page:

<script src="https://cdn.eu-captcha.eu/verify.js" async defer></script>

The script renders the widget, does the challenge, and adds the token to the form.

Thus, a full page is as follows:

<html>
    <head>
        <title>captcha integration sample</title>
    </head>
    <body>

    <form action="/login" method="post">
        <table>
            <tr>
                <td>user</td>
                <td>
                    <input type=text name="username" />
                </td>
            </tr>
            <tr>
                <td>pass</td>
                <td>
                    <input type=password name="password" />
                </td>
            </tr>
            <tr>
                <td colspan="2">
                    <div class="eu-captcha" data-sitekey="EUCAPTCHA_SITE_KEY"></div>
                </td>
            </tr>
            <tr><td colspan="2"><input type="submit" name="submit" /></td></tr>
        </table>
    </form>

    <script src="https://cdn.eu-captcha.eu/verify.js" async defer></script>
    </body>
</html>

Verify the token

This example shows the verification on the server with FastAPI:

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

    # configure the captcha settings and behaviour
    captcha_config = MyraEuCaptchaClientConfig(
        sitekey="EUCAPTCHA_SITE_KEY",
        secret="EUCAPTCHA_SECRET_KEY",
    )

    client = MyraEuCaptchaClient(config=captcha_config)

    # this is depending on your webserver-setup and whether we're behind
    # a reverse-proxy (nginx, apache, traefik, or something similar.)
    remote_addr = request.headers.get('x-real-ip','')
    validationresult = await client.avalidate(
                token=eu_captcha_response,
                remote_addr=remote_addr)

    if validationresult.success:
        # yay - all good.
        # <your-code-here>
        pass
    else:
        # validation failed, check validationresult.errors
        # <your-code-here>
        pass

The asynchronous verification uses avalidate(), the synchronous verification uses validate().

The source of the IP address of the visitor depends on your web server. If the application is behind an upstream system such as nginx, Apache, or Traefik, read the address from the applicable header.

Behaviour for errors

By default, the package is fault-tolerant: for a timeout, an API error, or a network error, the verification gives the True result. No exception occurs. The errors that occurred are given in MyraEuCaptchaResult.errors.

You change this behaviour with MyraEuCaptchaClientConfig:

    captcha_config = MyraEuCaptchaClientConfig(
        sitekey="EUCAPTCHA_SITE_KEY",
        secret="EUCAPTCHA_SECRET_KEY",
        connect_timeout: int = 3
        read_timeout: int = 10
        write_timeout: int = 10
        pool_timeout: int = 3
        default_result_on_error:bool = True ## this is the validation result, that is returned on exceptions
        suppress_exceptions:bool = True     ## if you want exceptions to be raised, set this to False
    )
Setting Default Effect
connect_timeout 3 Time limit for the connection setup in seconds.
read_timeout 10 Time limit to read the response in seconds.
write_timeout 10 Time limit to send the request in seconds.
pool_timeout 3 Time limit for an available connection from the connection pool in seconds.
default_result_on_error True Result of the verification when an exception occurs.
suppress_exceptions True Set to False, the package causes the exception instead of suppressing it.

For Django, see Django.

Full example

See Vue and Python.