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

Vue and Python

This example protects the contact form of an application that already exists. The frontend is a Vue application with Vite, the backend is a Python server with Flask. Both are already in operation. For the Myra EU CAPTCHA, you change only the files that an arrow marks below.

Requirements

The following requirements must be met:

Requirement Value
Node.js with npm installed
Python Version 3 with pip
Sitekey Public sitekey and secret from the Details view

Warning

The public sitekey belongs in the frontend, the secret only in the backend. Each visitor can read a secret that is in the delivery package of the frontend.

Project structure

These files change. All other parts of the project stay unchanged:

my-project/
├── frontend/                     # existing Vue application (Vite)
│   ├── package.json              # ← Step 1: enter the @myrasec/eu-captcha-vue package
│   ├── vite.config.js
│   ├── index.html
│   └── src/
│       ├── main.js
│       ├── App.vue
│       └── ContactForm.vue       # ← Steps 1 and 2: embed the widget, send the token
└── backend/                      # existing Python server (Flask)
    ├── .venv/
    ├── requirements.txt          # ← Step 3: enter the myra-eucaptcha package
    └── app.py                    # ← Step 3: put the verification at the start of the route

Step 1: Embed the widget

The form is in the frontend/src/ContactForm.vue file.

Install the package:

npm i @myrasec/eu-captcha-vue

Put the EuCaptcha component in the form and accept the token with the onComplete callback:

<template>
  <form @submit.prevent="handleSubmit">
    <input name="email" type="email" required />
    <textarea name="message" required></textarea>

    <!-- onComplete gives the token as soon as the challenge is complete -->
    <EuCaptcha :sitekey="captchaSitekey" :onComplete="onComplete" />

    <button type="submit">Submit</button>
  </form>
</template>

The component loads the verify.js script, makes the hidden iframe, and starts the challenge automatically.

Step 2: Send the token

Before the transmission, use isEuCaptchaDone() to examine if the challenge is complete. Then send the token in the eu-captcha-response field of the JSON body:

<script setup>
import { ref } from "vue";
import { EuCaptcha, isEuCaptchaDone } from "@myrasec/eu-captcha-vue";

const captchaSitekey = "EUCAPTCHA_SITE_KEY";
const token = ref("");

function onComplete(t) {
  token.value = t;
}

async function handleSubmit(e) {
  if (!isEuCaptchaDone()) {
    // challenge not yet complete
    return;
  }
  const fields = Object.fromEntries(new FormData(e.target));
  const res = await fetch("/api/contact", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ ...fields, "eu-captcha-response": token.value }),
  });
  if (res.ok) {
    // success
  }
}
</script>

Step 3: Verify the token

The verification belongs in the handler on the server that accepts the form data, here the /api/contact route in the backend/app.py file. It is in the first position, before all processing.

Install the package:

pip install myra-eucaptcha

Read the fields from the JSON body and put the verification at the start of the route:

import os

from flask import Flask, abort, request
from myra_eucaptcha import MyraEuCaptchaClient, MyraEuCaptchaClientConfig

app = Flask(__name__)

client = MyraEuCaptchaClient(config=MyraEuCaptchaClientConfig(
    sitekey=os.environ["EUCAPTCHA_SITE_KEY"],
    secret=os.environ["EUCAPTCHA_SECRET_KEY"],
))


@app.post("/api/contact")
def contact():
    body = request.get_json(silent=True) or {}

    # verification before all processing
    result = client.validate(
        token=body.get("eu-captcha-response", ""),
        remote_addr=request.headers.get("x-real-ip", ""),
    )
    if not result.success:
        abort(400, "captcha verification failed")

    # the existing logic continues from here
    email = body.get("email")
    message = body.get("message")
    return "Thank you!"

Note

The Python client needs the token explicitly. Read it from the eu-captcha-response field of the JSON body and give it to validate() together with the IP address of the visitor. Keep the sitekey and the secret in environment variables, from which os.environ reads them.

Warning

In training mode, result.success gives the True value. The transmission goes through. Training mode is effective for an unknown sitekey, for a wrong secret, and when the protection is off. Thus, always do the test with the true credentials from the customer portal.

See Python.

Verify the integration

Integration Test view with the Fully Integrated result

Integration Test view with the Fully Integrated result

At the end, use the Integration Test view of the sitekey to examine if the frontend and the backend operate together. Then the sitekey has the Fully Integrated status.

See Testing the integration.