Simple Captcha using PHP with GD library

Captcha can come in handy when fighting against spam and bot attacks. It generates random images and asks the user to re-enter the characters it sees in order to verify whether user is a human or not. We will develop a simple captcha script in PHP by using GD library. The only requirement is that you should have the GD library installed. It gives you the ability to create and manipulate image files in different formats in PHP.

The first thing we need to do is that search for a TrueType font on the internet. There are several sites which give TrueType fonts for free. Download a font of your choice from such a website. The TrueType font file will have .ttf as its extension. Place this file in the same folder in which you will place your PHP script. In this example we will use Turn Tablz font.

Turn Tablz font

Now create a new file named captcha.php and add the following code in it -

<?php

session_start();

/*Create a 220x35 image*/
$im = imagecreatetruecolor(220, 35);

/*Color code for orange*/
$orange = imagecolorallocate($im, 0xFF, 0x8c, 0x00);

/*Color code for white*/
$white = imagecolorallocate($im, 0xFF, 0xFF, 0xFF);

/*Generate a random string using md5*/
$md5_hash = md5(rand(0,999));

/*Trim the string down to 6 characters*/
$captcha_code = substr($md5_hash, 15, 6);

/*Store the value of the generated captcha code in session*/
$_SESSION['captcha'] = $captcha_code;

/* Set the background as orange */
imagefilledrectangle($im, 0, 0, 220, 35, $orange);

/*Path where TTF font file is present*/
$font_file = './TURNBB__.TTF';

/* Draw our randomly generated code*/
imagefttext($im, 30, 0, 5, 30, $white, $font_file, $captcha_code);

/* Output the image to the browser*/
header('Content-Type: image/png');
imagepng($im);

/*Destroy*/
imagedestroy($im);
?>

Here we first create a new image of the specified size - 200x35 by using imagecreatetruecolor(). Next we use imagecolorallocate() function to create resource identifiers for the colors we need i.e. orange and white. We generate a random string by using md5() function and then trim it to a string having 6 characters. We also store this string/code in a PHP session variable so that it can be accessed later on for verification. After this we create a rectangle and fill it with orange color by using imagefilledrectangle(). Then we write our code over this rectangle by using imagefttext(). Finally we send the image to the browser by setting the appropriate header and using imagepng() function.

We can now use this script in evaluating any form. Create another file named form.php and add the following code to it.

<?php session_start(); ?>

<form method="post" action="">
 <b>CAPTCHA check</b> (six letter code):<br /><br />
   <img src="captcha.php" alt="captcha image"><br />
   <input type="text" name="captcha" size="20" maxlength="6">
 <input type="submit" value="Submit">
</form>

<?php

/*if captcha code is posted*/
if(isset($_POST["captcha"]))
 if($_SESSION["captcha"]==strtolower($_POST["captcha"]))
 {
  /*CAPTCHA is valid. You can process the form now.*/
  echo 'CAPTCHA is valid. You can process the form now.';
 }
 else
 {    
  /*Invalid CAPTCHA*/
  echo 'Invalid CAPTCHA. Try again!';
 }
?>

As you see we have given the source of captcha image as captcha.php. When a user accesses this form, automatically a random captcha image is generated and displayed. Also the corresponding code has been stored in the session variable $_SESSION['captcha']. When the re-enters the code and submits it we can check the entered value of the code against the stored session value and then process the form only if both match. Check out the working demo of the code below -

//Input the IDs of the IFRAMES you wish to dynamically resize to match its content height: //Separate each ID with a comma. Examples: ["myframe1", "myframe2"] or ["myframe"] or [] for none: var iframeids=["FRAME1"] //Should script hide iframe from browsers that don't support this script (non IE5+/NS6+ browsers. Recommended): var iframehide="no" var getFFVersion=navigator.userAgent.substring(navigator.userAgent.indexOf("Firefox")).split("/")[1] var FFextraHeight=parseFloat(getFFVersion)>=0.1? 3 : 0 //extra height in px to add to iframe in FireFox 1.0+ browsers function resizeCaller() { var dyniframe=new Array() for (i=0; i<iframeids.length; i++){ if (document.getElementById) resizeIframe(iframeids) //reveal iframe for lower end browsers? (see var above): if ((document.all || document.getElementById) && iframehide=="no"){ var tempobj=document.all? document.all[iframeids] : document.getElementById(iframeids) tempobj.style.display="block" } } } function resizeIframe(frameid){ var currentfr=document.getElementById(frameid) if (currentfr && !window.opera){ currentfr.style.display="block" if (currentfr.contentDocument && currentfr.contentDocument.body.offsetHeight) //ns6 syntax currentfr.height = currentfr.contentDocument.body.offsetHeight+FFextraHeight+30; else if (currentfr.Document && currentfr.Document.body.scrollHeight) //ie5+ syntax currentfr.height = currentfr.Document.body.scrollHeight; if (currentfr.addEventListener) currentfr.addEventListener("load", readjustIframe, false) else if (currentfr.attachEvent){ currentfr.detachEvent("onload", readjustIframe) // Bug fix line currentfr.attachEvent("onload", readjustIframe) } } } function readjustIframe(loadevt) { var crossevt=(window.event)? event : loadevt var iframeroot=(crossevt.currentTarget)? crossevt.currentTarget : crossevt.srcElement if (iframeroot) resizeIframe(iframeroot.id); } function loadintoIframe(iframeid, url){ if (document.getElementById) document.getElementById(iframeid).src=url } if (window.addEventListener) window.addEventListener("load", resizeCaller, false) else if (window.attachEvent) window.attachEvent("onload", resizeCaller) else window.onload=resizeCaller