A defensive security PHP library that provides multiple layers of protection against form spam without requiring annoying CAPTCHAs. The library uses a combination of honeypot fields, submission timing analysis, RBL (Real-time Blackhole List) checks, and optional Redis-based rate limiting.
Include the library in your PHP project:
<?php
require_once("antispam/EasyAntiSpam.php");
use awehttam\AntiSpam\EasyAntiSpam;
?><?php
@session_start(); // Required for form timestamping
require_once("antispam/EasyAntiSpam.php");
use awehttam\AntiSpam\EasyAntiSpam;
$antiSpam = new EasyAntiSpam("contactForm");
?><form method="post">
    <?php $antiSpam->timestampForm(); ?>
    <!-- Your form fields -->
    <input type="text" name="name">
    <input type="email" name="email">
    
    <input type="text" name="phone" style="display:none">
    <button type="submit">Submit</button>
</form>if($_SERVER['REQUEST_METHOD'] == 'POST') {
    $score = $antiSpam->scoreSubmission($_POST, "phone");
    if($score) {
        // Spam detected - show generic error
        echo "An error occurred processing your request";
    } else {
        // Process legitimate submission
        // Send email, save to database, etc.
    }
}<?php
@session_start();
require_once("antispam/EasyAntiSpam.php");
use awehttam\AntiSpam\EasyAntiSpam;
// Create instance with unique form identifier
$antiSpam = new EasyAntiSpam("myForm");
// When rendering the form
$antiSpam->timestampForm();
// When processing submission
if($_SERVER['REQUEST_METHOD'] == 'POST') {
    // Check for spam (returns 0 if clean, positive number if spam detected)
    $score = $antiSpam->scoreSubmission($_POST, "honeypot_field");
    if($score) {
        $errors[] = "Sorry, we can't process your request";
    }
}
?>// Check multiple hidden fields at once
$score = $antiSpam->scoreSubmission($_POST, ["phone", "website", "company"]);// Enable debug logging
$antiSpam->setDebug(true);
// Use custom RBL servers
$antiSpam->setRBLServers([
    'zen.spamhaus.org',
    'bl.spamcop.net',
    'dnsbl.sorbs.net'
]);
// Use custom DNS server for RBL lookups
$antiSpam->setDNSServer("1.1.1.1:53");// Get detailed score without fast-check (checks all conditions)
$score = $antiSpam->scoreSubmission($_POST, "phone", false);
if($score == 0) {
    echo "Clean submission";
} else if($score == 1) {
    echo "One spam indicator detected";
} else {
    echo "Multiple spam indicators: " . $score;
}$fastcheck defaults to true, which returns immediately on the first spam indicator. Set to false to accumulate all spam scores.
    <?php
require_once("antispam/RedisRatelimiter.php");
use awehttam\AntiSpam\RedisRatelimiter;
// Connect to Redis
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
// Check rate limit: max 5 submissions per 10 minutes (600 seconds)
$exceeded = RedisRatelimiter::ratelimit(
    $redis,
    $_SERVER['REMOTE_ADDR'],
    600,  // time window in seconds
    5     // max hits in that window
);
if($exceeded) {
    die("Too many requests. Please try again later.");
}
?>// Custom callback when rate limit is exceeded
$callback = function($info) {
    error_log("Rate limit exceeded: " . $info['total_user_calls'] .
              " calls in " . $info['time_period'] . " seconds");
    // Could also:
    // - Send alert email
    // - Log to monitoring system
    // - Update abuse database
};
$exceeded = RedisRatelimiter::ratelimit(
    $redis,
    $_SERVER['REMOTE_ADDR'],
    600,
    5,
    $callback
);
if($exceeded) {
    header('HTTP/1.1 429 Too Many Requests');
    die("Rate limit exceeded");
}<?php
session_start();
require_once("antispam/EasyAntiSpam.php");
require_once("antispam/RedisRatelimiter.php");
use awehttam\AntiSpam\EasyAntiSpam;
use awehttam\AntiSpam\RedisRatelimiter;
$antiSpam = new EasyAntiSpam("contactForm");
if($_SERVER['REQUEST_METHOD'] == 'POST') {
    $errors = [];
    // First: Check rate limit
    $redis = new Redis();
    $redis->connect('127.0.0.1', 6379);
    if(RedisRatelimiter::ratelimit($redis, $_SERVER['REMOTE_ADDR'], 300, 3)) {
        $errors[] = "Too many requests. Please wait before trying again.";
    }
    // Second: Check spam indicators
    $score = $antiSpam->scoreSubmission($_POST, "phone");
    if($score) {
        $errors[] = "Your submission could not be processed.";
    }
    if(empty($errors)) {
        // Process legitimate submission
        mail($to, $subject, $message);
        echo "Thank you! Your message has been sent.";
    } else {
        foreach($errors as $error) {
            echo $error . "<br>";
        }
    }
}
?>| Method | Parameters | Description | 
|---|---|---|
| __construct() | string $formName | Creates instance with unique form identifier | 
| timestampForm() | None | Records current time in session for this form | 
| scoreSubmission() | array $vars, string|array $hiddenFields, bool $fastcheck | Checks submission for spam indicators. Returns spam score. | 
| setDebug() | bool $mode | Enables/disables debug logging | 
| setRBLServers() | array $servers | Sets custom list of RBL servers to query | 
| setDNSServer() | string $server | Sets custom DNS server (format: "host:port") | 
| Method | Parameters | Description | 
|---|---|---|
| ratelimit() | Redis $redis, string $ip, int $expires, int $max_hits, callable $callback | Checks if IP has exceeded rate limit. Returns true if exceeded. | 
The RBLChecker is automatically used by EasyAntiSpam but can also be used independently:
<?php
require_once("antispam/RBLChecker.php");
use awehttam\AntiSpam\RBLChecker;
$checker = new RBLChecker();
$checker->dnsServer = "8.8.8.8:53";
$checker->overallTimeoutMS = 300;  // 300ms timeout
$checker->maxRandomServers = 10;   // Query up to 10 RBL servers
$checker->debug = true;
$hits = $checker->checkRBL($_SERVER['REMOTE_ADDR']);
if($hits) {
    echo "IP found on $hits blacklists";
}
?>See example.php for a complete working contact form with EasyAntiSpam integration. The example demonstrates:
<?php
session_start();
require_once("antispam/EasyAntiSpam.php");
use awehttam\AntiSpam\EasyAntiSpam;
$antiSpam = new EasyAntiSpam("exampleForm");
if($_SERVER['REQUEST_METHOD']=='POST'){
    $errors=[];
    // Validate form fields
    if(!$_POST['name']) {
        $errors[] = "Please include your name";
    }
    // Check for spam
    $score = $antiSpam->scoreSubmission($_POST, "phone");
    if($score){
        $errors[] = "An internal error occurred";  // Generic message
    }
    if(empty($errors)){
        // Process submission
        mail($to, $subject, $message);
        echo "Thank you! Your message has been sent.";
    }
}
?>
<form method="post">
    <?php $antiSpam->timestampForm(); ?>
    <input type="text" name="name" placeholder="Your Name">
    <input type="email" name="email" placeholder="Your Email">
    <!-- Hidden field (honeypot) - Bots will fill this field.  Note: You should not include this comment in your real form -->
    <input type="text" name="phone" style="display:none">
    <textarea name="message"></textarea>
    <button type="submit">Submit</button>
</form>Hidden form fields that legitimate users won't see or fill, but bots will. If populated, the submission is flagged as spam.
Forms are timestamped when rendered. If submission happens too quickly (default: <2,000 milliseconds / 2 seconds), it's likely automated.
The submitter's IP is checked against multiple Real-time Blackhole Lists using concurrent non-blocking UDP queries. This happens in ~250ms and queries up to 7 random RBL servers by default.
Using Redis, track submission frequency per IP address. If an IP exceeds the threshold (e.g., 5 submissions in 10 minutes), block further attempts.
Enable debug mode to see detailed logging in your PHP error log:
$antiSpam->setDebug(true);
// Now submissions will log:
// - ANTISPAM DEBUG: Post hidden field score: 0
// - ANTISPAM DEBUG: Post minimum typing time score: 0; typing time was 15 seconds
// - ANTISPAM DEBUG: Post RBL Check score 0PHP Forms Anti Spam - Defensive security library for web forms