PHP Captcha Security Images

This script generates images (known as “Captcha’s”) which contain
security codes used for protecting a form from spam bots. By encoding
a ‘password’ inside an image and asking the user to re-enter what they see
you can verify the user is a human and not automated software submitting
your form. Why not try out the following form with valid and invalid codes
to see how it works.

See it in action

Update (27th March 2007): To stop spammers viewing the security code once and then continually submitting the form without requesting a new security image/code you should add the line unset($_SESSION['security_code']); when you are processing the form to clear the session

Update (7th February 2007): Due to a security bug in the script please ensure you are using the latest version

If you find this script useful then please consider making a donation to the developer

The code

<?php
session_start();
 
/*
* File: CaptchaSecurityImages.php
* Author: Simon Jarvis
* Copyright: 2006 Simon Jarvis
* Date: 03/08/06
* Updated: 07/02/07
* Requirements: PHP 4/5 with GD and FreeType libraries
* Link: http://www.white-hat-web-design.co.uk/articles/php-captcha.php
* 
* This program is free software; you can redistribute it and/or 
* modify it under the terms of the GNU General Public License 
* as published by the Free Software Foundation; either version 2 
* of the License, or (at your option) any later version.
* 
* This program is distributed in the hope that it will be useful, 
* but WITHOUT ANY WARRANTY; without even the implied warranty of 
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
* GNU General Public License for more details: 
* http://www.gnu.org/licenses/gpl.html
*
*/
 
class CaptchaSecurityImages {
 
	var $font = 'monofont.ttf';
 
	function generateCode($characters) {
		/* list all possible characters, similar looking characters and vowels have been removed */
		$possible = '23456789bcdfghjkmnpqrstvwxyz';
		$code = '';
		$i = 0;
		while ($i < $characters) { 
			$code .= substr($possible, mt_rand(0, strlen($possible)-1), 1);
			$i++;
		}
		return $code;
	}
 
	function CaptchaSecurityImages($width='120',$height='40',$characters='6') {
		$code = $this->generateCode($characters);
		/* font size will be 75% of the image height */
		$font_size = $height * 0.75;
		$image = @imagecreate($width, $height) or die('Cannot initialize new GD image stream');
		/* set the colours */
		$background_color = imagecolorallocate($image, 255, 255, 255);
		$text_color = imagecolorallocate($image, 20, 40, 100);
		$noise_color = imagecolorallocate($image, 100, 120, 180);
		/* generate random dots in background */
		for( $i=0; $i<($width*$height)/3; $i++ ) {
			imagefilledellipse($image, mt_rand(0,$width), mt_rand(0,$height), 1, 1, $noise_color);
		}
		/* generate random lines in background */
		for( $i=0; $i<($width*$height)/150; $i++ ) {
			imageline($image, mt_rand(0,$width), mt_rand(0,$height), mt_rand(0,$width), mt_rand(0,$height), $noise_color);
		}
		/* create textbox and add text */
		$textbox = imagettfbbox($font_size, 0, $this->font, $code) or die('Error in imagettfbbox function');
		$x = ($width - $textbox[4])/2;
		$y = ($height - $textbox[5])/2;
		imagettftext($image, $font_size, 0, $x, $y, $text_color, $this->font , $code) or die('Error in imagettftext function');
		/* output captcha image to browser */
		header('Content-Type: image/jpeg');
		imagejpeg($image);
		imagedestroy($image);
		$_SESSION['security_code'] = $code;
	}
 
}
 
$width = isset($_GET['width']) ? $_GET['width'] : '120';
$height = isset($_GET['height']) ? $_GET['height'] : '40';
$characters = isset($_GET['characters']) && $_GET['characters'] > 1 ? $_GET['characters'] : '6';
 
$captcha = new CaptchaSecurityImages($width,$height,$characters);
 
?>

Usage

Copy and paste the above code and save it on your webserver as CaptchaSecurityImages.php.
You will also need to place a copy of the “Monofont” font in the same directory as the CaptchaSecurityImages.php file. (Alternatively you can replace the line var $font = ‘monofont.ttf’; with the name of whatever font you want to use)

You can download the captcha zip which contains all the files needed to implement the script including the required font.

Place the following code on your form. This will generate an image with
a random string of characters along with the text field where the
user will retype the code.

<img src="CaptchaSecurityImages.php" alt="" />
Security Code:
<input id="security_code" name="security_code" type="text" />

You can also specify certain options for the image by
passing them as variables to CaptchaSecurityImages.php. The options available
are the width and height of the image and the number of characters

<img src="CaptchaSecurityImages.php?width=100&amp;height=40&amp;characters=5" alt="captcha" />
<input id="security_code" name="security_code" type="text" />

Place the following in the code where the form is submitted to. This code
will check what the user has typed matches the code in the image.

session_start();
if(($_SESSION['security_code'] == $_POST['security_code']) && (!empty($_SESSION['security_code'])) ) {
	// Insert you code for processing the form here, e.g emailing the submission, entering it into a database. 
	unset($_SESSION['security_code']);
} else {
	// Insert your code for showing an error message here
}

Optional Extras

If you would rather your <img> tag links to a jpg rather than a php file you can use mod_rewrite. By inserting the following in your .htaccess file you can use <img src=”captcha.jpg” /> instead.

RewriteEngine on
RewriteRule captcha.jpg /CaptchaSecurityImages.php

You may wish to change the colour of the captcha image, this can be done by editing the background_colour, text_colour and noise_colour variables. The imagecolorallocate() function constucts a colour from the given RGB (red, green and blue) values, each of these is a number between 0-255. Another idea you might want to try is using the mt_rand function to randomize the colour each time a captcha is generated.

Having Problems?

Please read our help page