altcha
Version:
Privacy-first CAPTCHA widget, compliant with global regulations (GDPR/HIPAA/CCPA/LGDP/DPDPA/PIPL) and WCAG accessible. No tracking, self-verifying.
413 lines (307 loc) • 15.2 kB
Markdown
# ALTCHA
ALTCHA is a self-hosted, privacy-first security solution that protects your websites, APIs, and online services from spam and abuse through an innovative proof-of-work mechanism. Unlike traditional CAPTCHAs that depend on intrusive methods like cookies or fingerprinting, ALTCHA delivers robust protection while respecting user privacy.
ALTCHA is fully compliant with:
- **Global privacy regulations**: GDPR, HIPAA, CCPA, PIPEDA/CPPA, LGPD, DPDPA, and PIPL
- **Accessibility standards**: [WCAG 2.2 AA-level](https://altcha.org/docs/v2/compliance/wcag/) and the [European Accessibility Act](https://altcha.org/docs/v2/compliance/european-accessibility-act-2025/)
For more details, visit [altcha.org](https://altcha.org).
> [!NOTE]
> **Breaking change (v2.3.0)**
>
> As of version **2.3.0**, the obfuscation and other plugins have been removed from the main package and moved to a separate package: `@altcha/plugins`.
>
> If you do not use any plugins, no changes are required.
>
> See the [migration guide for v2.3.0](https://github.com/altcha-org/altcha/blob/main/MIGRATION-v2.3.0.md).
## Features
- **Frictionless Experience**: Uses proof-of-work (PoW) instead of visual puzzles for a seamless user experience.
- **Code Challenge (New in v2)**: Supports accessible code challenges ("enter code from image") with an audio option.
- **Cookie-Free Design**: GDPR-compliant by default—no cookies or tracking.
- **Fully Accessible**: Meets WCAG 2.2 AA-level standards and complies with the European Accessibility Act (EAA).
- **Lightweight**: Minimal bundle size for fast page loads and optimal performance.
- **Self-Hosted**: No dependency on third-party services.
## What’s New in v2
Version 2 introduces enhanced accessibility, expanded language support, and integration with **ALTCHA Sentinel**—a self-hosted anti-spam solution for websites, apps, and services.
### Key Improvements in v2
- **Built-in Internationalization (i18n)** for 50+ languages
- **Improved RTL (right-to-left) language support**
- **Enhanced WCAG accessibility**
- **Support for accessible code challenges** (image + audio options)
- **Overlay UI**
### Migrating from v1
Version 2 (v2) is fully compatible with v1, and minimal migration steps are required. However, be sure to test your integration after updating.
- Translations: v2 introduces a new [built-in internationalization (i18n) system](#internationalization-i18n). The use of the `strings` attribute is now discouraged in favor of this new system.
- [ALTCHA Sentinel](https://altcha.org/docs/v2/sentinel): Sentinel is a new self-hosted solution that replaces the previous SaaS services and the SpamFilter. We recommend migrating to Sentinel for better compliance, enhanced security, unlimited verifications, and an adaptive Captcha with code-challenge support.
## Examples
Explore starter templates for popular frameworks:
- [React](https://github.com/altcha-org/altcha-starter-react-ts)
- [Vue](https://github.com/altcha-org/altcha-starter-vue-ts)
- [Svelte](https://github.com/altcha-org/altcha-starter-svelte-ts)
- [Solid](https://github.com/altcha-org/altcha-starter-solid-ts)
- [Lit](https://github.com/altcha-org/altcha-starter-lit-ts)
- [Angular](https://github.com/altcha-org/altcha-starter-angular)
## Server Integrations
- [TypeScript](https://github.com/altcha-org/altcha-lib)
- [PHP](https://github.com/altcha-org/altcha-lib-php)
- [Go](https://github.com/altcha-org/altcha-lib-go)
- [Python](https://github.com/altcha-org/altcha-lib-py)
- [Java](https://github.com/altcha-org/altcha-lib-java)
- [Ruby](https://github.com/altcha-org/altcha-lib-rb)
- [Elixir](https://github.com/altcha-org/altcha-lib-ex)
## Plugins & CMS
- [Libraries and plugins](https://altcha.org/docs/v2/libraries/)
## Usage
The ALTCHA widget is distributed as a **Web Component** and [supports all modern browsers](https://developer.mozilla.org/en-US/docs/Web/API/Web_components#browser_compatibility).
### 1. Install ALTCHA
```sh
npm install altcha
```
Import in your main file:
```js
import 'altcha';
```
Or load via `<script>` tag:
```html
<script async defer src="/altcha.js" type="module"></script>
```
**CDN**:
```html
<script
async
defer
src="https://cdn.jsdelivr.net/gh/altcha-org/altcha@main/dist/altcha.min.js"
type="module"
></script>
```
### 2. Add `<altcha-widget>` to Your Forms
```html
<form>
<altcha-widget challengeurl="https://..."></altcha-widget>
</form>
```
See [configuration options](#configuration) or the [website integration docs](https://altcha.org/docs/v2/widget-integration).
### 3. Integrate with Your Server
Refer to the [server documentation](https://altcha.org/docs/v2/server-integration) for implementation details.
## Supported Browsers
ALTCHA works on modern browsers with **Web Crypto API** support (specifically `crypto.subtle` - [caniuse.com](https://caniuse.com/?search=subtle)).
**Supported**:
- Chrome 67+ (desktop & Android)
- Edge 79+
- Firefox 63+ (desktop & Android)
- Safari 11+ (macOS & iOS)
- Any browser supporting Web Components + Web Crypto
**Not Supported**:
- Internet Explorer 11 (or older)
## Bundle Size
ALTCHA is optimized for performance:
| Distribution | Size (GZIPped) |
| ---------------------------- | -------------- |
| ALTCHA | 30 kB |
| ALTCHA with all translations | 46 kB |
| Cloudflare Turnstile | 85+ kB |
| hCaptcha | 250+ kB |
| reCAPTCHA | 300+ kB |
When GZIPped, it totals about 30 kB, making ALTCHA’s widget about 90% smaller than reCAPTCHA.
## Content Security Policy (CSP)
The default bundle includes styles and workers in a single file. For strict CSP compliance, use scripts from `/dist_external`. Learn more in the [documentation](https://altcha.org/docs/v2/widget-integration).
## Configuration
Required options (at least one is required):
- **challengeurl**: Server endpoint to fetch the challenge.
- **challengejson**: Preloaded JSON challenge data (avoids HTTP requests).
Additional options:
- **auto**: Automatically verify without user interaction (possible values: `off`, `onfocus`, `onload`, `onsubmit`).
- **credentials**: Whether to include [credentials](https://developer.mozilla.org/en-US/docs/Web/API/RequestInit#credentials) with the challenge request (possible values: `omit`, `same-origin`, `include`).
- **customfetch**: A custom `fetch` function for retrieving the challenge.
Accepts `url: string` and `init: RequestInit` as arguments and must return a [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response).
- **delay**: Artificial delay in milliseconds before verification (defaults to 0).
- **disableautofocus**: If true, prevents the code-challenge input from automatically receiving focus on render (defaults to `false`).
- **disablerefetchonexpire**: Whether to disable automatic re-fetch and re-validation when the challenge expires (defaults to `false`).
- **expire**: Challenge expiration duration in milliseconds.
- **floating**: Enable floating UI (possible values: `auto`, `top`, `bottom`).
- **floatinganchor**: CSS selector of the "anchor" to which the floating UI will be attached (defaults to the `button[type="submit"]` in the related form).
- **floatingoffset**: Y offset from the anchor element for the floating UI in pixels (defaults to `12`).
- **floatingpersist**: Whether to "persist" (keep visible) the floating widget after verification (possible values: `true` | `false` | `focus`; defaults to `false`, meaning the widget will hide).
- **hidefooter**: Hide the footer (ALTCHA link).
- **hidelogo**: Hide the ALTCHA logo.
- **id**: The checkbox `id` attribute. Useful for multiple instances of the widget on the same page.
- **language**: The ISO alpha-2 code of the language to use (the language file be imported from `altcha/i18n/*`).
- **maxnumber**: Max number to iterate to (defaults to 1,000,000).
- **name**: Name of the hidden field containing the payload (defaults to "altcha").
- **overlay**: Enables overlay UI mode (automatically sets `auto="onsubmit"`).
- **overlaycontent**: CSS selector of the HTML element to display in the overlay modal before the widget.
- **strings**: JSON-encoded translation strings. Refer to [customization](https://altcha.org/docs/v2/widget-customization).
- **verifyurl**: URL for server-side verification requests. This option is automatically configured with Sentinel. Override this setting only if using a custom server implementation. Supports `fn:function_name` format to call a global JS function instead.
- **workers**: Number of workers to utilize for PoW (defaults to `navigator.hardwareConcurrency || 8`, max value `16`).
- **workerurl**: URL of the Worker script (defaults to `./worker.js`, only works with `external` build).
Data Obfuscation options:
- **obfuscated**: The [obfuscated data](https://altcha.org/docs/v2/obfuscation) provided as a base64-encoded string (requires `altcha/obfuscation` plugin). Use only without `challengeurl`/`challengejson`.
Development / Testing options:
- **debug**: Print log messages in the console.
- **mockerror**: Causes verification to always fail with a "mock" error.
- **test**: Generates a "mock" challenge within the widget, bypassing the request to `challengeurl`.
## Internationalization (i18n)
ALTCHA supports **50+ languages**. You can import individual language translations or a bundle that includes all of them.
### Importing Translations
To import all translations:
```js
import 'altcha/i18n/all';
```
To import specific languages only:
```js
import 'altcha/i18n/de';
import 'altcha/i18n/fr-fr';
```
Alternatively, you can import the combined bundle, which includes both the widget and all translations:
```js
import 'altcha/i18n';
```
### Language Detection
The widget automatically detects the language from:
- The `<html lang="...">` attribute
- The user's browser settings (`navigator.languages`)
To override the language manually, use the `language` attribute:
```html
<altcha-widget language="de"></altcha-widget>
```
### Customizing Translations
You can override default translations by updating the global `altchaI18n` registry (`globalThis.altchaI18n` or `window.altchaI18n`):
```js
import 'altcha/i18n/de';
globalThis.altchaI18n.set('de', {
...globalThis.altchaI18n.get('de'),
label: 'Ich bin ein Mensch', // Custom label
});
```
## Code Challenges
For additional verification, ALTCHA supports **image/audio code challenges** (e.g., "Enter the code from the image"). This feature requires [ALTCHA Sentinel](https://altcha.org/docs/v2/sentinel) or a custom server implementation.
## Plugins
Extend functionality with plugins:
```js
import 'altcha/obfuscation'; // Data obfuscation
import 'altcha/upload'; // File uploads
import 'altcha'; // Main package
```
Enable plugins per widget:
```html
<altcha-widget plugins="upload,obfuscation"></altcha-widget>
```
### Available Plugins
- **obfuscation**: Secure sensitive data (emails, phone numbers).
- **upload**: File uploads with ALTCHA Sentinel or a custom backend.
## Programmatic Configuration
To configure the widget programmatically, use the `configure()` method:
```ts
document.querySelector('#altcha').configure({
challenge: {
algorithm: 'SHA-256',
challenge: '...',
salt: '...',
signature: '...',
},
strings: {
label: 'Verify',
},
});
```
Available configuration options:
```ts
export interface Configure {
auto?: 'off' | 'onfocus' | 'onload' | 'onsubmit';
challenge?: {
codeChallenge?: {
audio?: string;
image: string;
length?: number;
};
algorithm: string;
challenge: string;
maxnumber?: number;
salt: string;
signature: string;
};
challengeurl?: string;
credentials?: 'omit' | 'same-origin' | 'include' | boolean;
customfetch?:
| string
| ((url: string, init?: RequestInit) => Promise<Response>);
debug?: boolean;
delay?: number;
disableautofocus?: boolean;
disablerefetchonexpire?: boolean;
expire?: number;
floating?: 'auto' | 'top' | 'bottom';
floatinganchor?: string;
floatingoffset?: number;
floatingpersist?: boolean | 'focus';
hidefooter?: boolean;
hidelogo?: boolean;
maxnumber?: number;
mockerror?: boolean;
name?: string;
obfuscated?: string;
overlay?: boolean;
refetchonexpire?: boolean; // deprecated, use disablerefetchonexpire
spamfilter?: boolean | 'ipAddress' | SpamFilter; // deprecated
strings?: {
ariaLinkLabel: strin;
enterCode: string;
enterCodeAria: string;
error: string;
expired: string;
footer: string;
getAudioChallenge: string;
label: string;
loading: string;
reload: strin;
verificationRequired: string;
verified: string;
verifying: string;
waitAlert: string;
};
test?: boolean | number | 'delay';
verifyurl?: string;
workers?: number;
workerurl?: string;
}
```
## Methods
- `configure(options)` - Configures the widget with the given options. See Configuration options above.
- `getConfiguration()` - Returns the current configuration.
- `getState()` - Returns the current `state` of the widget.
- `show()` - Displays the widget (used in floating or overlay mode).
- `hide()` - Hides the widget (used in floating or overlay mode).
- `reset(state?, err?)` - Resets the internal `state`, optionally with an error.
- `setState(state, err?)` - Manually sets the specified `state`, optionally with an error.
- `setFloatingAnchor(element)` - Sets the anchor element for the floating UI.
- `verify()` - Initiates the verification process.s a "mock" challenge within the widget, bypassing the request to `challengeurl`.
## Events
- **code** - Triggers when code-challenge verification is requested.
- **load** - Triggers when the widget loads. The exported methods become available after this event.
- **sentinelverification** - Triggers upon a verification with ALTCHA Sentinel.
- **serververification** - (Deprecated) Triggers upon a server verification (only in conjunction with `spamfilter`).
- **statechange** - Triggers whenever an internal `state` changes.
- **verified** - Triggers when the challenge is verified.
```ts
enum State {
CODE = 'code',
ERROR = 'error',
VERIFIED = 'verified',
VERIFYING = 'verifying',
UNVERIFIED = 'unverified',
EXPIRED = 'expired',
}
```
Using events:
```js
document.querySelector('#altcha').addEventListener('statechange', (ev) => {
// See enum State above
console.log('state:', ev.detail.state);
});
```
> [!IMPORTANT]
> Both programmatic configuration and event listeners have to called/attached after the ALTCHA script loads, such as within `window.addEventListener('load', ...)`.
## Contributing
See [Contributing Guide](https://github.com/altcha-org/altcha/blob/main/CONTRIBUTING.md) and please follow our [Code of Conduct](https://github.com/altcha-org/altcha/blob/main/CODE_OF_CONDUCT.md).
## Sponsorship
This project is sponsored by [BAUSW.com - Digital Construction Site Diary](https://bausw.com/digital-construction-diary/), promoting transparency and trust in construction projects with real-time documentation.
## License
**MIT**