ExpressionEngine add-on · CleanTalk cloud anti-spam
CleanTalk Anti-Spam for ExpressionEngine
Protect supported ExpressionEngine and Solspace Freeform submissions with server-side CleanTalk classification—without adding a CAPTCHA challenge to the form.
Current version
ExpressionEngine
PHP
License
Invisible checks
Submissions are classified server-side. Optional Bot Detector adds a browser signal without a visitor challenge.
Native EE handling
Dedicated hooks reject suspected spam before supported content is saved or email is delivered.
Per-form controls
Enable protection individually for comments, registrations, Email forms, Channel Forms, and Freeform.
Controlled data scope
Only relevant allowlisted fields are sent. Passwords, uploads, security fields, cookies, and arbitrary POST data are excluded.
Explicit failure policy
Choose fail-closed or fail-open behavior, with privacy-safe diagnostic categories in the EE file log.
Before you install
Requirements
The add-on connects supported frontend forms to the CleanTalk Anti-Spam service. Each website needs its own Anti-Spam Access Key.
| Component | Requirement | Notes |
|---|---|---|
| ExpressionEngine | 7.2.0 or later | Use a release compatible with your PHP version. |
| PHP | 8.0 or later | The cURL and OpenSSL extensions are required. |
| CleanTalk | Anti-Spam website and Access Key | Do not use an account password, user token, or Security service key. |
| Runtime package | Bundled in release ZIP | Composer is not required on the EE server when installing an official release ZIP. |
| Freeform | 3.0.0 or later | This is the only certified Freeform version in the current release record. |
Set up the add-on
Installation
- Download an official release ZIP and extract it. Release packages already include the production Composer dependencies.
- Copy the complete cleantalk directory into your ExpressionEngine installation:
system/user/addons/cleantalk/ - In the ExpressionEngine Control Panel, open Developer → Add-Ons and install CleanTalk Anti-Spam for EE.
- Add this website as a separate Anti-Spam website in your CleanTalk dashboard and copy its Anti-Spam Access Key.
- Open the add-on settings, enter the Access Key, review the protection settings, and save.
- Select Test connection. Then submit an approved and rejected test through each form type you intend to protect.
Updating an existing installation
Back up the database and add-on directory, replace the complete cleantalk directory—including vendor—then run the add-on update from Developer → Add-Ons. Do not uninstall before upgrading; the update preserves the per-site settings and encrypted Access Keys.
Upgrading to 1.0.0-rc.2 refreshes all hook versions and migrates existing fail-open settings to fail-closed once. Administrators may explicitly select fail-open again afterward.
Disable or uninstall
The master switch bypasses checks without deleting settings. Uninstall removes the CleanTalk settings table, module, and hooks. It does not delete comments, members, Channel entries, or Freeform data. The settings table covers all EE sites, so uninstall removes saved keys and settings for every site.
Connect CleanTalk
CleanTalk account and Access Key
A CleanTalk Anti-Spam account is required. Configure the Access Key for the specific CleanTalk website represented by this EE site. Keys saved in the Control Panel are encrypted with ExpressionEngine’s session_crypt_key and stored per site.
For configuration-managed environments, the database key can be overridden:
$config['cleantalk_access_key'] = getenv('CLEANTALK_API_KEY'); Lookup priority is: ExpressionEngine configuration, then the CLEANTALK_API_KEY process environment variable, then the encrypted database value. An environment override applies to every MSM site served by that PHP environment.
Keep the encryption key stable. Do not change EE’s session_crypt_key during an upgrade, or previously encrypted Access Keys cannot be decrypted.
Control Panel reference
Settings
Settings are stored independently for each ExpressionEngine site. A blank Access Key field keeps the existing encrypted key unless Remove saved key is enabled.
Anti-Spam Access Key
Website-specific key used to authenticate CleanTalk requests. A configuration or environment override cannot be changed from the Control Panel.
Remove saved key
Deletes only the encrypted database value. It does not remove configuration or environment overrides.
Enable CleanTalk protection
Default: on
Master switch for all CleanTalk checks on the current EE site.
Enable Bot Detector
Default: on
Loads CleanTalk’s browser-side detector only on pages containing a protected form. Server-side classification continues if the script or token is unavailable.
API timeout
Default: 5 seconds
Maximum wait for CleanTalk. Available values are 3, 5, or 10 seconds.
If CleanTalk is unavailable
Default: reject
Reject submission is fail-closed and is the secure default. Allow submission and log the error is fail-open.
Protect comments
Default: on
Checks native ExpressionEngine comment submissions.
Protect member registrations
Default: on
Checks native frontend member registrations.
Protect Contact and Tell-a-Friend forms
Default: on
Checks only frontend forms submitted through ExpressionEngine’s native Email module.
Protect Channel Forms
Default: on
Checks new frontend Channel Form entries. Existing-entry edits are deliberately skipped.
Protect Solspace Freeform forms
Default: on
Checks supported frontend Freeform 3 submissions before storage and notification delivery.
Protect logged-in members
Default: off
When off, authenticated members bypass checks. Super Admins always bypass checks.
Submission flow
How protection works
Supported form hook
Relevant fields normalized
CleanTalk API check
Verdict and site policy
Normal processing or native error
When a visitor submits a protected form, the add-on confirms the master and form-specific settings, applies member bypass rules, extracts only the relevant fields, and sends a classification request over verified HTTPS. Registrations use CleanTalk’s new-user check; the other supported submissions use its message check.
An approved submission continues through the normal ExpressionEngine or Freeform workflow. A suspected-spam verdict is replaced with a fixed local message and rejected through the form’s native validation boundary before the supported content is saved or email is delivered.
If the API cannot provide a reliable verdict, the configured failure policy applies. Fail-closed rejects with a service-unavailable message; fail-open allows processing and records a privacy-safe diagnostic.
Bot Detector and CSP
When enabled, the add-on marks rendered protected forms and loads the detector once per page from:
https://fd.cleantalk.org/ct-bot-detector-wrapper.js A Content Security Policy must allow scripts from https://fd.cleantalk.org. A missing or blocked event token does not disable the server-side check and does not cause a local rejection by itself.
Exact support scope
Supported forms and features
| Form | Status | Rejection behavior |
|---|---|---|
| Native comments | Supported | EE standalone form error; comment is not saved. |
| Frontend member registration | Supported | Error is associated with the email field; no member is created. Non-sensitive values are restored, but passwords are not. |
| Email Contact | Supported | EE standalone form error; email is not delivered. |
| Email Tell-a-Friend | Supported | EE standalone form error; email is not delivered. |
| New Channel Form entry | Supported | Channel Form validation error; entry is not saved. |
| Existing Channel Form entry edit | Bypassed | Normal edit workflow; no CleanTalk request. |
| Solspace Freeform 3.0+ | Certified version | HTML/AJAX form-level error; no submission or notifications. Multi-page forms are checked on the final page with stored earlier values. |
Not universal POST protection: login, search, Control Panel submissions, webhooks, unrelated system email, other Freeform versions, and other third-party form add-ons are outside the current support scope.
Freeform notes and limitations
- Use Freeform’s normal rendering tags and ensure custom templates display form-level errors with form:errors. AJAX clients receive the error in formErrors.
- Back navigation and Control Panel edits are skipped. Classification runs on the posted final page.
- Freeform can stage uploaded files during its own validation. A CleanTalk rejection prevents submission storage, notifications, CRM, and mailing-list delivery, but not temporary upload staging.
- Custom AJAX navigation clients and token-bearing browser AJAX still need validation. A final page with no fields combined with simulated spam success is not certified.
Verify your setup
Testing
- Save the settings and select Test connection.
- Test while logged out unless you have enabled protection for logged-in members. Super Admins always bypass checks.
- Use only the rejection test address published in the official CleanTalk Anti-Spam FAQ. Do not invent or reuse account credentials as test data.
- Submit one expected approval and one expected rejection through every enabled form type.
- Confirm rejected comments, registrations, entries, Freeform submissions, and emails were not saved or delivered, as applicable. Review the CleanTalk dashboard for the classifications.
Use a development CleanTalk website and Access Key where possible so test requests do not pollute production history. For Freeform multi-page forms, confirm intermediate pages produce no classification and the final page produces one.
Data boundary
Privacy and data handling
For protected submissions, the PHP integration sends the sender IP, email and name when present, relevant message content, sanitized page URL and referrer, user agent, and the Bot Detector event token when present. Page URLs and referrers are stripped of credentials, query strings, and fragments.
Channel Form includes the title and configured text, textarea, rich text, email, and URL fields. Freeform includes configured text, textarea, email, and website fields; resolved values from earlier pages are included in the final multi-page check.
Passwords, uploaded file contents, authorization headers, cookies, EE CSRF/security data, encrypted form metadata, recipient/choice fields, unknown fields, sensitive field handles, and unrelated POST fields are excluded. The Access Key is used only as API authentication and is not included as form content or written to local logs.
Operator responsibility: update your privacy notice and any consent or international-transfer documentation that applies to your use of CleanTalk. The optional Bot Detector is a separately downloaded CleanTalk browser script; its browser data collection is governed by CleanTalk, not by the PHP field allowlist.
Common checks
Troubleshooting
The connection test fails
Confirm that the value is this website’s Anti-Spam Access Key—not a CleanTalk password, user token, or Security service key. Verify that PHP can resolve and reach api.cleantalk.org and moderate.cleantalk.org over HTTPS, and that cURL, OpenSSL, the bundled autoloader, and the CleanTalk SDK are available.
No request appears in the CleanTalk dashboard
Check the master switch, the specific form switch, the active EE site’s key, and member bypass rules. Confirm the template uses a supported native form or certified Freeform integration. Channel Form edits are intentionally not checked.
Bot Detector is absent
The script is added only when a supported form is rendered and protection, that form type, Bot Detector, and an Access Key are all active for a non-bypassed visitor. Check CSP rules and the rendered cleantalk-protected marker. Server-side checks remain active without the script.
Enable privacy-safe file logs
On EE 7, diagnostics are file logs rather than entries in the Control Panel Developer Log. Enable an EE log threshold of at least 1 and ensure system/user/logs is writable:
$config['log_threshold'] = 1; Files are written under system/user/logs/log-YYYY-MM-DD.php. Entries include a reason category, form type, configured policy and timeout, plus HTTP status/duration or API error number when available. They omit submission bodies, email addresses, Access Keys, request IDs, and raw remote error text.
The SDK or autoloader is missing
Reinstall the complete official release archive, which includes vendor/autoload.php and the CleanTalk SDK. A Git source checkout requires composer install; production sites should use a built release package.
Frequently asked questions
FAQ
Is a CleanTalk account required?
Yes. Add the EE website as an Anti-Spam website in CleanTalk and configure that website’s Anti-Spam Access Key.
Does the add-on add a CAPTCHA?
No CAPTCHA challenge is added by this implementation. Classification runs server-side. The optional Bot Detector supplies a browser event token without adding a visitor challenge.
Which forms are protected?
Native EE comments, frontend member registrations, Email Contact and Tell-a-Friend forms, new Channel Form entries, and certified Solspace Freeform 3.3.10 frontend submissions. Other form systems are not supported by the current hooks.
Are logged-in members checked?
Not by default. You can enable protection for authenticated members. Super Admins always bypass classification.
What information is sent to CleanTalk?
The PHP integration sends the sender IP, available email/name, allowlisted relevant content, sanitized page/referrer URLs, user agent, and optional detector token. Passwords, files, security fields, cookies, and arbitrary POST data are excluded.
What happens if CleanTalk cannot be reached?
The site’s failure policy applies. The default fail-closed policy rejects with a local service-unavailable message. Fail-open allows the submission. Both paths write a privacy-safe diagnostic when EE file logging is enabled.
Can the Access Key live outside the database?
Yes. Set cleantalk_access_key in EE configuration or use the CLEANTALK_API_KEY PHP environment variable. Configuration takes precedence.
Release history
Changelog
1.1.0
18 September 2026
- Kept the bundled
cleantalk/php-antispamSDK at 4.4.1 under GPL-3.0, with its notices intact; customers must use their own CleanTalk account and Access Key. - Documented the GNU LGPL version 3 election for the SDK’s getID3-derived
utf8_decode()fallback, retaining its attribution and corresponding source. - No runtime behavior changes from v1.0.1; only version and licence metadata changed.
1.0.1
16 September 2026
- Established the cleaned public source repository.
- Removed internal release-candidate verification material from public packages.
- No runtime behavior changes from v1.0.0.
1.0.0
16 September 2026
- Initial public release.
- Added CleanTalk protection for supported ExpressionEngine core forms.
- Added support for Solspace Freeform standard, AJAX and multipage forms.
- Bundled the official CleanTalk PHP SDK and production dependencies.
- Added configurable fail-open and fail-closed API failure handling.
Support
Tell us what is happening
Need help with CleanTalk Anti-Spam for ExpressionEngine? Send us the details below. Version information and clear reproduction steps help us investigate more quickly.
Do not include passwords, API keys, CleanTalk Access Keys, personal customer data, or other sensitive credentials in your support request or attachment.
ExpressionEngine® is a registered trademark of Packet Tide, LLC. CleanTalk and related marks are trademarks of their respective owners. CleanTalk Anti-Spam for EE is independently developed and maintained by Yukon Cloud; Yukon Cloud is not affiliated with or endorsed by Packet Tide, LLC or CleanTalk.