{"id":14990171,"url":"https://github.com/altcha-org/altcha","last_synced_at":"2026-05-23T07:11:08.520Z","repository":{"id":207907591,"uuid":"720381676","full_name":"altcha-org/altcha","owner":"altcha-org","description":"GDPR, WCAG 2.2 AA, and EAA compliant, self-hosted CAPTCHA alternative with PoW mechanism and advanced anti-spam filter.","archived":false,"fork":false,"pushed_at":"2025-04-28T10:07:18.000Z","size":1759,"stargazers_count":815,"open_issues_count":3,"forks_count":34,"subscribers_count":7,"default_branch":"main","last_synced_at":"2025-05-03T12:36:32.174Z","etag":null,"topics":["antispam","captcha","captcha-alternative","ddos-mitigation","ddos-protection","hcaptcha","proof-of-work","recaptcha","spam-api","spam-detection","spam-filtering","spam-prevention","spam-protection","svelte","wcag","webcomponent"],"latest_commit_sha":null,"homepage":"https://altcha.org","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/altcha-org.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.txt","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2023-11-18T10:05:44.000Z","updated_at":"2025-05-02T16:18:06.000Z","dependencies_parsed_at":"2023-12-05T05:25:16.597Z","dependency_job_id":"dca6d7ea-31d0-47ea-bd90-84e5066cc67d","html_url":"https://github.com/altcha-org/altcha","commit_stats":{"total_commits":75,"total_committers":3,"mean_commits":25.0,"dds":"0.040000000000000036","last_synced_commit":"dc10c7262e102eda85e018ea63796d7b1c9c351e"},"previous_names":["altcha-org/altcha","altcha-org/altchajs"],"tags_count":50,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/altcha-org%2Faltcha","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/altcha-org%2Faltcha/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/altcha-org%2Faltcha/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/altcha-org%2Faltcha/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/altcha-org","download_url":"https://codeload.github.com/altcha-org/altcha/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253890452,"owners_count":21979833,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["antispam","captcha","captcha-alternative","ddos-mitigation","ddos-protection","hcaptcha","proof-of-work","recaptcha","spam-api","spam-detection","spam-filtering","spam-prevention","spam-protection","svelte","wcag","webcomponent"],"created_at":"2024-09-24T14:19:39.157Z","updated_at":"2026-05-04T08:05:11.643Z","avatar_url":"https://github.com/altcha-org.png","language":"JavaScript","funding_links":[],"categories":["JavaScript","Third Party Components","svelte","Cybersecurity"],"sub_categories":["Captcha"],"readme":"# ALTCHA\n\nALTCHA 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.\n\nALTCHA is fully compliant with:\n\n- **Global privacy regulations**: GDPR, HIPAA, CCPA, PIPEDA/CPPA, LGPD, DPDPA, and PIPL\n- **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/)\n\nFor more details, visit [altcha.org](https://altcha.org).\n\n## Playground\n\nWant to see it in action? Visit the official ALTCHA Playground to experiment with widget configurations, fine-tune the Proof-of-Work (PoW) settings, and see how the security mechanisms hold up in real-time.\n\n[Open ALTCHA Playground](https://playground.altcha.org)\n\n## Features\n\n- **Frictionless Experience**: Eliminates frustrating visual puzzles by using background **Proof-of-Work (PoW)** for a seamless user journey.\n- **Hardware-Resistant Security**: Leverages **Argon2 and Scrypt** memory-bound algorithms to neutralize hardware acceleration (ASICs/GPUs) and sophisticated bot farms.\n- **Accessible Code Challenges**: Provides \"Enter code from image\" fallbacks with built-in **audio support** for visually impaired users.\n- **Privacy by Design**: Fully **GDPR compliant** and cookie-free—no tracking, no fingerprinting, and no data collection.\n- **Universal Accessibility**: Engineered to exceed **WCAG 2.2 AA** standards, ensuring compliance with the **European Accessibility Act (EAA)**.\n- **Lightweight**: Minimal footprint, optimized for rapid page loads and high-performance environments.\n- **100% Self-Hosted**: Maintain full sovereignty over your infrastructure with no reliance on third-party API availability.\n\n## What’s New in v3\n\n- **Next-Gen PoW**: Significant performance gains and reduced CPU overhead through an optimized verification mechanism.\n- **Advanced Bot Defense**: Native support for **Argon2 and Scrypt**, raising the cost of attack for automated scripts and specialized hardware.\n- **Modern UI**: Refined styling options, including a suite of new built-in themes and improved CSS custom property support.\n- **Developer Experience**: Improved TypeScript support and streamlined integration.\n\n### Migrating from v2\n\nSee [MIGRATION-v2.md](https://github.com/altcha-org/altcha/blob/v3/MIGRATION-v2.md).\n\n## Examples\n\nExplore starter templates for popular frameworks:\n\n- [React](https://github.com/altcha-org/altcha-starter-react-ts)\n- [Vue](https://github.com/altcha-org/altcha-starter-vue-ts)\n- [Svelte](https://github.com/altcha-org/altcha-starter-svelte-ts)\n- [Solid](https://github.com/altcha-org/altcha-starter-solid-ts)\n- [Lit](https://github.com/altcha-org/altcha-starter-lit-ts)\n- [Angular](https://github.com/altcha-org/altcha-starter-angular)\n\n## Server Integrations\n\n- [TypeScript](https://github.com/altcha-org/altcha-lib)\n- [Dart](https://github.com/altcha-org/altcha-lib-dart)\n- [PHP](https://github.com/altcha-org/altcha-lib-php)\n- [Go](https://github.com/altcha-org/altcha-lib-go)\n- [Python](https://github.com/altcha-org/altcha-lib-py)\n- [Java](https://github.com/altcha-org/altcha-lib-java)\n- [Ruby](https://github.com/altcha-org/altcha-lib-rb)\n- [Elixir](https://github.com/altcha-org/altcha-lib-ex)\n- [Rust](https://github.com/altcha-org/altcha-lib-rs)\n- [C++](https://github.com/altcha-org/altcha-lib-cpp)\n\n## Plugins \u0026 CMS\n\n- [Libraries and plugins](https://altcha.org/docs/v2/libraries/)\n\n## Usage\n\nThe ALTCHA widget is distributed as a **Web Component**.\n\n### 1. Install ALTCHA\n\n```sh\nnpm install altcha\n```\n\nImport in your main file:\n\n```js\nimport 'altcha';\n```\n\nOr load via `\u003cscript\u003e` tag:\n\n```html\n\u003cscript async defer src=\"/altcha.js\" type=\"module\"\u003e\u003c/script\u003e\n```\n\n### 2. Add `\u003caltcha-widget\u003e` to Your Forms\n\n```html\n\u003cform\u003e\n\t\u003caltcha-widget challenge=\"https://...\"\u003e\u003c/altcha-widget\u003e\n\u003c/form\u003e\n```\n\nSee [configuration options](#configuration) or the [website integration docs](https://altcha.org/docs/v2/widget-integration).\n\n### 3. Integrate with Your Server\n\nRefer to the [server documentation](https://altcha.org/docs/v2/server-integration) for implementation details.\n\n## Supported Browsers\n\nALTCHA works on modern browsers with **Web Crypto API** support (specifically `crypto.subtle` - [caniuse.com](https://caniuse.com/?search=subtle)).\n\n**Supported**:\n\n- Chrome 67+ (desktop \u0026 Android)\n- Edge 79+\n- Firefox 63+ (desktop \u0026 Android)\n- Safari 11+ (macOS \u0026 iOS)\n- Any browser supporting Web Components + Web Crypto\n\n**Not Supported**:\n\n- Internet Explorer 11 (or older)\n\n## Bundle Size\n\nALTCHA is optimized for performance:\n\n| Distribution                 | Size (GZIPped) |\n| ---------------------------- | -------------- |\n| ALTCHA                       | 34 kB          |\n| ALTCHA with all translations | 52 kB          |\n| Cloudflare Turnstile         | 85+ kB         |\n| hCaptcha                     | 250+ kB        |\n| reCAPTCHA                    | 300+ kB        |\n\nWhen GZIPped, it totals about 34 kB, making ALTCHA’s widget about ~90% smaller than reCAPTCHA.\n\n## Content Security Policy (CSP)\n\nThe 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).\n\n## Configuration\n\n### Programmatic Configuration\n\nThe widget provides a global `$altcha` object to manage defaults, register new algorithms, or add custom translations.\n\nTo update an existing widget instance, use the `.configure()` [method](). This is the preferred way to handle complex objects or functions that cannot be passed via HTML attributes.\n\n```ts\n// Set defaults for all future widget instances:\n$altcha.defaults.set({\n\tchallenge: 'https://api.example.com/challenge',\n\tdebug: true\n});\n\n// Update a specific instance dynamically:\nconst widget = document.querySelector('altcha-widget');\nwidget.configure({\n\tworkers: 2,\n\tlanguage: 'fr'\n});\n```\n\n### Attribute Configuration\n\nFor simple implementations, the widget supports a subset of configuration options directly as HTML attributes. For more advanced properties, use the programmatic approach above.\n\n**Supported Attributes:**\n\n```html\n\u003caltcha-widget\n\tauto=\"off\"\n\tchallenge=\"https://api.example.com/challenge\"\n\tconfiguration='{\"minDuration\": 1000}'\n\tdisplay=\"standard\"\n\tlanguage=\"en\"\n\tname=\"altcha\"\n\ttheme=\"default\"\n\ttype=\"checkbox\"\n\tworkers=\"4\"\n\u003e\u003c/altcha-widget\u003e\n```\n\n\u003e [!TIP]\n\u003e The `configuration` attribute accepts a JSON-encoded string, allowing you to pass complex settings directly in your HTML markup.\n\n### Core Settings\n\n- **`name`**: The `name` attribute of the hidden input field containing the payload. (Default: `\"altcha\"`)\n- **`challenge`**: The challenge data or the URL to fetch a new challenge from.\n- **`type`**: Visual style of the interaction element (`'native'`, `'checkbox'`, or `'switch'`).\n- **`language`**: The ISO alpha-2 language code for localization (requires corresponding i18n file).\n- **`workers`**: The number of Web Workers to spawn for proof-of-work calculations.\n\n### Automation \u0026 Timing\n\n- **`auto`**: Determines when verification triggers automatically (`'off'`, `'onfocus'`, `'onload'`, or `'onsubmit'`).\n- **`minDuration`**: The minimum verification time in milliseconds; adds an artificial delay if the PoW is faster. (Default: `500`)\n- **`retryOnOutOfMemoryError`**: Automatically attempts to restart verification with fewer workers if the browser runs out of memory (Argon2 and Scrypt only).\n\n### UI \u0026 Display\n\n- **`display`**: The visual layout mode (`'standard'`, `'bar'`, `'floating'`, `'overlay'`, or `'invisible'`).\n- **`barPlacement`**: Vertical position of the widget when `display` is set to `bar` (`'bottom'` or `'top'`).\n- **`hideLogo`**: Hides the ALTCHA logo icon.\n- **`hideFooter`**: Hides the \"ALTCHA\" attribution link.\n- **`validationMessage`**: Custom validation message for the HTML5 `setCustomValidity` API.\n\n### Floating Widget Settings\n\n- **`floatingAnchor`**: The element or CSS selector the floating UI attaches to. Defaults to the first submit button.\n- **`floatingPlacement`**: Preferred position relative to the anchor (`'auto'`, `'bottom'`, or `'top'`).\n- **`floatingOffset`**: Vertical offset in pixels between the UI and its anchor. (Default: `12`)\n- **`floatingPersist`**: Whether the floating widget remains visible after successful verification.\n- **`popoverPlacement`**: Preferred position of popovers relative to the widget (`'auto'`, `'bottom'`, or `'top'`).\n\n### Modal \u0026 Challenge Settings\n\n- **`codeChallengeDisplay`**: UI layout for the code-challenge modal (`'standard'`, `'overlay'`, or `'bottomsheet'`).\n- **`overlayContent`**: CSS selector for an element to be mirrored inside the overlay modal.\n- **`audioChallengeLanguage`**: Forces a specific language for audio-based challenges.\n- **`disableAutoFocus`**: Prevents the code-challenge modal from stealing focus when opened.\n\n### Advanced \u0026 Debugging\n\n- **`debug`**: Enables verbose logging in the browser console.\n- **`test`**: Mocks a successful verification for testing environments.\n- **`mockError`**: Forces the widget into a failed state for UI testing.\n- **`fetch`**: A custom `fetch` implementation for network requests.\n- **`humanInteractionSignature`**: Whether the collector for HIS is enabled (Default: `true`).\n- **`setCookie`**: When configured, sends the payload as a cookie.\n- **`timeout`**: Verification timeout in milliseconds (Default: `90_000`).\n- **`verifyFunction`**: A custom verification handler that overrides default network verification.\n\n## Algorithms\n\nALTCHA supports multiple proof-of-work algorithms. `PBKDF2/*` and `SHA-*` are bundled with the main widget by default. `Argon2` and `Scrypt` are memory-bound algorithms that resist hardware acceleration (ASICs/GPUs) but require importing their workers separately.\n\n**Supported algorithms:**\n\n- `PBKDF2/SHA-256` (default, bundled)\n- `PBKDF2/SHA-384` (bundled)\n- `PBKDF2/SHA-512` (bundled)\n- `SHA-256` (bundled)\n- `SHA-384` (bundled)\n- `SHA-512` (bundled)\n- `ARGON2ID` (requires separate worker import)\n- `SCRYPT` (requires separate worker import)\n\nIf you use `Argon2` or `Scrypt`, import their workers and register them via the `$altcha.algorithms` global before the widget initializes.\n\n### Adding Argon2 / Scrypt Workers (Vite)\n\nWorks with both `altcha` and `altcha/external`:\n\n```ts\nimport 'altcha'; // or 'altcha/external'\nimport Argon2idWorker from 'altcha/workers/argon2id?worker';\nimport ScryptWorker from 'altcha/workers/scrypt?worker';\n\n$altcha.algorithms.set('ARGON2ID', () =\u003e new Argon2idWorker());\n$altcha.algorithms.set('SCRYPT', () =\u003e new ScryptWorker());\n```\n\n### Without Bundler Worker Import Support\n\nIf your environment does not support `?worker` imports, load the prebuilt worker files directly:\n\n```ts\nimport 'altcha';\n\n$altcha.algorithms.set(\n\t'ARGON2ID',\n\t() =\u003e new Worker('/path/to/node_modules/altcha/dist/workers/argon2id.js')\n);\n$altcha.algorithms.set(\n\t'SCRYPT',\n\t() =\u003e new Worker('/path/to/node_modules/altcha/dist/workers/scrypt.js')\n);\n```\n\n### Using `altcha/external`\n\n`altcha/external` excludes all bundled workers, requiring you to register every algorithm explicitly. Use this for full control over which workers are loaded:\n\n```ts\nimport 'altcha/external';\nimport Argon2idWorker from 'altcha/workers/argon2id?worker';\nimport Pbkdf2Worker from 'altcha/workers/pbkdf2?worker';\nimport ScryptWorker from 'altcha/workers/scrypt?worker';\nimport ShaWorker from 'altcha/workers/sha?worker';\n\n$altcha.algorithms.set('PBKDF2/SHA-256', () =\u003e new Pbkdf2Worker());\n$altcha.algorithms.set('PBKDF2/SHA-384', () =\u003e new Pbkdf2Worker());\n$altcha.algorithms.set('PBKDF2/SHA-512', () =\u003e new Pbkdf2Worker());\n$altcha.algorithms.set('SHA-256', () =\u003e new ShaWorker());\n$altcha.algorithms.set('SHA-384', () =\u003e new ShaWorker());\n$altcha.algorithms.set('SHA-512', () =\u003e new ShaWorker());\n$altcha.algorithms.set('ARGON2ID', () =\u003e new Argon2idWorker());\n$altcha.algorithms.set('SCRYPT', () =\u003e new ScryptWorker());\n```\n\n## Cookies\n\nBy default, the widget sends the ALTCHA payload as a form field by creating a hidden input. It can also be configured to send the payload via a cookie.\n\nTo enable this behavior, use the `setCookie` configuration option:\n\n```ts\nwidget.configure({\n\tsetCookie: {\n\t\tname: 'altcha',\n\t\tpath: '/'\n\t}\n});\n```\n\n`setCookie` accepts the following cookie options:\n\n```ts\ninterface SetCookieOptions {\n\tdomain?: string;\n\tname?: string;\n\tmaxAge?: number;\n\tpath?: string;\n\tsameSite?: string;\n\tsecure?: boolean;\n}\n```\n\n## Server Configuration\n\nWhen the widget fetches a challenge from the server, the server can override widget configuration using either the `X-Altcha-Config` response header or the `configuration` property in the challenge response.\n\nExample using the `configuration` property in the challenge JSON response to force cookie usage:\n\n```json\n{\n\t\"configuration\": {\n\t\t\"setCookie\": {\n\t\t\t\"name\": \"altcha\",\n\t\t\t\"path\": \"/submit\"\n\t\t}\n\t},\n\t\"parameters\": {},\n\t\"signature\": \"...\"\n}\n```\n\nThe `X-Altcha-Config` header must contain a JSON-encoded object with configuration options.\n\n## Internationalization (i18n)\n\nALTCHA supports **50+ languages**. You can import individual language translations or a bundle that includes all of them.\n\n### Importing Translations\n\nTo import all translations:\n\n```js\nimport 'altcha/i18n/all';\n```\n\nTo import specific languages only:\n\n```js\nimport 'altcha/i18n/de';\nimport 'altcha/i18n/fr-fr';\n```\n\nAlternatively, you can import the combined bundle, which includes both the widget and all translations:\n\n```js\nimport 'altcha/i18n';\n```\n\n### Language Detection\n\nThe widget automatically detects the language from:\n\n- The `\u003chtml lang=\"...\"\u003e` attribute\n- The user's browser settings (`navigator.languages`)\n\nTo override the language manually, use the `language` attribute:\n\n```html\n\u003caltcha-widget language=\"de\"\u003e\u003c/altcha-widget\u003e\n```\n\n### Customizing Translations\n\nYou can override default translations by updating the global `$altcha` registry (`globalThis.$altcha.i18n`):\n\n```js\nimport 'altcha/i18n/de';\n\n$altcha.i18n.set('de', {\n\t...$altcha.i18n.get('de'),\n\tlabel: 'Ich bin ein Mensch' // Custom label\n});\n```\n\n## Code Challenges\n\nFor 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.\n\n## Data Obfuscation\n\n[Data obfuscation]() is supported via an official plugin, which must be imported alongside the widget. This is ideal for protecting sensitive information, such as email addresses, from scrapers until the challenge is solved.\n\nTo obfuscate data, run:\n\n```sh\nnpx altcha-lib obfuscate [data]\n```\n\n### Programmatic Usage\n\nThe plugin exports `ObfuscationPlugin` with static methods `obfuscate` and `deobfuscate` for manual data handling:\n\n```ts\nimport { ObfuscationPlugin } from 'altcha/plugins/obfuscation';\n\nconst obfuscatedData = await ObfuscationPlugin.obfuscate('mailto:hello@example.com');\n```\n\n### Widget Integration\n\nTo use the plugin with the widget, ensure `altcha/plugins/obfuscation` is imported before the main library. Use the `data-obfuscated` attribute to provide the Base64-encoded payload:\n\n```html\n\u003cscript\u003e\n\timport 'altcha/plugins/obfuscation';\n\timport 'altcha';\n\u003c/script\u003e\n\n\u003caltcha-widget data-obfuscated=\"${obfuscatedData}\" display=\"floating\"\u003e\u003c/altcha-widget\u003e\n```\n\n## Methods\n\n- `configure(options)` - Configures the widget with the given options. See Configuration options above.\n- `getConfiguration()` - Returns the current configuration.\n- `getState()` - Returns the current `state` of the widget.\n- `show()` - Displays the widget (used in some display modes).\n- `hide()` - Hides the widget (used in some display modes).\n- `reset(state?, err?)` - Resets the internal `state`, optionally with an error.\n- `setState(state, err?)` - Manually sets the specified `state`, optionally with an error.\n- `updateUI()` - Force UI update or reposition, for example for the floating display mode.\n- `verify()` - Initiates the verification process.\n\n## Events\n\n- **codechallenge** - Triggers when code-challenge verification is requested.\n- **expired** - Triggers when the challenge expires.\n- **load** - Triggers when the widget loads. The exported methods become available after this event.\n- **outofmemory** - Triggers when an Out-Of-Memory error is received (Argon2 and Scrypt only).\n- **serververification** -Triggers upon a server verification.\n- **statechange** - Triggers whenever an internal `state` changes.\n- **verified** - Triggers when the challenge is verified.\n\n```ts\nenum State {\n\tCODE = 'code',\n\tERROR = 'error',\n\tVERIFIED = 'verified',\n\tVERIFYING = 'verifying',\n\tUNVERIFIED = 'unverified',\n\tEXPIRED = 'expired'\n}\n```\n\nUsing events:\n\n```js\ndocument.querySelector('altcha-widget').addEventListener('statechange', (ev) =\u003e {\n\t// See enum State above\n\tconsole.log('state:', ev.detail.state);\n});\n```\n\n\u003e [!IMPORTANT]  \n\u003e Both programmatic configuration and event listeners have to called/attached after the ALTCHA script loads, such as within `window.addEventListener('load', ...)`.\n\n## Contributing\n\nSee [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).\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faltcha-org%2Faltcha","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faltcha-org%2Faltcha","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faltcha-org%2Faltcha/lists"}