ActiveState Code

Recipe 440588: Human verification test (captcha)


The gen_captcha function generates an image containing text thatÂ’s easy for a human to read, but difficult for a computer. This allows you create a test to tell humans and computers apart. (requires PIL)

Python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import random
import Image
import ImageFont
import ImageDraw
import ImageFilter


def gen_captcha(text, fnt, fnt_sz, file_name, fmt='JPEG'):
	"""Generate a captcha image"""
	# randomly select the foreground color
	fgcolor = random.randint(0,0xffff00)
	# make the background color the opposite of fgcolor
	bgcolor = fgcolor ^ 0xffffff
	# create a font object 
	font = ImageFont.truetype(fnt,fnt_sz)
	# determine dimensions of the text
	dim = font.getsize(text)
	# create a new image slightly larger that the text
	im = Image.new('RGB', (dim[0]+5,dim[1]+5), bgcolor)
	d = ImageDraw.Draw(im)
	x, y = im.size
	r = random.randint
	# draw 100 random colored boxes on the background
	for num in range(100):
		d.rectangle((r(0,x),r(0,y),r(0,x),r(0,y)),fill=r(0,0xffffff))
	# add the text to the image
	d.text((3,3), text, font=font, fill=fgcolor)
	im = im.filter(ImageFilter.EDGE_ENHANCE_MORE)
	# save the image to a file
	im.save(file_name, format=fmt)

if __name__ == '__main__':
	"""Example: This grabs a random word from the dictionary 'words' (one
	word per line) and generates a jpeg image named 'test.jpg' using
	the truetype font 'porkys.ttf' with a font size of 25.
	"""
	words = open('words').readlines()
	word = words[random.randint(1,len(words))]
	gen_captcha(word.strip(), 'porkys.ttf', 25, "test.jpg")

Discussion

A CAPTCHA (Completely Automated Public Turing test to Tell Computers and Humans Apart) is a type of challenge and response test used tell humans and computers apart. This could be used to prevent "bots" from accessing online resources, taking part in online polls, signing up for free accounts, etc...

You must provide your own TrueType font(s); it works best if you use odd or irregular shaped fonts. You could even randomly choose a font for each captcha.

Comments

  1. 1. At 4:23 p.m. on 21 sep 2005, Kieran Holland said:

    An alternative python captcha library. Check out the PyCaptcha library too. I have found it to be simple and extensible:

    http://freshmeat.net/projects/pycaptcha/

  2. 2. At 5:47 a.m. on 17 jan 2006, Matthias Urlichs said:

    dead. no pycaptcha projct on freshmeat; the ones I could find are all PHP.

  3. 3. At 9:54 a.m. on 2 jun 2006, Antonello Lobianco said:

    http://sourceforge.net/projects/pycaptcha/. http://sourceforge.net/projects/pycaptcha/

  4. 4. At 9:48 p.m. on 2 nov 2006, Mayuresh Phadke said:

    An alternate method to generate the word. Instead of taking the word from dictionary it could be generated as follows:

    def gen_random_word(wordLen=6):
            allowedChars = "abcdefghijklmnopqrstuvwzyzABCDEFGHIJKLMNOPQRSTUVWZYZ0123456789"
            word = ""
            for i in range(0, wordLen):
                    word = word + allowedChars[random.randint(0,0xffffff) % len(allowedChars)]
            return word
    

    The main function would change to

    if __name__ == '__main__':
        """Example: This grabs a random word from the dictionary 'words' (one
        word per line) and generates a jpeg image named 'test.jpg' using
        the truetype font 'porkys.ttf' with a font size of 25.
        """
            word = gen_random_word()
            gen_captcha(word.strip(), 'porkys.ttf', 25, "test.jpg")
    
  5. 5. At 8:13 a.m. on 4 nov 2007, Armin Ronacher said:

    Not yet. It's not dead, the source is currently located here as it seems: http://svn.navi.cx/misc/trunk/pycaptcha/

  6. 6. At 8:13 a.m. on 4 nov 2007, Armin Ronacher said:

    Not yet. It's not dead, the source is currently located here as it seems: http://svn.navi.cx/misc/trunk/pycaptcha/

Sign in to comment