Invisible ALTCHA proof-of-work spam protection for Gravity Forms. No user interaction, no third-party requests, no captcha puzzles — every submission carries a signed PBKDF2 proof that the browser quietly solved in the background.
- MIT-licensed end to end (altcha-org/altcha for PHP, altcha widget for JS, this plugin for the glue).
- No external API calls — challenges are issued and verified by your own WordPress install.
- No license keys, no quotas.
- Drop-in: enables itself automatically for every Gravity Form.
- WordPress 6.0+
- PHP 8.2+
- Gravity Forms 2.5+
The plugin is published through generoi/packagist.
With that repository configured in your root composer.json:
composer require generoi/gravityforms-altcha
wp plugin activate gravityforms-altcha- Download the latest
gravityforms-altcha.zipfrom Releases. - Upload to
wp-content/plugins/(or via Plugins → Add New → Upload). - Activate.
- Form render — the plugin injects a hidden
<altcha-widget>web component above the submit button on every Gravity Form. - Browser-side proof-of-work — the widget fetches a fresh challenge from
/wp-json/genero/gravityforms-altcha/v1/challenge(signed with a per-site HMAC secret) and brute-forces a PBKDF2/SHA-256 derived-key match. - Submission — the widget writes the solution into a hidden
altchafield that Gravity Forms posts back with the rest of the form. - Server-side verification —
gform_validationdecodes the payload, reconstructs the challenge, and runsaltcha-org/altcha::verifySolution(). On failure the submission is rejected with a generic error message.
There is no admin UI, no per-form configuration, and no settings page — everything customisable lives behind WordPress filters.
Skip protection on specific forms:
add_filter('genero/gravityforms_altcha/should_protect', function (bool $protect, array $form): bool {
// Don't run ALTCHA on internal preview-only forms.
if (in_array((int) $form['id'], [42, 43], true)) {
return false;
}
return $protect;
}, 10, 2);Use an externally-managed secret (for example a dedicated vault entry shared across a fleet of sites):
add_filter('genero/gravityforms_altcha/hmac_key', fn () => getenv('ALTCHA_HMAC_KEY') ?: null);Returning null falls back to the auto-generated gravityforms_altcha_hmac_key
option.
Localise or rewrite the validation error:
add_filter('genero/gravityforms_altcha/error_message', fn () => __('Spam check failed. Please reload and try again.', 'your-textdomain'));composer install
npm install
npm run build # outputs build/widget.js
composer test # PHPUnit suite, no WordPress dependency
composer lint:fix # PintMIT — see LICENSE.
Bundles the MIT-licensed altcha-org/altcha PHP library and the MIT-licensed altcha widget. Neither ships with this repository — both are installed through Composer and npm respectively.