This i quite a tricky one that took me months to solve.
First things first. As you have discovered nearly all captcha images are dynamically generated images, this means that each time you request the image, even though the url (src tag) is the same, a new captcha image will always generated.
Your best bet to solve this is by "snipping" the already loaded captcha image out of your webbrowser. Trust me, this is the best way, if not the only way.
The good news is, it can easily be done with a built in method
webBrowser.DrawToBitmap(Bitmap,Rectangle)
My Sample Code: (how to use webbrowser.DrawToBitmap for an specific Element)
private void button1_Click(object sender, EventArgs e)
{
int CaptchaWidth = getXoffset(webBrowser1.Document.GetElementById("Captch-Element-Name"));
int CaptchaHeight = getYoffset(webBrowser1.Document.GetElementById("Captch-Element-Name"));
Bitmap bitmap = new Bitmap(CaptchaWidth, CaptchaHeight);
webBrowser1.DrawToBitmap(bitmap, new Rectangle(0, 0, CaptchaWidth, CaptchaHeight));
//now load the image into your pictureBox (you might need to convert the bitmap to a image)
}
//Methods to get Co-ordinates Of an Element in your webbrowser
public int getXoffset(HtmlElement el)
{
int xPos = el.OffsetRectangle.Left;
HtmlElement tempEl = el.OffsetParent;
while (tempEl != null)
{
xPos += tempEl.OffsetRectangle.Left;
tempEl = tempEl.OffsetParent;
}
return xPos;
}
public int getYoffset(HtmlElement el)
{
int yPos = el.OffsetRectangle.Top;
HtmlElement tempEl = el.OffsetParent;
while (tempEl != null)
{
yPos += tempEl.OffsetRectangle.Top;
tempEl = tempEl.OffsetParent;
}
return yPos;
}
So, the bad news is that c# has a annoying little bug in the drawtobitmap method (which is mentioned on the msdn site). What happens is sometimes a blank image will be returned when you run it.... yeah... not really what you want when you trying to crack Captchas right!
Luckily! Another stackOverflow user and i spent months working on a bug free version of this method that makes use of native GDI+.
And it works perfectly, so if drawtobitmap doesn't work the way you expect, here is an alternative.
Sample:
[DllImport("user32.dll")]
public static extern bool PrintWindow(IntPtr hwnd, IntPtr hdcBlt, uint nFlags);
public Bitmap CaptureWindow(Control ctl)
{
//Bitmap bmp = new Bitmap(ctl.Width, ctl.Height); // includes borders
Bitmap bmp = new Bitmap(ctl.ClientRectangle.Width, ctl.ClientRectangle.Height); // content only
using (Graphics graphics = Graphics.FromImage(bmp))
{
IntPtr hDC = graphics.GetHdc();
try { PrintWindow(ctl.Handle, hDC, (uint)0); }
finally { graphics.ReleaseHdc(hDC); }
}
return bmp;
}
So you'll simply call:
CaptureWindow(webBrowser1);
This will return a image of the entire webbrowser, then just snip-out the section containing the captcha image.
You can view my questions were i had the similar problems here (most weren't even answered):
Extracting a image from a WebBrowser Control
Screenshot method generates black images
Reset Webbrowser control to update settings
Now that you have the captcha images you'll need to decrypt them. So ask another question, send me the link and ill share my methods.
Im glad you didnt have to endure my nightmare. Don't forget to mark this as a solution, and as useful!