Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
153 changes: 67 additions & 86 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,134 +1,115 @@
# CleanTalk php-antispam: Lightweight Spam Protection for PHP Apps
============

![example workflow](https://github.com/CleanTalk/php-antispam/actions/workflows/tests.yml/badge.svg)

[![Latest Stable Version](https://poser.pugx.org/cleantalk/php-antispam/v)](https://packagist.org/packages/cleantalk/php-antispam)

## Invisible spam protection: no CAPTCHA, puzzles, or math tests

_A PHP client for the CleanTalk anti-spam API. Spam protection and a CAPTCHA-free alternative to reCAPTCHA, powered by background scoring that doesn’t interrupt website visitors._

If you find this project useful, please consider starring it on GitHub ⭐. It helps us improve and maintain the project.
## The Invisible protection from spam, no captcha, no recaptcha, no puzzles, no math captcha.
_API for antispam service cleantalk.org_

#### Requirements
* PHP 5.6 and above
* CURL support

* PHP 5.6 or later
* cURL support

### How does it stop spam?
### How we stop spam?
PHP Anti-Spam library providing invisible spam protection for your websites, registration forms, and comment sections. CleanTalk API offers an effective CAPTCHA alternative that silently blocks spam without interrupting your users' experience.

This PHP library provides invisible spam protection for websites, registration forms, and comment sections. The CleanTalk API is a CAPTCHA alternative that detects spam without interrupting your users.
When users submit forms on your website form, the form data is securely sent to CleanTalk’s cloud servers. CleanTalk analyzes submissions using advanced heuristics. CleanTalk then returns a real-time verdict— legitimate requests or spam.

When a user submits a form, the library securely sends the form data to CleanTalk's cloud servers for analysis. CleanTalk then returns a real-time verdict identifying the submission as legitimate or spam. Your application decides how to handle that verdict.
You are free to do anything with spam, or just allow as to block spam (we will interrupt desirable request).

## CleanTalk vs CAPTCHA
| Feature | CleanTalk Anti-Spam | Traditional CAPTCHA |
|---------------------|-----------------------------------|------------------------------------------|
| User Interaction | 100% invisible to users | Requires solving puzzles or clicks |
| Form Compatibility | Works with any PHP form | Often requires additional scripts |
| Speed | Instant cloud check | Slower due to user interaction |
| Accessibility | No visual tests | Can be difficult for screen-reader users |
| Feature | CleanTalk Anti-Spam | Traditional CAPTCHA |
|---------------------|-----------------------------------|--------------------------------------|
| User Interaction | 100% invisible to users | Requires solving puzzles or clicks |
| Form Compatibility | Works with any PHP form | Often requires additional scripts |
| Speed | Instant cloud check | Slower due to user interaction |
| Accessibility | Fully accessible, no visual tests | Often inaccessible to screen readers |

> CleanTalk is a **PHP spam filter** and **CAPTCHA-free alternative** that protects your forms without adding friction for users.
> CleanTalk is a **PHP spam filter** and a **captcha-free alternative** that boosts UX and protects your forms with zero friction.

## Getting started
## Interesting? Let's make some settings (it will take few minutes)

Setup takes only a few minutes.

### Step 1: install the SDK

Install the SDK with Composer:
## 1. Installation

```bash
composer require cleantalk/php-antispam
```

Alternatively, download the ZIP archive and extract it into your project directory.

### Step 2: configure your API key
Without Composer: extract the library archive and include `require_once '/path/to/php-antispam/cleantalk-antispam.php';`.

First, copy your API key from your [CleanTalk dashboard](https://cleantalk.org/my/).
## 2. Constants

Make it available to PHP as an environment variable:
Define them in a shared settings file that is loaded **both on the form page and in the form handler**: the JavaScript check hash must match in both places. Defining `CLEANTALK_ACCOUNT_EMAIL` and `CLEANTALK_SALT` enables offline protection: when the cloud is unavailable, visitors without the JavaScript check cookie are blocked. Without these constants, requests are allowed while the cloud is unavailable, as in previous versions.

| Name | Value |
|---|---|
| `CLEANTALK_API_KEY` | Your CleanTalk API key |

On managed hosting, add it in the **Environment variables** or **Secrets** section of your hosting control panel, then restart the application if required.

If your application already loads a `.env` file, add:

```dotenv
CLEANTALK_API_KEY=your-api-key
```php
define('CLEANTALK_ACCOUNT_EMAIL', 'you@example.com'); // required: CleanTalk account email
define('CLEANTALK_SALT', 'f3c9a1e07b2d4c8e9a6b5d0f1e2c3a4b'); // required: secret string, at least 32 characters
// define('CLEANTALK_JS_URL', '/cleantalk'); // if the library is outside the web root (see step 4)
// define('CLEANTALK_MODERATE_TIMEOUT', 2); // cloud timeout, seconds (default 2 sec, applied only with offline protection)
// define('CLEANTALK_OFFLINE_MODE', true); // testing only: never contact the cloud
```

PHP does not load `.env` files by itself; this option works only when your application or framework includes a dotenv loader. Do not put the API key in your PHP files or commit it to source control.

### Step 3: add the CleanTalk handler to your form handler
## 3. Form page

Add the handler to your PHP code:
Print the library scripts before the form or in `<head>`. Use the same access key as in the form handler.

```php linenums="1"
$api_key = getenv('CLEANTALK_API_KEY');
if (empty($api_key)) {
throw new RuntimeException('CLEANTALK_API_KEY is not configured');
}

$email = $_POST['email']; // Get this value from your form.
$cleantalk_antispam = (new CleantalkAntispam($api_key))
->setEmail($email);
// Set additional parameters here.
$api_result = $cleantalk_antispam->handle();
```php
<?php echo \CleanTalk\CleantalkAntispam::getFrontendHTMLCode($apikey); ?>
<form method="post" action="/contact-handler.php">
<input name="name">
<input name="email" type="email">
<textarea name="message"></textarea>
<button type="submit">Send</button>
</form>
```

See [additional configuration options](readme_additional.md) to select the form type and provide the sender name, message, IP address, and Bot Detector settings.

### Step 4: add the JavaScript library to your HTML template
## 4. Making the JS file reachable

The library collects frontend data used for bot detection.
The browser must load `js/ct-js-check.js` from the library directory. If the directory is inside the web root, nothing needs to be done. If it is outside, choose one option.

```html
<script src="https://fd.cleantalk.org/ct-bot-detector-wrapper.js" defer></script>
```

Enable the event token in your PHP handler:
**Option A (recommended): serve the file with your own handler** at `/cleantalk/ct-js-check.js`. This way the file always matches the installed library version.

```php linenums="3"
...
// Set additional parameters here.
$cleantalk_antispam->setEventTokenEnabled(1);
...
```php
header('Content-Type: application/javascript');
readfile('/path/to/php-antispam/js/ct-js-check.js');
```

### Step 5: handle the API verdict

For example, stop processing when CleanTalk identifies a submission as spam:

```php
if ($api_result && $api_result->allow === 0) {
die('Blocked. Spam protection OK. Reason: ' . $api_result->comment);
// Or add your own actions, logs, or messages.
}
define('CLEANTALK_JS_URL', '/cleantalk');
```

### Step 6 (optional): troubleshoot the integration
**Option B: copy the file** into a public directory, for example `/assets/cleantalk/`, and set `define('CLEANTALK_JS_URL', '/assets/cleantalk');`. Copy the file again after every library update.

To identify possible configuration problems, log the improvement suggestions after calling `handle()`:
## 5. Form handler

Check the data **before** saving it or sending an email:

```php
// Troubleshooting: log improvement suggestions.
error_log($cleantalk_antispam->whatsWrong(true));
use CleanTalk\CleantalkAntispam;

$cleantalk = new CleantalkAntispam($apikey, $_POST['email']);
$result = $cleantalk
->setEventTokenEnabled(1) // required: Bot Detector is included via getFrontendHTMLCode()
->setNickName($_POST['name']) // user name, if available
->setMessage($_POST['message']) // message text, if available
->useContactFormCheck() // for registration forms: ->useRegistrationCheck()
->handle();

if (!$result->allow) {
// Blocked: do not save the data, show $result->comment
}
```

The diagnostic output can contain personal data. Use this logging only while troubleshooting and store it in appropriately protected logs.

See the [complete form-handler example](https://github.com/CleanTalk/php-antispam/blob/dev/examples/form_with_handler/form_with_handler.php) for context.
`$result->offline` is `true` when the decision was made without the cloud.

### Step 7 (optional): get help
## 6. Testing

If you have questions, open a GitHub issue or contact us through our ticket system.
1. Open the form page. In DevTools, make sure `ct-js-check.js` loads with status 200 and the `ct_js_check` cookie is set.
2. Temporarily add `define('CLEANTALK_OFFLINE_MODE', true);`.
- With JavaScript enabled, the form must be **submitted**.
- With JavaScript disabled and the cookie deleted, the form must be **blocked**.
3. Remove `CLEANTALK_OFFLINE_MODE`.

## Examples

Expand Down
34 changes: 18 additions & 16 deletions examples/form_with_handler/form_with_handler.php
Original file line number Diff line number Diff line change
@@ -1,8 +1,19 @@
<?php
require_once '../../../php-antispam/cleantalk-antispam.php';
require_once __DIR__ . '/../../cleantalk-antispam.php';

use CleanTalk\CleantalkAntispam;

// CLEANTALK ANTISPAM SETTINGS: must be the same on the form page and in the form handler
define('CLEANTALK_ACCOUNT_EMAIL', 'you@example.com'); // required: CleanTalk account email
define('CLEANTALK_SALT', 'replace-with-a-random-string-32-chars'); // required: secret string, at least 32 characters
// define('CLEANTALK_JS_URL', '/cleantalk'); // if the library is outside the web root

$api_key = getenv('CLEANTALK_API_KEY');
if (empty($api_key)) {
throw new RuntimeException('CLEANTALK_API_KEY is not configured');
}
// END OF CLEANTALK ANTISPAM SETTINGS

?>
<!DOCTYPE html>
<html lang="en">
Expand Down Expand Up @@ -61,8 +72,8 @@
}
</style>

<!-- CLEANTALK ANTISPAM -->
<script src="https://fd.cleantalk.org/ct-bot-detector-wrapper.js" defer></script>
<!-- CLEANTALK ANTISPAM: Bot Detector and the JavaScript check for offline protection -->
<?php echo CleantalkAntispam::getFrontendHTMLCode($api_key); ?>
<!-- END OF CLEANTALK ANTISPAM -->
</head>
<body>
Expand All @@ -87,26 +98,17 @@
$messageType = 'error';
}

if ($messageType !== 'error' && !filter_var($email, FILTER_VALIDATE_EMAIL)) {
$statusMessage = 'Please enter a valid email address.';
$messageType = 'error';
}

// HANDLE CLEANTALK ANTISPAM
if ($messageType !== 'error') {
$api_key = getenv('CLEANTALK_API_KEY');
if (empty($api_key)) {
throw new RuntimeException('CLEANTALK_API_KEY is not configured');
}

$cleantalk_antispam = (new CleantalkAntispam($api_key))
->useContactFormCheck()
->setEventTokenEnabled(1) // required: Bot Detector is included via getFrontendHTMLCode()
->setEmail($email)
->setNickName($name)
->setMessage($message)
->setEventTokenEnabled(1);
->setMessage($message);
$api_result = $cleantalk_antispam->handle();
if ($api_result->allow === 0) {
// $api_result->offline is true when the cloud was unavailable and the JavaScript check decided
if (!$api_result->allow) {
$statusMessage = 'Spam detected - ' . $api_result->comment;
$messageType = 'error';
}
Expand Down
30 changes: 30 additions & 0 deletions js/ct-js-check.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**
* CleanTalk offline JavaScript check.
*
* Copies the server generated hash from the data-ct-js-key attribute into a cookie.
* The backend compares the cookie with the same hash when the moderate server is unreachable:
* a matching value proves that JavaScript is executed in the visitor browser.
*/
(function () {
'use strict';

var self = document.currentScript || (function () {
var scripts = document.getElementsByTagName('script');
return scripts[scripts.length - 1];
})();

if (!self) {
return;
}

var key = self.getAttribute('data-ct-js-key');

// Reject anything but a sha256 hex digest to keep arbitrary data out of the cookie header
if (!key || !/^[a-f0-9]{64}$/.test(key)) {
return;
}

var secure = location.protocol === 'https:' ? '; secure' : '';

document.cookie = 'ct_js_check=' + key + '; path=/; max-age=86400; samesite=lax' + secure;
})();
Loading
Loading