Captcha is becoming complex and impractical with time. Here is an example: So, I dedicated myself to make my own captcha system that's more practical. At first, I needed some idea for the captcha, and here it is: I used Python to build the captcha system. Here is the snippet: random, string PIL Image, ImageDraw numpy np bomb = Image.open( ) bomb = bomb.resize((round(bomb.size[ ] * ), round(bomb.size[ ] * ))) bombMask = bomb.convert( ) lock = Image.open( ) lock = lock.resize((round(lock.size[ ] * ), round(lock.size[ ] * ))) lockMask = lock.convert( ) strData = string.ascii_letters + string.digits response = x range( ): response += random.choice(strData) response bgColor = (random.randint( , ), random.randint( , ), random.randint( , )) img = Image.new( , ((bomb.size[ ]) * + ( * ), bomb.size[ ] + round(bomb.size[ ] * )), color = bgColor) result = [] posX = maxHeight = x range( ): num = random.randint( , ) rotateDeg = random.randint( , ) (num == ): result.append( ) thisImg = bomb.rotate(rotateDeg, expand= ) thisMask = bombMask.rotate(rotateDeg, expand= ) : result.append( ) thisImg = lock.rotate(rotateDeg, expand= ) thisMask = lockMask.rotate(rotateDeg, expand= ) num = random.randint( , ) (num == ): thisImg = thisImg.transpose(Image.FLIP_LEFT_RIGHT) (num == ): thisImg = thisImg.transpose(Image.FLIP_TOP_BOTTOM) thisImg = thisImg.convert( ) data = np.array(thisImg) red, green, blue, alpha = data.T white_areas = (red == ) & (blue == ) & (green == ) itemColor = (random.randint( , ), random.randint( , ), random.randint( , )) (itemColor == bgColor): itemColor[ ] = random.randint( , ) data[..., : ][white_areas.T] = itemColor thisImg = Image.fromarray(data) img.paste(thisImg, (posX, ), thisMask) posX += lock.size[ ] + draw = ImageDraw.Draw(img) x range(random.randint( , )): draw.line((random.randint( , img.size[ ]),random.randint( , img.size[ ]), random.randint( , img.size[ ]), random.randint( , img.size[ ])), fill=bgColor, width=random.randint( , )) x range(random.randint( , )): dotX = random.randint( , img.size[ ]) dotY = random.randint( , img.size[ ]) diameter = random.randint( , ) draw.ellipse((dotX, dotY, dotX + diameter, dotY + diameter), fill=(random.randint( , ), random.randint( , ), random.randint( , ))) x range(random.randint( , )): draw.line((random.randint( , img.size[ ]) , random.randint( , img.size[ ]), random.randint( , img.size[ ]) + , random.randint( , img.size[ ])), fill=(random.randint( , ), random.randint( , ), random.randint( , )), width=random.randint( , )) filename = randomName() + img.save( + filename) file = open( , ) file.writelines( .join(str(v) v result) + + filename + ) import from import import as "bomb.png" 0 0.5 1 0.5 "L" "lock.png" 0 0.5 1 0.5 "L" : def randomName () '' for in 16 return : def buildCaptcha () 200 255 200 255 200 255 'RGB' 0 5 40 6 1 1 1.5 40 0 for in 5 1 2 0 360 if 1 0 1 1 else 1 1 1 1 3 if 2 elif 3 'RGBA' 255 0 0 0 255 0 255 0 255 if 0 0 255 -1 50 1 40 for in 50 80 0 0 0 1 0 0 0 1 3 5 for in 50 200 0 0 0 1 1 10 0 255 0 255 100 255 for in 15 30 0 0 0 1 0 0 20 0 1 0 255 0 255 100 255 1 3 '.png' 'captcha/padlock/' 'answer.csv' 'a' ' ' for in ',' '\n' So, what the system does is: 1. Read the source images, and 2. Create the background image with a random color. 3. Generate the random icon. 4. Change the icon color with a random color. 5. Add some random lines and dots. 6. Save the image with a random name. 7. Store the file location and captcha answer in a file named . 8. Repeat it 1000 times. bomb.png padlock.png. answer.csv Here is the result: And here is another sample: After that, we need the engine and user interface for the captcha. For the engine, I used PHP with MySQL database, and for the user interface, I used bootstrap. Here is the engine work: 1. Read the to receive random captcha location and the answer. 2. Store the answer to the database, and add the unique hash for the identifier. 3. Give the unique hash, and file location to the UI. 4. The UI process the data and turn back the user response with a unique hash (of course) to the engine. 5. The engine checks the answer. 6. If valid, the engine updates the captcha data, sets it as solved. If it's not valid, the engine will try the process 'till 3 times. answer.csv Here is the final result: Before submission: Captcha authentication process: On success: On fail: This is my first article! Thanks for reading. Have a good day.