Click here to Skip to main content
13,250,883 members (47,965 online)
Click here to Skip to main content
Add your own
alternative version


24 bookmarked
Posted 20 May 2007

The image-based CAPTCHA

, 20 May 2007
Rate this:
Please Sign up or sign in to vote.
The article describes a variant of the image-based CAPTCHA.

A brief overview of the most known implementations

  • Carnegie Mellon's PIX CAPTCHA - the so called "naming images CAPTCHA" - the user sees a few pictures, and has to select a word that is appropriate to all the shown pictures. The main problem of this type of CAPTCHAs is misspelling while writing the answer, and synonyms for the answer-word (for example: dog, hound, pooch). In the described case, this is solved by means of transferring all the variants of the answer to the client side.
  • Oli Warner's KittenAuth - in order to prove his humanity, the visitor has to select all animals of a specified species among the proposed pictures. But, the limited number of pictures allows to recreate the picture base manually.
  • Microsoft's Asirra - in outline, it is similar to KittenAuth - the user has to distinguish cats from dogs - but, it works with an extremely large array of pictures (photos of homeless animals from the specialized site), and a reconstruction of the picture base is impossible.
  • IMAGINATION - a CAPTCHA that requires two steps to be passed. At the first step, the visitor clicks elsewhere on the picture that is composed of a few images, and selects a single image. In the second step, the selected image is loaded. It is enlarged, but very distorted. Also, variants of the answer are loaded on the client side. The visitor should select a correct answer from the set of proposed words.

Why are the image-based CAPTCHAs NOT so widespread as the text-based ones?

I will not touch on the contrastive analysis of the possibility to crack them, you can find some thoughts/calculations here and here. I want to express my point of view as a web developer. So, why?

  • They are too large. A CAPTCHA should not take a dominant position on a web page. Is is only an ancillary element that serves to weed out bots under forms filling, getting some information, etc.
  • The traffic. A few pictures, each with a size of about 5-10 KB, would weigh a lot for a single page, in my opinion. Visitors using a low bandwidth network will be unpleasantly impressed, not to mention visitors using dial-up connections.
  • The inconsistency to the general conception of a website. A CAPTCHA with cats (or dolphins) will be appropriate on a leisure site, but will be irrelevant - for example - on a site of a medical institution. In this case, it is possible to gather a number of images of medical subjects, but - on the analogy of Asirra - it would be problematic to find a site with a large amount of photos of homeless doctors :).
  • The laborious process of the picture base creation.

I have to note that it is not a criticism in any way - I only want to find an answer for the above question. Let's sum up the aforesaid. An image-based CAPTCHA might be a good alternative to a text-based one if it would be a single, light-weight image based on a limited set of pictures.

The idea

Look at these two pictures:

The original image
The changed image

It is easy to notice that the right image is slightly distorted, and it is not hard to outline a rough region where the distortion takes place. In order to notice it, the original image is not required. A human easy copes with this task even he sees an image the first time and does not know what the image depicts - the aforesaid does not apply to an expressionist's pictures :).

Now about bots. I have never worked with image recognition systems and my knowledge in this area is rather poor. Perhaps, the proposed variant is intricate to parse by special programs, perhaps not - it will be interesting to hear an expert's opinion.

The code overview

The proposed image-based CAPTCHA control works in such a way: a visitor sees a picture with a distorted part and he has to click elsewhere in the anomalous region boundaries. The point he clicks on will be marked with a red spot.

The control fulfils a double functionality, it renders its HTML content and forms the picture itself. It has two child controls: an image, and a hidden field that serves to store coordinates of the visitor's chosen point. The image URL forms by adding the special parameter to the currently requested URL. When the request to this new URL comes, the control interrupts the usual process of page loading and writes the image as a byte array in the response.

protected override void OnInit(EventArgs e)
    if (HttpContext.Current.Request[queryKey] != null)

private void DrawImage()
    Bitmap bitmap;
    //the image creation goes here

    HttpContext.Current.Response.ContentType = "image/jpg";

This approach allows to compound all the functionality in a single control. In a heavily loaded environment, it is better to take out the image creation elsewhere to another place - for example, to the HttpHandler - to avoid complicating the creation of the page where the control is placed on.

The coordinates of the point where the visitor clicks is calculated and visualized by means of JavaScript (tested on IE 6.0, Firefox 1.0+, Opera 9.1). They are stored in the hidden field in order to be accessible on the server side.

function captchaClicked(hidID,e)
  var sender = || e.srcElement;
  var offsetX, offsetY;
  //the calculation of the the clicked point's coordinates

  if (e.offsetX) //IE

     offsetX = e.offsetX;
     offsetY = e.offsetY;
  else if (e.pageX) //Firefox, Opera

     var left = sender.offsetLeft;
     var top = sender.offsetTop;
     var parentNode = sender.offsetParent;
     while(parentNode != null && parentNode.offsetLeft != null 
                              && parentNode.offsetTop != null){
        left += parentNode.offsetLeft;
        top += parentNode.offsetTop;
        parentNode = parentNode.offsetParent;
     offsetX = e.pageX - left;
     offsetY = e.pageY - top;
  //storing of the coordinates
  document.getElementById(hidID).value = offsetX+","+offsetY;
  //the creation of the little red spot to mark the clicked point
  var spot = document.getElementById("spotOnCaptha");
  if (!spot)
     spot = document.createElement("span"); = "spotOnCaptha"; = "3px"; = "3px";"1px";"red";"absolute"; = 100;
  //positioning of the spot = e.pageX || (event.clientX + document.body.scrollLeft); = e.pageY || (event.clientY + document.body.scrollTop);

Now, about the CAPTCHA image creation. In the loaded template picture, a rectangle with randomly defined coordinates is selected. Then, the coordinates are saved in the Session. It is possible to store them in the ViewState, but in this case, they have to be encoded because the ViewState is accessible on the client side. Then, the image in the rectangle boundaries is stretched (any other distortion may be used, the only condition - it has to be notable for the site visitor).

Also, here is another problem. It is possible to compare the template (original) image and the final distorted image pixel by pixel in order to find the distorted area (thanks davidbeseke for the exploit). To avoid this possibility, the template image is also changed in a random way. In the example below, it is stretched or compressed on a random scale.

//template image loading

using (System.Drawing.Image img = 
    //CAPCTHA image size is smaller then the template image one.

    int captchaWidth = (int)(img.Width * 0.9);
    int captchaHeight = (int)(img.Height * 0.9);

    bitmap = new Bitmap(captchaWidth, captchaHeight);
    Graphics g = Graphics.FromImage(bitmap);

    //the rectangle dimension

    int rectWidth = 20;
    int rectHeight = 20;

    Random r = new Random();

    //the original (template) image 
    //is stretched or shrunken in a random way

    float scaleX = 1 + r.Next(-100, 100) / 1000f;
    float scaleY = 1 + r.Next(-100, 100) / 1000f;
    g.ScaleTransform(scaleX, scaleY);
    g.DrawImage(img, 0, 0, img.Width, img.Height);

    //the rectangle coordinates are selected in a random way too

    int x = r.Next(0, captchaWidth - rectWidth);
    int y = r.Next(0, captchaHeight - rectHeight);
    Rectangle distortedRect = new Rectangle(x, y, rectWidth, rectHeight);
    HttpContext.Current.Session["ImgCAPTCHA.coords"] = distortedRect;

    rectWidth = rectWidth + 10;
    rectHeight = rectHeight + 10;
    if (x + rectWidth > captchaWidth)
        x = captchaWidth - rectWidth;
    if (y + rectHeight > captchaHeight)
        y = captchaHeight - rectHeight;

    //draw distorted part of the image

    g.DrawImage(img, distortedRect, 
                new Rectangle(x, y, rectWidth, rectHeight), 

    g.DrawRectangle(Pens.Black, 0, 0, captchaWidth-1, captchaHeight-1);

Maybe the proposed image creation algorithm looks imperfect. Yes, it does. I want to say that this article is rather an idea presentation than a control's description (it is just an example).

How to use

In order to use the control, it has to assign the path of the template image to the TemplateImageUrl property. The result of the CAPTCHA control action is a value of the IsValid property. The control can be locked after a fixed number of the failed attempts to pass the test, per session (FailedAttemptsBeforeLocking and IsLocked properties). You can see how it works on the test page on my site. The full code is accessible in the demo project.


  • 20 May 2007: Posted.
  • 22 May 2007: The ability to lock the control after a predefined number of unsuccessful attempts was added. The algorithm of the image creation was changed.


This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


About the Author

Mykola Tarasyuk
Software Developer (Senior)
Ukraine Ukraine
I'm a software developer from Ukraine. I write about ASP.NET and other .NET related topics over at

You may also be interested in...

Comments and Discussions

QuestionThnx Pin
white5hadow4-Feb-13 0:30
memberwhite5hadow4-Feb-13 0:30 
GeneralInteresting Idea Pin
stixoffire14-Dec-07 2:30
memberstixoffire14-Dec-07 2:30 
GeneralContinuation ... Pin
Mykola Tarasyuk31-Aug-07 8:00
memberMykola Tarasyuk31-Aug-07 8:00 
GeneralNice idea, but ... Pin
chitty222-May-07 22:36
memberchitty222-May-07 22:36 
GeneralRe: Nice idea, but ... Pin
Mykola Tarasyuk23-May-07 0:05
memberMykola Tarasyuk23-May-07 0:05 
GeneralCracking this captcha Pin
davidbeseke22-May-07 4:17
memberdavidbeseke22-May-07 4:17 
GeneralRe: Cracking this captcha Pin
Mykola Tarasyuk22-May-07 5:44
memberMykola Tarasyuk22-May-07 5:44 
GeneralRe: Cracking this captcha Pin
Mykola Tarasyuk23-May-07 0:06
memberMykola Tarasyuk23-May-07 0:06 
GeneralI may be wrong Pin
sk8er_boy28720-May-07 22:34
membersk8er_boy28720-May-07 22:34 
GeneralRe: I may be wrong Pin
Mykola Tarasyuk21-May-07 2:42
memberMykola Tarasyuk21-May-07 2:42 
>>I don't know if this is such a good idea. The example is not
>>very good. I didn't spot the difference until I read the text
>>below it (the red arrow points too far to the left of the deformation,
>> so it didn't help much).

Thanks for the case comment. I'll try to improve the images in the article.
Do you have the same difficulty when you work with demo project or on test page? My interest whether is it hard to notice a distortion or is it impossible to notice it?

>>It would be really easy for an automated bot to just send all the
>>coordinates in the image to the server (i.e, simulate a click on
>>each pixel of the image) and figure out the returned destination
>> url through elimination. It would probably end up with two possible
>>destination url's, one which is the real request url, and one which
>>points back to the image control in case the user clicked outside the
>> deformation, for another test.
>> By comparing url strings or by repeating the process a few times,
>>the real url is bound to be found.

Image url do not store any information about the right answer. This url is changed only to avoid caching of the image.
Coordinates are stored in Session and they are changed on each postback - also image is refreshed and the distortion will be in another place - so it is impossible to send multiple answers to the same image. Or did I misunderstand something in your message?

GeneralRe: I may be wrong Pin
sk8er_boy28721-May-07 3:18
membersk8er_boy28721-May-07 3:18 
GeneralRe: I may be wrong Pin
hoxha21-May-07 6:16
memberhoxha21-May-07 6:16 
GeneralRe: I may be wrong Pin
Mykola Tarasyuk21-May-07 12:35
memberMykola Tarasyuk21-May-07 12:35 
GeneralRe: I may be wrong Pin
Mykola Tarasyuk21-May-07 12:34
memberMykola Tarasyuk21-May-07 12:34 
GeneralTest page [modified] Pin
sk8er_boy28721-May-07 23:24
membersk8er_boy28721-May-07 23:24 
GeneralRe: Test page Pin
Mykola Tarasyuk22-May-07 5:47
memberMykola Tarasyuk22-May-07 5:47 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.171114.1 | Last Updated 20 May 2007
Article Copyright 2007 by Mykola Tarasyuk
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid