« Best CSS .Classes for CSS Toolbox301 Redirect Cheatsheet »
Simple PHP Anti-Spam Captcha Script
November 28th, 2007
One of the best, if not the best, ways to prevent automated web robot tools and spammers from taking advantage of your forms and scripts is by using a captcha image. Here is a simple example that I hacked up earlier today to use on my Advanced Request and Response HTTP Header Viewer among other tools.
View a working example on my Advanced Request and Response HTTP Header Viewer tool.
PHP Anti-Spam Captcha Example
Save this on your site as capya.php and include in your php script with require_once 'capya.php', then run with askapache_captcha(); which outputs XHTML of the captcha image.
<?php
session_start();
define('CAPYAINC','/home/user/askapache.com/includes/capya/'); // the directory where the fonts and bg image are stored
define('CAPYAURI','http://static.askapache.com/i/'); // the web uri where the captcha image will be located
define('CAPYADIR','/home/user/static.askapache.com/public_html/i/'); the directory where the captcha image will be stored
function askapache_captcha($type=1,$numletters=4,$fontsize=22){
$capya_string=capya_string($numletters); // the letters and numbers displayed on captcha
$capya_bgfile=CAPYAINC.'n.png'; // the background image for the captcha
$capya_filename='askapache-'.rand(1111,999999).'.jpg'; // the filename of finished captcha
$capya_file=CAPYADIR.$capya_filename; // the full path to finished captcha
$capya_uri=CAPYAURI.$capya_filename; // the public web address to finished captcha
$rgb[0]=array(204,0,0);
$rgb[1]=array(34,136,0);
$rgb[2]=array(51,102,204);
$rgb[3]=array(141,214,210);
$rgb[4]=array(214,141,205);
$rgb[5]=array(100,138,204);
// create image from background image
$image=imagecreatefrompng($capya_bgfile);
// store the md5 of the captcha string
$_SESSION['askapache_captcha'] = md5($capya_string);
// add chars to captcha image
$g=$fontsize;
for($i=0; $i<$numletters; $i++){
$L[]=substr($capya_string,$i,1); // each char from string into individual variable
$A[]=rand(-20, 20); // random angle for each char
$F[]=CAPYAINC.rand(1, 10).".ttf"; // random font for each char
$C[]=rand(0, 5); // random color for each char
$T[]=imagecolorallocate($image,$rgb[$C[$i]][0],$rgb[$C[$i]][1],$rgb[$C[$i]][2]); // allocate colors for chars
imagettftext($image, $fontsize, $A[$i], $g, $fontsize+15, $T[$i], $F[$i], $L[$i]); // write chars to image
$g+=$fontsize+10;
}
// save jpeg image to public web folder
imagejpeg($image, $capya_file);
if($type===1){
// output the image url
echo '<p><label for="capya" class="S"><input id="capya" name="capya" type="text" value="" size="5" class="S" style="width:150px" maxlength="5" /></label></p>';
} else echo '';
// destroy image
imagedestroy($image);
// delete all captcha images at 12 and 3 oclock if more than 100 are found
$dt=date('g');
if(($dt==12)||($dt=='12'))capya_cleanup();
else if(($dt==3)||($dt=='3'))capya_cleanup();
}
function capya_cleanup(){
$files=glob(CAPYADIR."apache*.jpg");
if(sizeof($files)>100){
foreach ($files as $filename) {
unlink($filename);
//echo "$filename size " . filesize($filename) . "\n";
}
}
}
function capya_string($len){
$str='';
for($i=1; $i<=$len; $i++) {
$ord=rand(48, 90);
if((($ord >= 48) && ($ord <= 57)) || (($ord >= 65) && ($ord<= 90))) $str.=chr($ord);
else $str.=capya_string(1);
}
return $str;
}
?>
Verify Captcha
To verify a user-submitted (via POST or GET) value for the captcha image, do this.
<?php
if(md5($_REQUEST['capya'])===$_SESSION['askapache_captcha']){
echo 'verified, continue processing script';
}else{
echo 'incorrect, stop processing script';
}
?>
Get the Anti-Spam Captcha Code
Please Comment!
Reader Comments
-
It outputs an "input" field instead of the captcha image! Does anyone know what's wrong?
-
Nice script :)
-
Great read! but for those who don't have GdLibs installed, you can use ImageMagick.
-
A very nice piece of code and a very helpful addition to feedback boxes, but I found one problem. You open the feedback site, and unless you hit CTRL+R, capya does not register the first input you put, just claims that the code was wrong. You have to return, refresh site with a new code and try again.
-
Thanks a lot! This is the best capcha code I could find in the net!
Good work! -
is there anyway you can outline the steps in layman's terms? especially this: Save this on your site as capya.php and include in your php script with require_once 'capya.php', then run with askapache_captcha(); which outputs XHTML of the captcha image.
thanks!
-
quite difficult for me. (I'm newbie for php) but I will try to do it :)
-
Hi Love the captcha script.
Im having a problem with it and maybe you can help me out im getting a timezone error with the
date();functionReporting:
Strict Standards: date() [function.date]: It is not safe to rely on the system's timezone settings. Please use the date.timezone setting, the TZ environment variable or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected 'Europe/London' for '0.0/no DST' instead in C:\AppServ\www\IrishModels\capya\capya.php on line 50
Can you please advise,
Again Many Thanks.
-
Perfect, thanks!
-
Great piece of php anti-spam captcha code. Very elegant - thanks for sharing!
-
sorry, my mistake. Just check the Directories defined if the path is correct. Anyway you can also check this one
link> gscripts.net/free-php-scripts/Anti_Spam_Scripts/Image_Validator/details.html -
Hi Steve, Remove the semicolon in this line
imagettftext($image, $fontsize, $A[$i], $g, $fontsize+15, $T[$i], $F[$i], $L[$i]);
-
Hi there,
Was just cruising around to compare anti-spam form techniques and found your post. I like your solution - I imagine it's very tight!
I decided to go with siding with the humans, however - I'm tired of squinting at twisted numbers and letters every time I want to submit a form, so I went with a simple 'pick the unique picture' system, and my web development clients say it's dramatically reduced the volume of spam, while gaining some pleasant comments from their customers on how easy it is to use!
If anyone wants to know more, they can head over to my blog to read about my anti-spam human-checker php script
Keep up the good work
Spiral Out!
David -
OK, I spoke too soon. I see on 31 Where the face's are called. It looks right though. I'll keep looking around. Thanks.
-
Hey there, I appreciate the example and code you have going. I am having a hard time finding where the code actualy pulls in the .ttf files. I'm getting errors like:
Warning: imagettftext() [function.imagettftext]: Could not find/open font in /home/designb/public_html/php/capya.php on line 34I am sorry if this is a dumb question...but any help would be awesome!! Thanks.
First problem, I have more than 18000 images generated with this script in my folder "captcha" since 2009. (the picture's name looks like : apache-1141.jpg)
Secondly, it occurs that the picture isn't generated, the href image has a value (ex: apache-1111.jpg) but there is no picture in the folder with this name...