VB.NET Example

elcastelli quickly hacked up a VB.NET example!
Download the VB.NET project here.

    Public Function postCaptcha(ByVal strApiKey As String, ByVal strCaptchaFile As String) As String
        Dim objEncoding As New System.Text.UTF8Encoding
        Dim objStreamWriter As System.IO.StreamWriter
        Dim objStream As System.IO.Stream
        Dim objHTTPRequest As HttpWebRequest
        Dim sbPostData As New System.Text.StringBuilder
        Dim intUploadBit As Integer
        Dim intUploadSoFar As Integer
        Dim inttoUpload As Integer
        Dim i As Integer
        Dim objStreamReader As System.IO.Stream
        Dim strResult As String

        'set request properties
        objHTTPRequest = System.Net.WebRequest.Create("http://www.captchakiller.com/api.php")
        objHTTPRequest.AllowAutoRedirect = True
        objHTTPRequest.Accept = "*/*"
        objHTTPRequest.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705)"
        objHTTPRequest.KeepAlive = False
        objHTTPRequest.Timeout = 30000
        objHTTPRequest.Method = "POST"
        objHTTPRequest.ContentType = "multipart/form-data; boundary=7cf2a327f01ae"


        sbPostData.Append("--" + "7cf2a327f01ae" + vbCrLf)
        sbPostData.Append("Content-Disposition: form-data; name=""api_key""" + vbCrLf)
        sbPostData.Append(vbCrLf)
        sbPostData.Append(strApiKey + vbCrLf)

        sbPostData.Append("--" + "7cf2a327f01ae" + vbCrLf)
        sbPostData.Append("Content-Disposition: form-data; name=""expire""" + vbCrLf)
        sbPostData.Append(vbCrLf)
        sbPostData.Append("1000" + vbCrLf)   'defaulted to 1000 but you can change this
        sbPostData.Append("--" + "7cf2a327f01ae" + vbCrLf)
        sbPostData.Append("Content-Disposition: form-data; name=""method""" + vbCrLf)
        sbPostData.Append(vbCrLf)
        sbPostData.Append("upload_captcha" + vbCrLf)

        sbPostData.Append("--" + "7cf2a327f01ae" + vbCrLf)
        sbPostData.Append("Content-Disposition: form-data; name=""rights""" + vbCrLf)
        sbPostData.Append(vbCrLf)
        sbPostData.Append("false" + vbCrLf) 'defaulted to false but you can change this

        'this is the header for our captcha file upload
        sbPostData.Append("--" + "7cf2a327f01ae" + vbCrLf)
        sbPostData.Append("Content-Disposition: form-data; name=""file""; filename=""" & strCaptchaFile & "" + vbCrLf)
        sbPostData.Append("Content-Type: image/pjpeg" + vbCrLf)
        sbPostData.Append(vbCrLf)

        'read our captch into a byte array
        Dim objBinReader As New BinaryReader(File.OpenRead(strCaptchaFile))
        Dim bytPhotoContents As Byte() = objBinReader.ReadBytes(objBinReader.BaseStream.Length)
        objBinReader.Close()

        'convert our other post data into a byte array
        Dim bytPostContents As Byte() = objEncoding.GetBytes(sbPostData.ToString)

        'create a footer for insertation after the file bytes are uploaded
        Dim bytPostFooter As Byte() = objEncoding.GetBytes(vbCrLf + "--" + "7cf2a327f01ae" + vbCrLf)

        'create a new data buffer to hold all of our byte arrays
        Dim bytDataBuffer As Byte() = New Byte(bytPostContents.Length + bytPhotoContents.Length + bytPostFooter.Length) {}

        'copy the contents of our three byte arrays into our single byte array
        System.Buffer.BlockCopy(bytPostContents, 0, bytDataBuffer, 0, bytPostContents.Length)
        System.Buffer.BlockCopy(bytPhotoContents, 0, bytDataBuffer, bytPostContents.Length, bytPhotoContents.Length)
        System.Buffer.BlockCopy(bytPostFooter, 0, bytDataBuffer, bytPostContents.Length + bytPhotoContents.Length, bytPostFooter.Length)

        'set the content length based on our new byte array length
        objHTTPRequest.ContentLength = bytDataBuffer.Length

        'get our stream and post our data
        objStream = objHTTPRequest.GetRequestStream()


        'chunk up our data and upload it to our stream
        'will generally only need to send in one chunk unless file is large
        intUploadBit = Math.Max(bytDataBuffer.Length / 100, 50 * 1024)
        intUploadSoFar = 0

        While i < bytDataBuffer.Length
            inttoUpload = Math.Min(intUploadBit, bytDataBuffer.Length - i)
            intUploadSoFar += inttoUpload
            objStream.Write(bytDataBuffer, i, inttoUpload)
            i = i + intUploadBit
        End While

        'close our stream
        objStream.Close()

        'get the response from the server
        Dim objHTTPResponse As HttpWebResponse = CType(objHTTPRequest.GetResponse(), HttpWebResponse)
        objStreamReader = objHTTPResponse.GetResponseStream()

        'final result from server is returned to strResult
        Dim objStreamResult As New System.IO.StreamReader(objStreamReader)
        strResult = objStreamResult.ReadToEnd

        
        'close our objects
        objStreamReader.Close()
        objStreamResult.Close()

        Return strResult


    End Function

Example Code Perl

When I run this it looks like:

$ perl test.pl 
SUCCESS: captcha_id=17B30BBC-6B66-42CC-0AA3-70B55A4E9402
GOT CAPTCHA ID: 17B30BBC-6B66-42CC-0AA3-70B55A4E9402
ATTEMPT 1
WAIT: check back later
ATTEMPT 2
SUCCESS: captcha_result="DMJDxRw"

Here is the source code of that test client:

require LWP::UserAgent;
use Data::Dumper;

my $ua = LWP::UserAgent->new;
push @{ $ua->requests_redirectable }, "POST";

my $api_key = "insert_your_api_code_here";
my $captcha_url = "http://www.website.com/captcha_url";
my $upload_filename = "captcha_filename_on_disk";

my $response = $ua->post( "http://www.captchakiller.com/api.php",
                Content_Type => 'form-data',
                Content => [ api_key => $api_key, method => "upload_captcha",
                captcha_url => $captcha_url, file => [ $upload_filename ] ] );
$captcha_id = "";
if ( $response->is_success ) {
        print $response->{_content};
        if ( $response->{_content} =~ /SUCCESS: captcha_id=([\w\-]+)/ ) {
                $captcha_id = $1;
                print "GOT CAPTCHA ID: $captcha_id\n";
        }
}
else {
        die $response->status_line;
}

$captcha_result = "";
for ( my $cnt = 1; $cnt < 20; $cnt++ ) {
        print "ATTEMPT $cnt\n";
        my $response = $ua->post( "http://www.captchakiller.com/api.php",
                Content => [ api_key => $api_key, method => "get_result", captcha_id => $captcha_id ] );
        if ( $response->is_success ) {
                print $response->{_content};
                next if ( $response->{_content} =~ /^WAIT/ );
                last if ( $response->{_content} =~ /^FAILURE/ );
                if ( $response->{_content} =~ /^SUCCESS: captcha_result=\"(.*)\"$/ ) {
                        $captcha_result = $1;
                        last;
                }
        }
        else {
                die $response->status_line;
        }
}

VB.NET Example and 30 limit

Why does the VB.Net example start failing uploading captchas after a certain time (error is: FAILURE: only 30 free per day, please upgrade.), but uploading directly from browser works perfectly fine?