Tutorial on creating image captcha in PHP using GD library

There are already a number of free captcha libraries available on web. But as a developer you might want to know (in case you don’t) how the captcha is actually generated. So in this small tutorial we will learn step by step how to generate a captcha image using PHP.

Captcha is a string of alphabets and/or numbers that is generated randomly. It is used in web forms to avoid spams and bots as bots are not able to read the characters in the captcha image. The random captcha string, when it is generated, is stored somewhere( usually in SESSION or in database). When the user submits the form, a check is made to see if the captcha character entered by the user and the stored value of captcha string match. If a match occurs, then it is assume that the user is a human and not a bot and the form is allowed to process further.

Now a days you may often find a maths captcha. Where you are asked to input the result of some small arithmetic permutation. Like 5 x _ = 20. So if you fill 4 in the input, since 5×4=20, then the form is validated. But for the sake of this tutorial we are going to concentrate only on image captcha.

For generating image captcha we need to generate an image containing our random string of characters. For this we are going to use the PHP’s GD library. In most of the cases this library is installed by default on your server. So we are not going to discuss on how to install it. The GD library provides numerous functions for generating images in various formats and outputing it to the browser.
We begin with imagecreatetruecolor

$im = imagecreatetruecolor('150', '50');

What the above code does is create an image resource of width 150px and height 50px. Note that $im contains an image resource and not the actual image. We now have to add components to this image like the background color and some strings.
We shall require three colors: first for the background, second for the captcha string and the third for the background noise pixels that shall make the captcha difficult to read for bots.
Before applying these colors to our image resource $im, we will have to first create these colors.

$bg = imagecolorallocate($im, 230, 80, 0); //background color blue
$fg = imagecolorallocate($im, 255, 255, 255);//foreground text color white
$ns = imagecolorallocate($im, 200, 200, 200);//noise color

The last three parameters for imagecolorallocate are the rgb value for the color. And the first parameter is the image resource.

So we have our colors ready, now we can start filling the image resource with the colors. First we will add the background color

imagefill($im, 0, 0, $bg);// second and third params are the x and y co-ordinate to start filling color

Now add some characters to image. For now we will add ‘captcha’ but this will be generated randomly in the final captcha code.

imagestring($im, 5, 10, 8,  'captcha', $fg);

imagestring will draw the string ‘captcha’ provided as the fifth param. Second param 5 is the code for the built in font. 10 & 8 are the upper left corner x and y co-ordinates to start filling the string from. First param is the image resource and the last one is the color for the image string.

We have added background color, we have added the captcha string. We are officially done. But still some bots out there are capable of reading images. So to defeat them we will add some noise to the image so that it can be read by humans but not by the bots.

imagesetpixel( $im, 2, 4, $ns );

The above code will add a small pixel at the co-ordinate (2,4) measured from top left corner. Obiviously we will need many of these to make the image more difficult to read.

Once we have done that we can generate our image using imagepng which will create a png image out of the image resource $im.

Now we can generate our image.

imagepng($im);

As a best practise we will also the destroy the created image, since once outputed to the browser we no longer require it.

imagedestroy($im);

To output the image to the browser we will have to send some headers that will tell the browser that content type of this page is an image of type png. The below code should be called before any data is sent to browser. So it will go before the line imagepng($img)

header("Cache-Control: no-cache, must-revalidate");
header('Content-type: image/png');

Below is the overall code. Note that we have added some variables as params to the above discussed functions. The purpose of this is to add dynamicity to our code. Also the background noise pixel generating function imagesetpixel is added in a for loop for calling it multiple times. And lastly the cpatcha characters are generated randomly. The random captcha characters are stored in SESSION[‘captcha_code’] session variable.


Save the above code in a php file, say captcha.php, and use this file as an image source for the captcha image.

A simple example usage of the above php file would be as follow

HTML form

Server side Validation


Leave a Reply

Your email address will not be published. Required fields are marked *