Thomas Landauer Logo

Preventing Spam in Form Submissions without Using a CAPTCHA

Got a Spam Problem?

If you’re looking for a smart solution to prevent your forum/guestbook/web-application/whatever from getting flooded with junk entries, I think I can help you.

Foreword: Why You Shouldn’t Use a CAPTCHA

Example of a CAPTCHAA CAPTCHA is a method to fight spam robots, by requiring the user to enter a code which is displayed as a distorted image.

The bad news: CAPTCHAs are annoying to users.

The good news: You probably don’t need one. The method described here would require the spammer to sit down and adjust his scripts for your specific website. So, unless your site is an extremely attractive target for spammers, they probably won’t take that time.

The bottom line:
CAPTCHAs are needed only on very popular sites. Try less intrusive methods first.

Basics: Use CSS

Code

HTML:

<label>Leave this blank: <input type="text" class="noshow" name="leaveblank"></label><br>
<label>Do not change this: <input type="text" class="noshow" name="dontchange" value="http://" ></label>

CSS:

.noshow { display:none; }

PHP:

if ($_POST['leaveblank'] != '' or $_POST['dontchange'] != 'http://') {
   // display message that the form submission was rejected
}
else {
   // accept form submission
}

First Improvement: Use JavaScript

Code

HTML:

<input type="text" id="leaveblank" name="leaveblank">
<script type="text/javascript">
  document.getElementById('leaveblank').className = "noshow";
</script>

Second Improvement: Use Encoded JavaScript

Code

HTML:

<script type="text/javascript">
/* <![CDATA[ */
function hivelogic_enkoder(){var kode=
"kode=\")''(nioj.)(esrever.)''(tilps.edok=edok;\\\"kode=\\\"\\\\oked\\\\\\"+
"\\\\\"\\\\=document.write\\\\\\\\\\\"\\\\\\\\\\\\\\\\\\\\s(r<pc iytet\\\\"+
"\\\\\\\\\\\\p=\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\tx\\\\\\\\\\\"\\\\/eatajcvis"+
"tr\\\\\\\\\\\\\\\\p\\\\\\\\\\\\\\\\\\\\\\\\\\\"\\\\\\\\\\\\\\\\\\\\\\\\\\"+
"\\\\\\\\\\>\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\drcnmonu.eetEge"+
"teltmyndB'Ie(vlbaaekl)nc'a.slaseN=m\\\\\\\\\\\\\\\\  \\\\\\\\\\\\\\\\\\\\"+
"\\\\\\\\\\\\ns\\\\\\\\\\\"\\\\oo\\\\\\\\\\\\\\\\hw\\\\\\\\\\\\\\\\\\\\\\\\"+
"\\\\\\\\;r\\\\\\\\\\\"\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"+
"n/\\\\\\\\\\\\\\\\c<istr\\\\\\\\\\\\\\\\p>\\\\\\\\\\\"\\\\);;\\\\\\\\\\\""+
"\\\\=x''f;roi(0=i;(<okedl.netg-h)1i;=+)2x{=+okedc.ahAr(t+i)1k+do.ehcratAi("+
"})okedx=(+<iokedl.netg?hokedc.ahAr(tokedl.netg-h)1':)';\\\"\\\\;x='';for(i"+
"=0;i<(kode.length-1);i+=2){x+=kode.charAt(i+1)+kode.charAt(i)}kode=x+(i<ko"+
"de.length?kode.charAt(kode.length-1):'');\\\"=edok\";kode=kode.split('').r"+
"everse().join('')"
;var i,c,x;while(eval(kode));}hivelogic_enkoder();
/* ]]> */
</script>

Third Improvement: Use PHP

Code

PHP:

// You can use the date() function to change field names periodically:
// For daily changes, e.g. use:
$code = date('Yz'); // Don’t copy this 1:1 - adjust the date() parameters!
$html = "<input type='text' name='abc$code'>\n";
if (!isset($_POST["abc$code"]) {
   // reject form submission
}

Improvement of the Third Improvement

Code

PHP:

$code = date('Yz');
$codeYesterday = date('Yz', time()-86400); // 86400 seconds are 1 day
if (isset($_POST["abc$codeYesterday"])
   $code = $codeYesterday;
}

Fourth Improvement: Use a Database

Code

MySQL:

 CREATE TABLE `spam` (
 `ip` int(10) unsigned default NULL,
 `timestamp` timestamp NOT NULL,
  KEY `ip` (`ip`));

PHP:

$ip = $_SERVER['REMOTE_ADDR'];
// when you reject a form submission:
mysqli_query("INSERT INTO `spam` SET `ip`=INET_ATON('$ip');");
// whenever somebody opens the page:
mysqli_query("SELECT `timestamp` FROM `spam` WHERE ip=INET_ATON('$ip') ORDER BY `timestamp` DESC LIMIT 1;");
if (time() - $timestamp < 120) { // 2 minutes
   // display error message to try again in 2 minutes
}
else {
   // display HTML form
}

Links