How To Create a CAPTCHA Graphic in VB.NET
November 6th, 2007
In this article we’ll be creating a class to generate CAPTCHA graphics that you can use on web sites to help authenticate users as being human and not an automated process.
What Is CAPTCHA
CAPTCHA is an abbreviation for Completely Automated Public Turing test to tell Computers and Humans Apart. This method uses images of words or numbers that are, in theory, distorted and jumbled enough so that an optical character recognition program can’t read them but a human should be able to do so easily.
I’m not a big fan of this method myself since I think it interferes with the user experience. However, there is plenty of demand for them to be placed into systems that interact with the public on the Internet.
The CAPTCHA Class
You can download the CAPTCHA class source code here.
This class is a simple one that builds a 5 character numeric string and places it on a grid background with random ‘noise’. Our properties include the height, width, and font along with the randomly generated value between 10000 and 99999 and the matching bitmap. The new method is available as a parameterless version for subclassing and one that allows you to pass in the height, width, and font.
The core routine is the GenerateNewCaptcha shown here:
Public Sub GenerateNewCaptcha() If _captchaFont Is Nothing OrElse _captchaHeight = 0 OrElse _captchaWidth = 0 Then Exit Sub End If _captchaCode = RandomValue.Next(10000, 100000).ToString _captchaImage = New Bitmap(_captchaWidth, _captchaHeight) Using CaptchaGraphics As Graphics = Graphics.FromImage(CaptchaImage) Using BackgroundBrush As New Drawing2D.HatchBrush(Drawing2D.HatchStyle.SmallGrid, Color.DimGray, Color.WhiteSmoke) CaptchaGraphics.FillRectangle(BackgroundBrush, 0, 0, _captchaWidth, _captchaHeight) End Using Dim CharacterSpacing As Integer = (_captchaWidth \ 5) - 1 Dim HorizontalPosition As Integer Dim MaxVerticalPosition As Integer For Each CharValue As Char In _captchaCode.ToCharArray MaxVerticalPosition = _captchaHeight - Convert.ToInt32(CaptchaGraphics.MeasureString(CharValue, _captchaFont).Height) CaptchaGraphics.DrawString(CharValue, _captchaFont, Brushes.DimGray, HorizontalPosition, RandomValue.Next(0, MaxVerticalPosition)) HorizontalPosition += CharacterSpacing + RandomValue.Next(-1, 1) Next For Counter As Integer = 0 To 24 CaptchaGraphics.FillEllipse(Brushes.DimGray, RandomValue.Next(1, _captchaWidth), RandomValue.Next(1, _captchaHeight), RandomValue.Next(1, 4), RandomValue.Next(1, 4)) Next For Counter As Integer = 0 To 24 CaptchaGraphics.FillEllipse(Brushes.WhiteSmoke, RandomValue.Next(1, _captchaWidth), RandomValue.Next(1, _captchaHeight), RandomValue.Next(1, 4), RandomValue.Next(1, 4)) Next End Using End Sub
Let’s look at some of the details of this routine.
First, notice that we’re generating random numbers in several places, most notably to generate the main code value. We also use random numbers to place the numbers and the noise bits.
The HatchBrush object is used to draw the grid background. This style could be changed to a different pattern. There are several variations you could try to get a unique effect. You could even randomize the background.
The characters from the randomly generated number are drawn onto the graphic one character at a time and are randomly placed along the vertical axis and slightly off kilter on the horizontal one.
The FillEllipse method of the Graphics object is used to create the noise at 50 different random points on the graphic. These little marks help obscure the actual characters from OCR’s and sometimes from humans as well.
Using the Class
Using the class is simple. You just create the class, display the graphic from it and verify user input against the value stored in the class. You can also regenerate the value if the user requests it. Remember that you will need to save the generated bitmap to disk in order to display it to a web user in an ASP.NET application.
More You Can Add
There are several things you could add to this class to enhance it. You could:
- Add the ability to accept strings
- Add the ability to dynamically size the strings and the resulting bitmap
- Add more distortion by using Graphics method to twist the output
- Add more background noise options
That’s all for this example. Let me know if you have any questions or observations by this example by leaving me a comment.
Entry Filed under: Code Examples
Rate This Article:









(5 votes, average: 4.6 out of 5)
17 Comments Add your own
1. Ashok | November 10th, 2007 at 7:34 pm
Could provide a concrete example of using the captcha class? Thank you
2. nilesh | November 13th, 2007 at 8:49 am
please can you show the view of the bild simple software
3. jfrankcarr | November 13th, 2007 at 8:58 am
Thanks for stopping by Ashok and Nilesh,
I’ll put together an example soon.
4. Naafraat | November 18th, 2007 at 6:27 am
I have seen some software tools that can read a Captcha graphic. How is that made possible. Can we do it using vb ?
5. jfrankcarr | November 18th, 2007 at 12:48 pm
Hi Naafraat,
That would require Optical Character Reader (OCR) software. There are several tools available for .NET that can do this to varying degrees of success.
How well it will decipher a CAPTCHA depends on the how hard the graphic is to read. In my example, the background grid graphic, random placement, font and dots would make it more difficult to OCR than plain text. If you applied more effects to the graphic it would make it more difficult to read, both for software and humans.
6. Will N | January 17th, 2008 at 11:49 am
How do you call this on your page to show the image?
7. Keith B. | February 13th, 2008 at 3:21 pm
Thanks for the code download and the tips. Nice post.
8. David | February 26th, 2008 at 7:04 pm
How do you call this class and use it in the page?
9. Yoko | March 8th, 2008 at 10:39 pm
Very informative. Thanks for sharing. :)
10. Sanjai Malani | April 8th, 2008 at 1:37 am
How do you call this class and use it in the page?
11. Chuck | April 23rd, 2008 at 12:46 pm
Sometime even more effective than captcha is just asking a simple, easy for humans to understand, hard for computers to grasp, question.
Something as simple as “What is the sum of 10 and 5?”
As far as I know, there are no bots out there yet smart enough to decipher such simple questions. A more sophisticated system could randomize a set of simple questions, to make it even more secure.
What color is the sun? Yellow.
What is the name of the planet on which we live? Earth
and so on.
Another advantage is this is more accessible to the vision-impaired.
12. jfrankcarr | April 23rd, 2008 at 1:50 pm
Hi Chuck,
That is true. However, there are some blackhat scripts around that I’ve seen that will do some equation solving for captchas, particularly if it’s worded like you have in your comment.
It’s a never ending battle against spam. While I don’t update this site often due to other commitments, I do keep an eye on it. In the past 3 months there have been over 10000 spam comment attempts. Akismet, while not perfect, does a good job of keeping them at bay.
13. Cathy | July 21st, 2008 at 1:07 am
Hi,
I would like to know the design part of the code.. i.e.captcha
14. Toner | December 23rd, 2008 at 5:30 pm
To integrate:
Dim myCaptcha As New Captcha
myCaptcha.CaptchaHeight = 50
myCaptcha.CaptchaWidth = 150
myCaptcha.CaptchaFont = New Font(”Verdana”, 20, FontStyle.Regular)
myCaptcha.GenerateNewCaptcha()
myCaptcha.CaptchaImage.Save(Request.PhysicalApplicationPath & “images\captcha\” & myCaptcha.CaptchaCode & “.jpg”)
ltrCaptcha.Text = myCaptcha.CaptchaCode
imgCaptcha.ImageUrl = “../images/captcha/” & myCaptcha.CaptchaCode & “.jpg”
Then on user input just check wheter invisble ltrCaptcha text is same as user’s input!
15. venkat | March 31st, 2009 at 1:21 am
hai..
As you said you have to store the image in your project folder..
If it happen like this.. if the number of user visiting that page in the
sense - so there are no.of images stored in the My Images folder
how to avoid this….
how to use Character Instead of numbers… to display in the image..
16. Webdevelopment company | September 19th, 2009 at 1:42 am
As i am fresher in vb.net development thanks a lot to give me insight in captcha it helps me a lot.
17. Vasanth | January 29th, 2010 at 11:25 am
hi venkat ,
we can also use characters or numbers or mixed characters otrnumbers by modifying the code with the single function which is shown below
Imports System.Web.SessionState
Imports System.Drawing
Imports System.Drawing.Imaging
Public Class Captcha
Protected RandomValue As New Random
Protected _captchaImage As Bitmap
Protected _captchaHeight As Integer
Protected _captchaWidth As Integer
Protected _captchaFont As Font
Protected _captchaCode As String
”’
”’ Useful for subclassing
”’
”’
Public Sub New()
End Sub
”’
”’ Loads properties and generates an initial captcha value and graphic
”’
”’ The Width of the Captcha Graphic
”’ The Height of the Captcha Graphic
”’ The Font of the Captcha Graphic
”’
Public Sub New(ByVal imageWidth As Integer, ByVal imageHeight As Integer, ByVal imageFont As Font)
_captchaHeight = imageHeight
_captchaWidth = imageWidth
_captchaFont = imageFont
GenerateNewCaptcha()
End Sub
”’
”’ Generates a new captcha value and graphic for the class
”’
”’
Public Sub GenerateNewCaptcha()
If _captchaFont Is Nothing OrElse _captchaHeight = 0 OrElse _captchaWidth = 0 Then
Exit Sub
End If
_captchaCode = getrandomstring()
_captchaImage = New Bitmap(_captchaWidth, _captchaHeight)
Using CaptchaGraphics As Graphics = Graphics.FromImage(CaptchaImage)
Using BackgroundBrush As New Drawing2D.HatchBrush(Drawing2D.HatchStyle.SmallGrid, Color.GhostWhite, Color.WhiteSmoke)
CaptchaGraphics.FillRectangle(BackgroundBrush, 0, 0, _captchaWidth, _captchaHeight)
End Using
Dim CharacterSpacing As Integer = (_captchaWidth \ 5) - 1
Dim HorizontalPosition As Integer
Dim MaxVerticalPosition As Integer
For Each CharValue As Char In _captchaCode.ToCharArray
MaxVerticalPosition = _captchaHeight - Convert.ToInt32(CaptchaGraphics.MeasureString(CharValue, _captchaFont).Height)
CaptchaGraphics.DrawString(CharValue, _captchaFont, Brushes.DimGray, HorizontalPosition, RandomValue.Next(0, MaxVerticalPosition))
HorizontalPosition += CharacterSpacing + RandomValue.Next(-1, 1)
Next
For Counter As Integer = 0 To 24
CaptchaGraphics.FillEllipse(Brushes.DimGray, RandomValue.Next(1, _captchaWidth), RandomValue.Next(1, _captchaHeight), RandomValue.Next(1, 4), RandomValue.Next(1, 4))
Next
For Counter As Integer = 0 To 24
CaptchaGraphics.FillEllipse(Brushes.WhiteSmoke, RandomValue.Next(1, _captchaWidth), RandomValue.Next(1, _captchaHeight), RandomValue.Next(1, 4), RandomValue.Next(1, 4))
Next
End Using
End Sub
”’
”’ The captcha bitmap image
”’
”’
”’
”’
Private Function getrandomstring() As String
Dim arrstr() As String
arrstr = “A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,1,2,3,4,5,6,7,8,9,0″.Split(”,”.ToCharArray())
Dim strdraw As String
Dim r As Random
r = New Random()
strdraw = String.Empty
Dim i As Integer
For i = 0 To 4
strdraw += arrstr(r.Next(0, arrstr.Length - 1))
Next
Return strdraw
End Function
Public Property CaptchaImage() As Bitmap
Get
Return _captchaImage
End Get
Set(ByVal value As Bitmap)
_captchaImage = value
End Set
End Property
”’
”’ The value of the captcha
”’
”’
”’
”’
Public Property CaptchaCode() As String
Get
Return _captchaCode
End Get
Set(ByVal value As String)
_captchaCode = value
End Set
End Property
”’
”’ The Height of the Captcha Graphic
”’
”’
”’
”’
Public Property CaptchaHeight() As Integer
Get
Return _captchaHeight
End Get
Set(ByVal value As Integer)
_captchaHeight = value
End Set
End Property
”’
”’ The Width of the Captcha Graphic
”’
”’
”’
”’
Public Property CaptchaWidth() As Integer
Get
Return _captchaWidth
End Get
Set(ByVal value As Integer)
_captchaWidth = value
End Set
End Property
”’
”’ The Font of the Captcha Graphic
”’
”’
”’
”’
Public Property CaptchaFont() As Font
Get
Return _captchaFont
End Get
Set(ByVal value As Font)
_captchaFont = value
End Set
End Property
End Class
Leave a Comment
Some HTML allowed:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>
Trackback this post | Subscribe to the comments via RSS Feed