Mini (Cap.js)
The Mini Widget is based on Cap.js but has a different implementation which suites the Compatibility needs for Before.sh Captcha-as-a-Service.
Installation
Include the script in your HTML:
<script src="https://cdn.hopjs.net/npm/@before.sh/mini@1.4.2/cap.min.js"></script>
or
<script src="https://cdn.jsdelivr.net/npm/@before.sh/mini@1.4.2/cap.min.js"></script>
Usage
The widget can be embedded using the <cap-mini>
custom element with a site key:
<cap-mini cap-site-key="YOUR_SITE_KEY"></cap-mini>
It will automatically detect an endpoint, and therefore doesn't need to specify one.
Invisible Mode
The widget can be controlled programmatically without visible UI:
const captcha = new Cap({
apiEndpoint: '/api/'
});
// Trigger solve programmatically
captcha.solve();
// Listen for completion
captcha.addEventListener('solve', (event) => {
console.log('Token:', event.detail.token);
});
When no DOM element is provided to the constructor, the widget is automatically hidden with display: none
and appended to the document.
Configuration Attributes
Current Naming Convention (v1.4.2+)
Attribute | Type | Description |
---|---|---|
cap-site-key | string | Site key for authentication (new API mode) |
cap-endpoints | string | Comma-separated list of fallback endpoints (optional) |
cap-api-endpoint | string | API endpoint URL (legacy mode) |
cap-darkmode | boolean | Enables dark theme when set to "true" |
cap-label | boolean | Shows Cap.js attribution when "true" , before.sh branding when "false" (default: "true" ) |
cap-color | string | Primary color for border and brand highlight (e.g., "#242424" ) |
cap-worker-count | number | Number of Web Workers for parallel computation (default: hardware concurrency) |
cap-hidden-field-name | string | Name attribute for the hidden token input field (default: "cap-token" ) |
Legacy Naming Convention
The following attribute names are supported for backwards compatibility:
data-cap-site-key
→cap-site-key
data-cap-endpoints
→cap-endpoints
data-cap-api-endpoint
→cap-api-endpoint
darkmode
→cap-darkmode
color
→cap-color
data-cap-worker-count
→cap-worker-count
data-cap-hidden-field-name
→cap-hidden-field-name
Internationalization
Text displayed by the widget can be customized using cap-i18n-*
or data-cap-i18n-*
attributes:
Attribute | Default Value | When Displayed |
---|---|---|
cap-i18n-initial-state | "I'm a human" | Initial state |
cap-i18n-verifying-label | "Verifying..." | During verification |
cap-i18n-solved-label | "You're a human" | After successful verification |
cap-i18n-error-label | "Error. Try again." | On error |
cap-i18n-verify-aria-label | "Click to verify you're a human" | ARIA label (initial) |
cap-i18n-verifying-aria-label | "Verifying you're a human, please wait" | ARIA label (verifying) |
cap-i18n-verified-aria-label | "We have verified you're a human, you may now continue" | ARIA label (verified) |
cap-i18n-error-aria-label | "An error occurred, please try again" | ARIA label (error) |
cap-i18n-wasm-disabled | "Enable WASM for significantly faster solving" | Warning when WebAssembly unavailable |
Example:
<cap-mini
cap-site-key="YOUR_SITE_KEY"
cap-i18n-initial-state="Ich bin ein Mensch"
cap-i18n-verifying-label="Überprüfung läuft...">
</cap-mini>
Styling
CSS Custom Properties
The widget accepts CSS custom properties for styling:
Property | Default | Description |
---|---|---|
--cap-background | #fdfdfd | Background color (light mode) |
--cap-background-dark | #1a1a1a | Background color (dark mode) |
--cap-border-color | var(--cap-primary-color, #d946ef) | Border color (light mode) |
--cap-border-color-dark | var(--cap-primary-color, #d946ef) | Border color (dark mode) |
--cap-border-radius | 14px | Border radius |
--cap-color | #212121 | Text color (light mode) |
--cap-color-dark | #e5e5e5 | Text color (dark mode) |
--cap-primary-color | #d946ef | Primary accent color (border and brand highlight) |
--cap-widget-height | 72px | Widget height |
--cap-widget-width | 230px | Widget width |
--cap-widget-padding | 14px | Internal padding |
--cap-gap | 15px | Gap between elements |
--cap-checkbox-size | 25px | Checkbox dimensions |
--cap-checkbox-background | #fafafa91 | Checkbox background (light) |
--cap-checkbox-background-dark | #2a2a2a | Checkbox background (dark) |
--cap-checkbox-border | 1px solid #aaaaaad1 | Checkbox border |
--cap-checkbox-border-dark | #555 | Checkbox border color (dark) |
--cap-checkbox-border-radius | 100% | Checkbox border radius |
--cap-checkbox-margin | 2px | Checkbox vertical margin |
--cap-spinner-color | #000 | Loading spinner color |
--cap-spinner-background-color | #eee | Loading spinner background |
--cap-spinner-thickness | 5px | Loading spinner thickness |
--cap-font | system fonts | Font family |
--cap-checkmark | SVG data URI | Success checkmark icon |
--cap-error-cross | SVG data URI | Error icon |
Example:
<style>
cap-mini {
--cap-primary-color: #242424;
--cap-border-radius: 8px;
--cap-widget-width: 300px;
}
</style>
Shadow Parts
The widget exposes CSS parts for styling via ::part()
:
checkbox
- The checkbox/spinner elementlabel
- The text labelattribution
- The attribution link
Example:
cap-mini::part(label) {
font-size: 16px;
}
JavaScript API
Programmatic Control
const widget = document.querySelector('cap-mini');
// Trigger verification
widget.solve();
// Reset widget
widget.reset();
// Access token value
console.log(widget.token);
Events
The widget dispatches the following events:
Event | Detail Properties | Description |
---|---|---|
solve | { token: string } | Fired when verification completes successfully |
progress | { progress: number } | Fired during solving (0-100) |
error | { isCap: boolean, message: string } | Fired when an error occurs |
reset | none | Fired when widget is reset |
Example:
widget.addEventListener('solve', (event) => {
console.log('Token:', event.detail.token);
// Token is also available in hidden input field
});
widget.addEventListener('progress', (event) => {
console.log('Progress:', event.detail.progress + '%');
});
widget.addEventListener('error', (event) => {
console.error('Error:', event.detail.message);
});
Event Attributes
Events can also be handled via HTML attributes:
<cap-mini
cap-site-key="YOUR_SITE_KEY"
onsolve="handleSolve"
onprogress="handleProgress"
onerror="handleError"
onreset="handleReset">
</cap-mini>
<script>
function handleSolve(event) {
console.log('Solved:', event.detail.token);
}
</script>
API Communication
New API (Site Key Mode)
When using cap-site-key
, the widget makes two requests:
-
Challenge Request (GET)
- Endpoint:
{endpoint}/{siteKey}/challenge
- Returns:
{ challenge, token }
- Endpoint:
-
Redeem Request (POST)
- Endpoint:
{endpoint}/{siteKey}/redeem
- Body:
{ token, solutions }
- Returns:
{ success: boolean, token: string, expires: string }
- Endpoint:
Legacy API (Endpoint Mode)
When using cap-api-endpoint
, the widget makes two requests:
-
Challenge Request (POST)
- Endpoint:
{apiEndpoint}challenge
- Returns:
{ challenge, token }
- Endpoint:
-
Redeem Request (POST)
- Endpoint:
{apiEndpoint}redeem
- Body:
{ token, solutions }
- Returns:
{ success: boolean, token: string, expires: string }
- Endpoint:
Fallback and Retry Behavior
In site key mode with multiple endpoints:
- Each endpoint is tried sequentially
- Each endpoint gets up to 3 attempts (configurable)
- Exponential backoff between retries (1s, 2s, 4s, max 5s)
- Request timeout: 10 seconds
- Client errors (400, 401, 403) skip retries
Token Handling
Upon successful verification:
- Token is stored in
widget.token
property - Token is set in a hidden input field (name configurable via
cap-hidden-field-name
) - Token automatically expires based on server response
- Widget automatically resets when token expires
WebAssembly
The widget uses WebAssembly for SHA-256 computation when available. Files are prefetched on load:
https://cdn.jsdelivr.net/npm/@cap.js/wasm@0.0.6/browser/cap_wasm.min.js
https://cdn.jsdelivr.net/npm/@cap.js/wasm@0.0.6/browser/cap_wasm_bg.wasm
Prefetch uses <link rel="prefetch">
which does not block page load or make API requests.
When WebAssembly is unavailable, a JavaScript fallback is used with a warning message displayed.
Custom Configuration
Custom Fetch Function
Override the fetch implementation:
window.CAP_CUSTOM_FETCH = async (url, options) => {
// Custom fetch logic
return fetch(url, options);
};
Custom WASM URL
Override the WASM library location:
window.CAP_CUSTOM_WASM_URL = 'https://your-cdn.com/cap_wasm.min.js';
Custom CSS Nonce
Add a nonce for Content Security Policy:
window.CAP_CSS_NONCE = 'your-nonce-value';
The nonce will be added to the <style>
tag: <style nonce="your-nonce-value">
.
Accessibility
The widget includes ARIA attributes:
role="button"
- Identifies the widget as interactivetabindex="0"
- Allows keyboard focusaria-label
- Describes current state (customizable via i18n attributes)aria-live="polite"
- Announces state changes to screen readers
Keyboard interaction:
- Enter or Space key triggers verification
Browser Compatibility
Required features:
- Custom Elements (Web Components)
- Shadow DOM
- Web Workers
- ES6+ syntax
- Optional: WebAssembly (fallback implemented)
License
Apache-2.0