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 not 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 for="leaveblank">Leave this blank</label>
 <input type="text" class="noshow" id="leaveblank" name="leaveblank" /><br />
<label for="dontchange">Do not change this</label>
 <input type="text" value="http://" class="noshow" id="dontchange" name="dontchange" />

CSS:

.noshow { display:none; }

PHP:

if ($_POST['leaveblank'] == '' && $_POST['dontchange'] == 'http://') {
 // 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, use e.g.:
$code = date('Yz'); // Don't copy this 1:1 - adjust the date parameters. (Y:year. z:day of the year)
$html = "<input type='text' id='abc$code' 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:
mysql_query("INSERT INTO `spam` SET `ip`=INET_ATON('$ip');");
// whenever somebody opens the page:
mysql_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: try again in 2 minutes
}
else {
 // display HTML form
}

Links

Gültiges XHTML 1.0 Strict Gültiges CSS 2.1 Entspricht den WAI Web Content Accessibility Guidelines 1.0 Level Double-A