JavaScript CAPTCHA
The following tutorial will guide you on how to integrate the TrustCaptcha CAPTCHA solution into your Javascript frontend to retrieve and evaluate the CAPTCHA verification result.
Preparation
Section titled “Preparation”You should have already completed the following steps before you start with CAPTCHA widget integration in your JavaScript frontend.
Read the basic Information: For a basic overview, please read the get started guide. We also recommend that you familiarize yourself with the technical concept of TrustCaptcha.
Existing CAPTCHA: If you don’t have a CAPTCHA yet, sign in or create a new user account. Then create a new CAPTCHA.
Existing JavaScript website: You need a JavaScript website in which you want to integrate the TrustCaptcha CAPTCHA widget.
Integrate the CAPTCHA widget
Section titled “Integrate the CAPTCHA widget”Follow the steps below to integrate the TrustCaptcha CAPTCHA widget into your JavaScript frontend
1. Add dependency
Section titled “1. Add dependency”You can add the TrustCaptcha widget to your project in two ways: load it from our CDN (simplest, what most integrations use), or self-host the bundle on your own infrastructure (privacy, performance, and resilience). Both options provide the exact same JavaScript bundle in three module formats — pick whichever fits your toolchain.
Option A — Load from our CDN
Section titled “Option A — Load from our CDN”The 3.0.x segment of the URL always serves the latest patch release of the 3.0 line. To pin a specific version (so the bundle never changes without a deployment), replace 3.0.x with the exact version, e.g. 3.0.0.
ECMAScript Modules (esm)
<!-- latest 3.0.x patch release --><script type="module" src="https://cdn.trustcomponent.com/trustcaptcha/3.0.x/trustcaptcha.esm.min.js"></script>
<!-- or pinned to a specific version --><script type="module" src="https://cdn.trustcomponent.com/trustcaptcha/3.0.0/trustcaptcha.esm.min.js"></script>Universal Module Definition (umd)
<!-- latest 3.0.x patch release --><script src="https://cdn.trustcomponent.com/trustcaptcha/3.0.x/trustcaptcha.umd.min.js"></script>
<!-- or pinned to a specific version --><script src="https://cdn.trustcomponent.com/trustcaptcha/3.0.0/trustcaptcha.umd.min.js"></script>CommonJS (cjs)
<!-- latest 3.0.x patch release --><script src="https://cdn.trustcomponent.com/trustcaptcha/3.0.x/trustcaptcha.cjs.min.js"></script>
<!-- or pinned to a specific version --><script src="https://cdn.trustcomponent.com/trustcaptcha/3.0.0/trustcaptcha.cjs.min.js"></script>Option B — Self-host the widget
Section titled “Option B — Self-host the widget”Host the bundle alongside your other static assets and reference it from there. Reasons to choose this:
- Privacy / GDPR — no third-party request from the user’s browser to our CDN.
- Performance & control — the file is served from your own origin, with your own caching, headers, and SLA.
- Resilience & failover — your widget continues to render even if our CDN is unreachable. This is a hard requirement for the widget-side failover to work in a complete-outage scenario.
Download the version you want to pin, drop it into your static-assets folder, and reference it from your HTML:
<script type="module" src="/assets/trustcaptcha-3.0.0.esm.min.js"></script>When upgrading, drop the new version into the same folder and update the path. Keep the old file around until all deploys are stable. If you hit issues after self-hosting, check the Troubleshooting section below.
2. Integrate CAPTCHA widget
Section titled “2. Integrate CAPTCHA widget”Insert the trustcaptcha element into your HTML. It is important that the widget is located within a form element. Then set the required site-key. You can find this key in your CAPTCHA settings. Information on all other properties can be found in the CAPTCHA widget overview.
Important: Once the CAPTCHA has been solved, you will receive a so-called verification token. This is available as a hidden input field with the name tc-verification-token. You can also get the token via the JavaScript event captchaSolved of the trustcaptcha component. Then send the verification token to your backend and validate it there. You can find out more about this in result validation overview.
<form> <!-- your input fields -->
<trustcaptcha-component sitekey="<your_site_key>" ></trustcaptcha-component>
<!-- further input fields / submit button --></form>
<script> const trustcaptchaComponent = document.getElementsByTagName('trustcaptcha-component')[0];
<!-- handle success --> trustcaptchaComponent.addEventListener('captchaSolved', (event) => { console.log('Verification token:', event.detail); });
<!-- handle error --> trustcaptchaComponent.addEventListener('captchaFailed', (event) => { console.error(event.detail); });</script>Example implementation
Section titled “Example implementation”The following example shows a possible implementation of the TrustCaptcha CAPTCHA widget in a JavaScript frontend.
The complete example including source code can be found on Github.
<head> <meta charset="UTF-8"> <title>TrustCaptcha Testsystem</title> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-KK94CHFLLe+nY2dmCWGMq91rCGa5gtU4mk92HdvYe+M/SXH301p5ILy+dN9+nJOZ" crossorigin="anonymous"> <script type="module" src="https://cdn.trustcomponent.com/trustcaptcha/3.0.x/trustcaptcha.esm.min.js"></script></head>
<body class="py-5"> <div class="d-flex justify-content-center"> <div class="w-100" style="max-width: 640px;"> <h1>Thymeleaf (Spring)</h1> Try Thymeleaf<br /> <br/> <form th:if="${captchaSuccess == null}" th:action="'/'" method="post" th:object="${model}"> <div class="mb-3"> <label for="messageInput" class="form-label">Message</label> <textarea class="form-control" id="messageInput" placeholder="Write a message" rows="3" th:field="*{message}"></textarea> </div> <div class="mb-3"> <trustcaptcha-component id="trustcaptchaComponent" sitekey="<your_site_key>" language="en" theme="light" token-field-name="myToken" ></trustcaptcha-component> </div> <div class="d-grid gap-2"> <button class="btn btn-success" id="submitButton" disabled>Post new message</button> </div> </form> <div th:if="${verificationResult}" > <div class="alert alert-success mt-3" role="alert"> <strong>Message: </strong><span th:text="${message}"></span><br> <strong>Passed: </strong><span th:text="${verificationResult.isVerificationPassed()}"></span><br> <strong>Score: </strong><span th:text="${verificationResult.getScore()}"></span><br> <strong>Decision type: </strong><span th:text="${verificationResult.getDecisionType()}"></span><br> <strong>Decision action: </strong><span th:text="${verificationResult.getDecisionAction()}"></span> </div> <div class="d-grid gap-2"> <button type="button" class="btn btn-primary" onclick="reloadPage()">Reload page</button> </div> </div> </div> </div></body>
<script>
function reloadPage() { window.location.href = '/' }
<!-- example, unused in this sample --> function resetCaptcha() { const trustcaptchaComponent = document.getElementById('trustcaptchaComponent'); trustcaptchaComponent.reset(); }
<!-- Handle solve and fail event --> const trustcaptchaComponent = document.getElementById('trustcaptchaComponent'); trustcaptchaComponent.addEventListener('captchaSolved', (event) => { console.log('Verification token:', event.detail); const submitButton = document.getElementById('submitButton'); submitButton.disabled = false; }); trustcaptchaComponent.addEventListener('captchaFailed', (event) => { console.error(event.detail); });</script>package com.trustcaptcha.sample.controller;
import com.trustcomponent.trustcaptcha.TrustCaptcha;import com.trustcomponent.trustcaptcha.exception.CaptchaFailureException;import com.trustcomponent.trustcaptcha.model.VerificationResult;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.stereotype.Controller;import org.springframework.ui.Model;import org.springframework.web.bind.annotation.*;
@Controllerpublic class SampleController {
private final Logger logger = LoggerFactory.getLogger(SampleController.class);
@GetMapping("/") public String getPage(Model model) {
model.addAttribute("model", new PageModel());
return "index"; }
@PostMapping(value = "/") public String postPage(@ModelAttribute PageModel pageModel, @RequestParam("tc-verification-token") String verificationToken, Model model) {
// Retrieving the verification result VerificationResult verificationResult; try { verificationResult = TrustCaptcha.getVerificationResult("<your_api_key>", verificationToken); } catch (CaptchaFailureException e) { // Fetch verification result failed - handle error throw new RuntimeException(e); }
// Act on the verification result if (!verificationResult.isVerificationPassed() || verificationResult.getScore() > 0.5) { logger.warn("Verification failed or bot score > 0.5 – possible automated request."); }
model.addAttribute("model", new PageModel()); model.addAttribute("message", pageModel.getMessage()); model.addAttribute("verificationResult", verificationResult);
return "index"; }}package com.trustcaptcha.sample.controller;
public class PageModel {
public String message;
public PageModel() { this.message = ""; }
public String getMessage() { return message; }
public void setMessage(String message) { this.message = message; }}Troubleshooting
Section titled “Troubleshooting”File encoding (UTF-8)
Section titled “File encoding (UTF-8)”The self-hosted bundle contains the widget’s translation strings (German ü, French accents, Chinese characters, …). Always save and serve the file as UTF-8. If your editor or build pipeline silently converts it to another encoding (e.g. Windows-1252), the widget will still load, but characters in some languages render as garbled placeholders. Downloading the file directly via the links above is the safest way to avoid encoding issues.
Content Security Policy
Section titled “Content Security Policy”If your site uses a Content Security Policy, allow-list the sources the widget needs:
script-src— the host you load the bundle from. Eitherhttps://cdn.trustcomponent.com(CDN) or'self'(self-hosted).connect-src—https://api.trustcomponent.com. The widget always talks to our API while the user solves the CAPTCHA, regardless of where the bundle is hosted.
If the widget loads but never starts the verification, the browser console will usually show a CSP violation message — that’s the fastest way to confirm this is the cause.
Next steps
Section titled “Next steps”Once you have integrated the TrustCaptcha widget into your frontend, please remember to check the verification token on the server side and evaluate the CAPTCHA result. You can find more information on this in result validation overview. We also recommend that you familiarize yourself with the following topics:
Security rules: You can find many security settings for your CAPTCHA in the CAPTCHA settings. These include, for example, authorized websites, CAPTCHA bypass for specific IP addresses, bypass keys, IP based blocking, geoblocking, individual difficulty and duration of the CAPTCHA, and much more. Learn more about the security rules.
Privacy & GDPR compliance: Include a passage in your privacy policy that refers to the use of TrustCaptcha. We also recommend that you enter into a data processing agreement with us to stay GDPR-compliant. Learn more about data protection.
Accessibility & UX: Customize TrustCaptcha to your website so that your website is as accessible as possible and offers the best possible user experience. More about accessibility.
Testing: If you use automated testing, make sure that the CAPTCHA does not block it. Learn more about testing.