CAPTCHA Widget Overview
Here we explain how the TrustCaptcha CAPTCHA widget can be integrated and customized into any website frontend.
Supported Technologies
Section titled “Supported Technologies”You can use TrustCaptcha with all common technologies and frameworks based on JavaScript. Server-side rendering (SSR), static site generation (SSG), and single-page applications (SPA) are all supported. There is a pure JavaScript library; separate npm packages exist for Angular, React, and Vue.js. A community-maintained Svelte integration is also available.
Widget integration
Section titled “Widget integration”This is how (or similarly) the implementation of the TrustCaptcha component on your website can look. Please refer to the respective tutorial that matches your programming language or framework.
<form>
<!-- your input fields -->
<trustcaptcha-component sitekey="<your_site_key>" ></trustcaptcha-component>
<!-- further input fields / submit button -->
</form>The TrustCaptcha component contains a range of properties, methods, and events. Below you’ll find a listing of all of them.
Widget properties, events and features
Section titled “Widget properties, events and features”Here is an overview of all available properties, methods, and events of the CAPTCHA widget.
Properties
Section titled “Properties”| Name | Type | Default | Description |
|---|---|---|---|
sitekey | UUID string | — | Sitekey of the CAPTCHA. You find it on the administration page of your CAPTCHA. Required. |
api-url | URL | https://api.trustcomponent.com | API endpoint the widget talks to. Override only when you’ve been told to. |
language | string | auto | Display language. auto detects from <html lang>, falls back to English. Supported: ar, be, bg, bs, ca, cs, da, de, el, en, es, et, fi, fr, hi, hr, hu, it, ko, lb, lt, lv, mk, nl, no, pl, pt, ro, ru, sk, sl, sq, sr, sv, tr, uk, zh. |
theme | light | dark | media | light | Display theme. media follows the user’s system prefers-color-scheme. |
full-width | boolean | false | When true, the widget stretches to the full available width of its container instead of using a fixed maximum width. |
autostart-disabled | boolean | false | When true, the verification will not start automatically on user interaction with the form. See the autostart section below. |
token-field-name | string | tc-verification-token | Name of the hidden <input> field added to the form when the verification succeeds. |
bypass-token | string | null | '' | Bypass token from the dashboard for automated tests — makes the CAPTCHA always pass. |
minimal-data-mode | boolean | false | When true, only the minimal set of data needed to run the verification is collected. Must match the captcha mode configured in the dashboard. |
failover-enabled | boolean | false | When true, a clearly marked failover token is issued client-side if the captcha API is unreachable. See the failover section below. |
translations | string (JSON) | '' | Override existing translations or add new languages. See custom translations. |
design | string (JSON) | '' | Custom design overrides. See custom design. License key required |
privacy-url | URL | '' | Link to your own privacy policy displayed next to the widget. License key required |
invisible | boolean | false | Hides the visible checkbox and runs the captcha in the background. License key required |
invisible-hint | hidden | inline | right-border | right-bottom | right-border | Position of the small “Trustcaptcha is verifying” hint shown while the invisible CAPTCHA runs. hidden shows nothing. |
white-label | boolean | false | Removes the Trustcaptcha branding from the widget. License key required |
license-key | string | null | null | License key that unlocks the licensed features above. You’ll find it in your CAPTCHA settings. |
framework | string | null | null | Forces a frontend framework hint sent in the verification metadata. The widget detects Angular, React and Vue automatically; only set this if the auto-detection misclassifies your stack. |
Methods
Section titled “Methods”| Name | Description |
|---|---|
startVerification() | Starts the verification manually. Useful when you’ve disabled autostart or trigger from outside the form. |
reset() | Resets the widget back to its initial state and clears the verification token. |
Events
Section titled “Events”| Name | Detail | Description |
|---|---|---|
captchaStarted | void | Fires as soon as the verification process actually starts. |
captchaSolved | string (verification token) | Fires when the CAPTCHA was solved successfully. The detail is the verification token to send to your backend. |
captchaFailed | { errorCode, message } | Fires when the CAPTCHA fails. errorCode is one of the error codes, message is a human-readable text. |
captchaExpired | void | Fires shortly before the verification token expires and the widget auto-resets. Use this to reset dependent UI state. |
captchaReset | void | Fires whenever the widget returns to its initial state — either programmatically via reset() or after expiry. |
Complete example
Section titled “Complete example”A full example with most of the available properties and events:
<form>
<!-- your input fields -->
<trustcaptcha-component sitekey="<your_site_key>" full-width="true" language="en" theme="light" license-key="<license-key>" white-label="true" translations='[{"language":"en","boxCompleted":"I am a happy human"}]' design='{"theme":{"light":{"boxDefaultBackground":"#eab308"}}}' privacy-url="https://www.example.com/my-privacy-policy" invisible="true" invisible-hint="right-bottom" token-field-name="tc-verification-token" bypass-token="<bypass-token>" minimal-data-mode="false" failover-enabled="true" ></trustcaptcha-component>
<!-- further input fields / submit button -->
</form>
<script> const widget = document.querySelector('trustcaptcha-component');
widget.addEventListener('captchaStarted', () => { /* ... */ }); widget.addEventListener('captchaSolved', (e) => { /* e.detail = verification token */ }); widget.addEventListener('captchaFailed', (e) => { /* e.detail = { errorCode, message } */ }); widget.addEventListener('captchaExpired', () => { /* ... */ }); widget.addEventListener('captchaReset', () => { /* ... */ });</script>Advanced property information
Section titled “Advanced property information”Here you will find helpful tips and tricks for integrating the TrustCaptcha component into your frontend.
Autostart
Section titled “Autostart”By default, the verification process starts automatically as soon as a user interacts with any input field that lives inside the same <form> as the CAPTCHA widget. Both keystrokes and focus changes count as interaction. To disable this behavior entirely, set autostart-disabled="true" on the component.
<form>
<!-- your input fields -->
<trustcaptcha-component sitekey="<your_site_key>" autostart-disabled="true" ></trustcaptcha-component>
<!-- further input fields / submit button -->
</form>You can also opt out per input field by adding the data-autostart="false" attribute. This is honored both for focus and for typing.
<form>
<input id="input1" name="input1"> <input id="input2" name="input2" data-autostart="false">
<trustcaptcha-component sitekey="<your_site_key>" ></trustcaptcha-component>
<!-- further input fields / submit button -->
</form>Custom Translations
Section titled “Custom Translations”The translations attribute lets you override existing translations or add entirely new languages. It is a JSON array of objects; each object is identified by its mandatory language field. Visible texts as well as screen-reader-only texts can be customized individually.
The full translation object looks like this:
{ "language": "en", "boxStart": "Start verification", "boxInProgress": "Verification in progress", "boxCompleted": "I am a human!", "endPrivacyPolicy": "Privacy", "ariaLabelStart": "CAPTCHA not started, click here to start the CAPTCHA", "ariaLabelRunning": "CAPTCHA in process", "ariaLabelDone": "CAPTCHA completed", "srRunning": "CAPTCHA verification started", "srDone": "CAPTCHA verification successfully completed", "srFailed": "CAPTCHA verification failed", "srExpired": "CAPTCHA verification expired, please start again", "srTrustcaptcha": "Open the Trustcaptcha website", "srPrivacy": "Open the privacy policy", "srFailureReasonPrefix": "Reason", "errorUnknown": "Unknown error.", "errorCommunicationFailure": "Server not reachable. Please check your internet connection and try again.", "errorPowFailure": "The bot verification failed. Please try again.", "errorPaymentRequired": "Limit of verifications has been reached. Please contact support.", "errorLocked": "Captcha blocked. Please contact the support."}When you override an existing language, fields you don’t specify keep their default. When you add a brand-new language, English is used as the fallback for any field you don’t provide.
The error* fields cover only those error situations that are actually shown to end users. Purely technical or configuration-time errors (e.g. an invalid sitekey) are not translatable — they’re aimed at developers integrating the widget, not end users.
Custom translations usage (plain HTML)
<trustcaptcha-component sitekey="<your_site_key>" language="en" translations='[{ "language": "en", "boxCompleted": "I am a happy human" }]'></trustcaptcha-component>Custom translations usage (Angular property binding)
public translations = JSON.stringify([ { language: "en", boxCompleted: "I am a happy human" }]);<trustcaptcha-component sitekey="<your_site_key>" language="en" [translations]="translations"></trustcaptcha-component>Custom Design
Section titled “Custom Design”The design attribute lets you adapt the look of the widget to fit your site. Only the properties you specify are overridden — everything else keeps its default value.
The full design object looks like this:
{ "rounding": { "box": "6px", "checkbox": "8px", "invisibleHint": "6px" }, "borderWidth": { "box": "1px", "checkbox": "1px" }, "theme": { "light": { "boxDefaultBackground": "#f9fafb", "boxDefaultText": "#374151", "boxDefaultBorder": "#e5e7eb", "boxCheckboxBackground": "#ffffff", "boxCheckboxBorder": "#e5e7eb", "boxSuccessBackground": "#f9fafb", "boxSuccessBorder": "#86efac", "boxFailureBackground": "#fef2f2", "boxFailureBorder": "#fca5a5", "boxFailureText": "#7f1d1d", "invisibleHintBackground": "#ffffff", "spinnerColor": "#3b82f6", "successIconColor": "#16a34a" }, "dark": { "boxDefaultBackground": "#1f2937", "boxDefaultText": "#e5e7eb", "boxDefaultBorder": "#374151", "boxCheckboxBackground": "#030712", "boxCheckboxBorder": "#374151", "boxSuccessBackground": "#1f2937", "boxSuccessBorder": "#15803d", "boxFailureBackground": "#450a0a", "boxFailureBorder": "#991b1b", "boxFailureText": "#fecaca", "invisibleHintBackground": "#1f2937", "spinnerColor": "#3b82f6", "successIconColor": "#22c55e" } }}What each field controls:
| Field | Effect |
|---|---|
rounding.box | Corner rounding of the outer widget box. |
rounding.checkbox | Corner rounding of the inner checkbox. |
rounding.invisibleHint | Corner rounding of the floating hint shown while an invisible captcha runs. |
borderWidth.box | Border width of the outer widget box. |
borderWidth.checkbox | Border width of the inner checkbox. |
boxDefaultBackground | Background while idle / running. |
boxDefaultText | Text color while idle / running. |
boxDefaultBorder | Border color while idle / running. |
boxCheckboxBackground | Background of the inner checkbox. |
boxCheckboxBorder | Border color of the inner checkbox. |
boxSuccessBackground | Background after a successful verification. |
boxSuccessBorder | Border color after a successful verification. |
boxFailureBackground | Background when the verification has failed. |
boxFailureBorder | Border color when the verification has failed. |
boxFailureText | Text color when the verification has failed. |
invisibleHintBackground | Background of the floating hint shown while an invisible captcha runs. |
spinnerColor | Stroke color of the loading spinner. |
successIconColor | Fill color of the success check icon. |
Custom design usage (plain HTML)
<trustcaptcha-component sitekey="<your_site_key>" license-key="<license-key>" design='{ "theme": { "light": { "boxDefaultBackground": "#eab308" } } }'></trustcaptcha-component>Custom design usage (Angular property binding)
public design = JSON.stringify({ theme: { light: { boxDefaultBackground: "#eab308" } }});<trustcaptcha-component sitekey="<your_site_key>" license-key="<license-key>" [design]="design"></trustcaptcha-component>The Verification Token
Section titled “The Verification Token”When the CAPTCHA widget is solved, the widget receives a so-called verification token from our servers. The token is a single Base64 string and is delivered in two ways:
- as a hidden
<input>field appended to the surrounding<form>(default name:tc-verification-token, configurable viatoken-field-name), and - as the detail of the
captchaSolvedJavaScript event.
Send this token to your backend — for example as part of the form submission, or via your own API call. On the backend, validate it through one of our server SDKs or the REST API.
Failover
Section titled “Failover”In rare cases the captcha API may be temporarily unreachable from a user’s network. By default the widget reports this as a COMMUNICATION_FAILURE, which means the form cannot be submitted. For workflows where availability is more important than absolute bot-protection (for example: lead forms, contact forms), you can enable an optional failover.
<trustcaptcha-component sitekey="<your_site_key>" failover-enabled="true"></trustcaptcha-component>When failover is enabled and our servers cannot be reached, the widget issues a clearly-marked failover token (the JSON payload contains clientFailover: true). The widget treats this as a successful verification and emits captchaSolved so the user can submit the form normally.
The decision what to do with such a request is made on the server side, not in the widget. Our backend SDKs surface failover tokens explicitly — typically via a dedicated exception or a flag on the verification result — so your application can:
- accept the request (treat the failover as proof of intent and a temporary loss of API connectivity),
- soft-challenge the user (e.g. require email confirmation), or
- reject the request entirely.
See the server failover behavior page for details on how each backend SDK exposes the failover signal.
Error Message
Section titled “Error Message”If the CAPTCHA widget is misconfigured or an error occurs during verification, the widget emits the captchaFailed event. The event detail contains a structured error model:
{ "errorCode": "UNKNOWN_ERROR", "message": "Unknown error."}errorCode identifies the exact error class (machine-readable, stable across releases) and lets you implement programmatic error handling. message is a human-readable text — for end-user-facing errors it’s already translated according to the active widget language.
Error Codes
Section titled “Error Codes”| Error Code | Description |
|---|---|
UNKNOWN_ERROR | An unexpected error occurred. Treat this as a generic failure and retry, or contact support if it persists. |
NO_FORM_FOUND | The widget is not placed inside a <form> element. Move the <trustcaptcha-component> into the surrounding form. |
COMMUNICATION_FAILURE | Our servers could not be reached. Usually a temporary networking issue. See failover if availability is critical. |
NO_SITE_KEY_SPECIFIED | The required sitekey attribute is missing. |
SITE_KEY_FORMAT_INVALID | The provided sitekey is not a valid UUID. Copy it again from your CAPTCHA settings. |
CAPTCHA_NOT_FOUND | No CAPTCHA exists for the configured sitekey. Most often a typo, or the captcha was deleted. |
CAPTCHA_NOT_ACCESSIBLE | The captcha is not allowed to be loaded from the page’s hostname. Check the Authorized websites setting in your CAPTCHA settings. |
MINIMAL_DATA_MODE_MISMATCH | minimal-data-mode on the widget does not match the captcha’s mode in the dashboard. Align both sides. |
POW_FAILURE | The proof-of-work challenges were not accepted by the server. Usually a transient issue — let the user retry. |
PAYMENT_REQUIRED | The captcha is locked due to a billing issue. Check your subscription and payment status. |
LOCKED | The captcha is administratively locked. Please contact support. |
LICENSE_FORMAT_INVALID | The provided license-key is not a well-formed JWT. |
LICENSE_INVALID | The license signature could not be verified or the subject is not a Trustcaptcha license. |
LICENSE_SITE_KEY_MISMATCH | The license was issued for a different sitekey. Use the license belonging to this captcha. |
LICENSE_FEATURE_MISSING_WHITE_LABEL | white-label was set but the license does not include the white-label feature. |
LICENSE_FEATURE_MISSING_INVISIBILITY | invisible was set but the license does not include the invisibility feature. |
LICENSE_FEATURE_MISSING_CUSTOMIZABILITY | design or privacy-url was set but the license does not include the customizability feature. |