Frontend Widget
The widget is a standard Web Component (<cap-widget>), loaded with a single <script> tag and usable with any framework.
Setup
<script src="https://capcat.ai/widget/cap.js"></script>TIP
This script is hosted by Capcat itself on capcat.ai, with no third-party CDN dependency, so it loads reliably worldwide (including China).
Form mode (zero JavaScript)
When the widget is placed inside a <form>, it automatically injects a hidden cap-token field and submits it along with the form:
<form action="/submit" method="POST">
<cap-widget data-cap-api-endpoint="https://api.capcat.ai/<site-key>/"></cap-widget>
<button type="submit">Submit</button>
</form>JavaScript mode (SPA / custom flow)
Listen for the solve event to get the token and decide yourself when to send it:
const widget = document.querySelector("cap-widget");
widget.addEventListener("solve", (e) => {
const token = e.detail.token;
// send the token to your backend, unlock the submit button, etc.
});Common attributes
| Attribute | Description |
|---|---|
data-cap-api-endpoint | The verification service URL, in the form https://api.capcat.ai/<site-key>/ (the site key is generated when you create a site in the console). Required. |
data-cap-theme | Set to auto to make the widget match your page's existing styles — see Auto theme. |
data-cap-branding | Set to hidden to remove the Capcat badge in the widget's corner — see Hiding the badge. |
data-cap-worker-count | Number of Web Workers used for solving, defaults to the device's core count. |
Styling
The widget renders inside Shadow DOM, so your page's CSS can't accidentally break it. Customization goes through two supported channels — auto theme and --cap-* CSS variables — which can be freely combined.
Auto theme
Add data-cap-theme="auto" and the widget derives its look from the page around it, no CSS required:
<cap-widget data-cap-theme="auto" data-cap-api-endpoint="..."></cap-widget>What gets sampled:
- Font family, size & text color — inherited from the widget's position in the page; font size follows the reference input.
- Background — the first opaque ancestor background, so it matches the card or panel it sits on and adapts to dark pages automatically.
- Border color & radius — aligned with the first text input in the same
<form>. Outside a form, the nearest surrounding form control is used, falling back to the nearest button (radius only, capped at24px). The checkbox radius scales proportionally. - Accent — the form's
accent-colorif set, otherwise the text color (used for the spinner, focus ring and troubleshooting link).
Auto theme only fills in variables you haven't set yourself: any --cap-* variable declared in your CSS takes precedence, so you can combine auto with the manual overrides below. It re-samples when the OS color scheme flips; if your app switches themes at runtime (e.g. a class toggle), re-set the attribute (el.setAttribute("data-cap-theme", "auto")) after switching to re-sample.
CSS variables
Set any of these on the cap-widget element (values shown are the defaults):
cap-widget {
--cap-background: #fdfdfd;
--cap-border-color: #dddddd8f;
--cap-border-radius: 14px;
--cap-widget-width: 260px;
--cap-widget-height: 58px;
--cap-widget-padding: 14px;
--cap-gap: 15px;
--cap-color: #212121;
--cap-font: system-ui, sans-serif;
--cap-font-size: 15px;
--cap-checkbox-size: 25px;
--cap-checkbox-border: 1px solid #aaaaaad1;
--cap-checkbox-border-radius: 6px;
--cap-checkbox-background: #fafafa91;
--cap-spinner-color: #000;
--cap-spinner-background-color: #eee;
--cap-focus-ring: #0066cc;
}A common recipe — make the widget fill its container like other form fields:
cap-widget {
display: block;
--cap-widget-width: 100%;
}Hiding the badge (paid plans)
data-cap-branding="hidden" removes the Capcat badge in the widget's corner. This is a paid-plan feature: enable Hide the Capcat badge for the site in the console first — on free sites the server makes the badge reappear.
For React / Vue / Svelte integration examples, see the upstream Widget docs.