Skip to content

Frontend Widget

The widget is a standard Web Component (<cap-widget>), loaded with a single <script> tag and usable with any framework.

Setup

html
<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:

html
<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:

js
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

AttributeDescription
data-cap-api-endpointThe 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-themeSet to auto to make the widget match your page's existing styles — see Auto theme.
data-cap-brandingSet to hidden to remove the Capcat badge in the widget's corner — see Hiding the badge.
data-cap-worker-countNumber 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:

html
<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 at 24px). The checkbox radius scales proportionally.
  • Accent — the form's accent-color if 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):

css
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:

css
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.

Built on Cap (Apache 2.0)