HTML Integration
This page covers the complete HTML-level integration of the EU CAPTCHA widget for server-rendered HTML pages.
Using React, Vue, Angular, or another SPA framework? Do not add the
<script>tag manually. Use the dedicated framework packages instead — see SPA Framework Integration.
1. Load the script
Add the following <script> tag inside your <head>:
<script src="https://cdn.eu-captcha.eu/verify.js" async defer></script>
Load this on every page that contains a form you want to protect. The script is small and loads asynchronously.
2. Place the widget
Add the widget <div> inside your <form>, typically just before the submit button:
<form method="POST" action="/your-endpoint">
<!-- your fields -->
<div class="eu-captcha" data-sitekey="EUCAPTCHA_SITE_KEY"></div>
<button type="submit">Submit</button>
</form>
Replace EUCAPTCHA_SITE_KEY with the public sitekey from your dashboard.
By default the widget runs the challenge automatically when the page loads. When the challenge completes, a hidden input field named eu-captcha-response is added to the form:
<input type="hidden" name="eu-captcha-response" value="<token>" />
This token is included in the form POST and must be verified on your server.
Widget attributes
| Attribute | Required | Default | Description |
|---|---|---|---|
data-sitekey |
✓ | — | Your public sitekey |
data-theme |
"light" |
Visual theme: "light" or "dark" (case-insensitive) |
|
data-width |
330 |
Widget width in pixels (finite number) | |
data-height |
100 |
Widget height in pixels (minimum 48) |
|
data-widgetid |
— | Custom widget ID; auto-generated if omitted | |
data-autostart |
true |
Set to "false" to defer the challenge until euCaptcha.execute() is called |
|
data-callback |
— | Global function name called on successful completion (receives token) | |
data-expired-callback |
— | Global function name called when the token expires | |
data-error-callback |
— | Global function name called on challenge failure |
See JavaScript API for full attribute details, the euCaptcha.execute() API, the window.getEuCaptchaElement() function, and the postMessage events the widget emits.
Multiple forms on one page
If your page has more than one protected form, add a separate .eu-captcha div inside each <form>. Each widget instance operates independently.
<!-- Form 1 -->
<form id="login-form" method="POST" action="/login">
<input type="email" name="email" />
<input type="password" name="password" />
<div class="eu-captcha" data-sitekey="EUCAPTCHA_SITE_KEY"></div>
<button type="submit">Log in</button>
</form>
<!-- Form 2 -->
<form id="newsletter-form" method="POST" action="/subscribe">
<input type="email" name="email" />
<div class="eu-captcha" data-sitekey="EUCAPTCHA_SITE_KEY"></div>
<button type="submit">Subscribe</button>
</form>
Framework packages
For React, Vue, Angular, and other single-page application frameworks, use the dedicated npm packages rather than the plain script tag. See SPA Framework Integration for installation, component usage, props, and how to check completion state before submitting.
- React:
@myrasec/eu-captcha - Vue 3 / Nuxt:
@myrasec/eu-captcha-vue - Angular 19/20/21:
@myrasec/eu-captcha-angular19/angular20/angular21 - Svelte / SvelteKit:
@myrasec/eu-captcha-svelte - Other SPAs (SolidJS, …):
@myrasec/eu-captchavialoadEuCaptcha()
Troubleshooting
Widget doesn't appear — check that the script loaded successfully (browser DevTools → Network). Ensure the sitekey value is correct.
Token not appearing in submitted form data — the challenge may not have completed before the user submitted. Consider only enabling the submit button after the widget signals completion.