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 and the European Accessibility Act
For more details, visit altcha.org.
- 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.
Version 2 introduces enhanced accessibility, expanded language support, and integration with ALTCHA Sentinel—a self-hosted anti-spam solution for websites, apps, and services.
- Built-in Internationalization (i18n) for 48+ languages
- Improved RTL (right-to-left) language support
- Enhanced WCAG accessibility
- Support for accessible code challenges (image + audio options)
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. The use of the
strings
attribute is now discouraged in favor of this new system. - ALTCHA 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.
Explore starter templates for popular frameworks:
The ALTCHA widget is distributed as a Web Component and supports all modern browsers.
npm install altcha
Import in your main file:
import 'altcha';
Or load via <script>
tag:
<script async defer src="/altcha.js" type="module"></script>
CDN:
<script
async
defer
src="https://cdn.jsdelivr.net/gh/altcha-org/altcha@main/dist/altcha.min.js"
type="module"
></script>
<form>
<altcha-widget challengeurl="https://..."></altcha-widget>
</form>
See configuration options or the website integration docs.
Refer to the server documentation for implementation details.
ALTCHA works on modern browsers with Web Crypto API support (specifically crypto.subtle
- caniuse.com).
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)
ALTCHA is optimized for performance:
Distribution | Size (GZIPped) |
---|---|
ALTCHA | 29+ kB |
ALTCHA with all translations | 42+ kB |
hCaptcha | 48+ kB |
reCAPTCHA | 270+ kB |
When GZIPped, it totals about 29 kB, making ALTCHA’s widget about 90% smaller than reCAPTCHA.
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.
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 with the challenge request (possible values:
omit
,same-origin
,include
). - customfetch: A custom
fetch
function for retrieving the challenge.
Acceptsurl: string
andinit: RequestInit
as arguments and must return aResponse
. - 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
). - 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 tofalse
, 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").
- strings: JSON-encoded translation strings. Refer to customization.
- refetchonexpire: Automatically re-fetch and re-validate when the challenge expires (defaults to true).
- 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 value16
). - workerurl: URL of the Worker script (defaults to
./worker.js
, only works withexternal
build).
Data Obfuscation options:
- obfuscated: The obfuscated data provided as a base64-encoded string (requires
altcha/obfuscation
plugin). Use only withoutchallengeurl
/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
.
ALTCHA supports 48+ languages. You can import individual language translations or a bundle that includes all of them.
To import all translations:
import 'altcha/i18n/all';
To import specific languages only:
import 'altcha/i18n/de';
import 'altcha/i18n/fr-fr';
Alternatively, you can import the combined bundle, which includes both the widget and all translations:
import 'altcha/i18n';
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:
<altcha-widget language="de"></altcha-widget>
You can override default translations by updating the global altchaI18n
registry (globalThis.altchaI18n
or window.altchaI18n
):
import 'altcha/i18n/de';
globalThis.altchaI18n.set('de', {
...globalThis.altchaI18n.get('de'),
label: 'Ich bin ein Mensch', // Custom label
});
For additional verification, ALTCHA supports image/audio code challenges (e.g., "Enter the code from the image"). This feature requires ALTCHA Sentinel or a custom server implementation.
Extend functionality with plugins:
import 'altcha/obfuscation'; // Data obfuscation
import 'altcha/upload'; // File uploads
import 'altcha'; // Main package
Enable plugins per widget:
<altcha-widget plugins="upload,obfuscation"></altcha-widget>
- obfuscation: Secure sensitive data (emails, phone numbers).
- upload: File uploads with ALTCHA Sentinel or a custom backend.
To configure the widget programmatically, use the configure()
method:
document.querySelector('#altcha').configure({
challenge: {
algorithm: 'SHA-256',
challenge: '...',
salt: '...',
signature: '...',
},
strings: {
label: 'Verify',
},
});
Available configuration options:
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;
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;
refetchonexpire?: boolean;
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;
}
- 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.
enum State {
CODE = 'code',
ERROR = 'error',
VERIFIED = 'verified',
VERIFYING = 'verifying',
UNVERIFIED = 'unverified',
EXPIRED = 'expired',
}
Using events:
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', ...)
.
See Contributing Guide and please follow our Code of Conduct.
This project is sponsored by BAUSW.com - Digital Construction Site Diary, promoting transparency and trust in construction projects with real-time documentation.
MIT