antigate-2.0: Interface for captcha recognition API

Safe HaskellNone





 {-# LANGUAGE OverloadedStrings #-}
 import Text.Recognition.Antigate
 import Data.Default
 import Network
 import Control.Monad
 import Control.Monad.IO.Class
 import Data.ByteString.Lazy hiding (putStrLn)
 import System.Timeout

 myApiKey :: ApiKey
 myApiKey = "0123456789abcdef0123456789abcdef"{api_host=""}

 downloadJpegCaptcha :: Manager -> IO ByteString
 downloadJpegCaptcha = undefined

 answerCaptcha :: String -> Manager -> IO Bool
 answerCaptcha = undefined

 main :: IO ()
 main = withSocketsDo $ do
     res <- timeout (30*1000000) $ withManager $ \m -> do
         bytes <- liftIO $ downloadJpegCaptcha m
         (id, answer) <- solveCaptcha def myApiKey def{phrase=True} "captcha.jpg" bytes m
         res <- liftIO $ answerCaptcha answer m
         unless res $ reportBad myApiKey id m
         return res
     case res of
         Nothing -> do
             putStrLn "Timed out"
         Just True -> do
             putStrLn "Solved successfully"
         Just False -> do
             putStrLn "Couldn't solve"



data ApiKey Source

Antigate API access key paired with service provider's host. At least these services claim to support Antigate API: Antigate, Captchabot, Decaptcher, ExpertDecoders, ImageTyperz, DeathByCaptcha and Pixodrom.

api_key :: ApiKey -> StringSource

This is a record selector

api_host :: ApiKey -> StringSource

default: "". This is a record selector

data CaptchaConf Source

Properties of the captcha to be solved. See




phrase :: Bool
  • False = default value (one word)
  • True = captcha has 2-4 words
regsense :: Bool
  • False = default value (case is not important)
  • True = captcha is case sensitive
numeric :: Maybe Bool
  • Nothing = default value
  • Just True = captcha consists from numbers only
  • Just False = captcha does not have numbers on it
calc :: Bool
  • False = default value
  • True = numbers on captcha must be summed
min_len :: Word
  • 0 = default value
  • >0 = minimum length of captcha text workers required to input
max_len :: Word
  • 0 = default value (unlimited)
  • >0 = maximum length of captcha text workers required to input
is_russian :: Bool
  • False = default value
  • True = captcha goes to Russian-speaking worker
max_bid :: Maybe Double

Default value is set on bids page. This parameter allows to control maximum bid without setting it on the bids page.

data ApiResult a Source


OK a 

captcha is not recognized yet, repeat request withing 1-5 seconds


user authorization key is invalid (its length is not 32 bytes as it should be)


the captcha ID you are sending is non-numeric


you have set wrong user authorization key in request


account has zero or negative balance


no idle captcha workers are available at the moment, please try a bit later or try increasing your bid


the size of the captcha you are uploading or pointing to is zero


your captcha size is exceeding 100kb limit


your captcha file has wrong extension, the only allowed extensions are gif,jpg,jpeg,png


Could not determine captcha file type, only allowed formats are JPG, GIF, PNG


Request with current account key is not allowed from your IP. Please refer to IP list section



High level

data SolveConf Source




api_upload_sleep :: [Int]

how much to sleep while waiting for available slot; in microseconds.

Default: [3000000]

api_check_sleep :: [Int]

how much to sleep between captcha checks; in microseconds.

Default: [6000000,2000000,3000000] -- sleep 6 seconds before checking, on first retry sleep 2 seconds, then always sleep 3 seconds. List can be infinite

api_counter :: Phase -> Int -> IO ()

api_counter will be called at the start of each phase

 api_counter = \phase count -> do
     if count == 0
       then putStrLn $ show phase ++ " began"
       else putStrLn $ show phase ++ " retries: " ++ show count

Default: _ _ -> return ()

api_upload_callback :: CaptchaID -> IO ()

This will be called when upload phase finishes



:: (Failure HttpException m, MonadIO m) 
=> SolveConf 
-> ApiKey 
-> CaptchaConf 
-> FilePath

image filename (antigate guesses filetype by file extension)

-> ByteString

image contents

-> Manager

HTTP connection manager to use

-> m (CaptchaID, String) 

High level function to solve captcha, blocks until answer is provided (about 2-10 seconds).

throws SolveException or HttpException when something goes wrong.

Core functions

uploadCaptcha :: (Failure HttpException m, MonadIO m) => ApiKey -> CaptchaConf -> FilePath -> ByteString -> Manager -> m (ApiResult CaptchaID)Source

upload captcha for recognition

throws HttpException on network errors.

checkCaptcha :: (Failure HttpException m, MonadIO m) => ApiKey -> CaptchaID -> Manager -> m (ApiResult String)Source

retrieve captcha status

throws HttpException on network errors.

checkCaptchas :: (Failure HttpException m, MonadIO m) => ApiKey -> [CaptchaID] -> Manager -> m [ApiResult String]Source

retrieve multiple captcha status

throws HttpException on network errors.

reportBad :: (Failure HttpException m, MonadIO m) => ApiKey -> CaptchaID -> Manager -> m BoolSource

report bad captcha result

throws HttpException on network errors.

getBalance :: (Failure HttpException m, MonadIO m) => ApiKey -> Manager -> m DoubleSource

retrieve your current account balance

throws HttpException on network errors.

Connection manager

data Manager

Keeps track of open connections for keep-alive.

If possible, you should share a single Manager between multiple threads and requests.

Since 0.1.0

newManager :: ManagerSettings -> IO Manager

Create a Manager. You may manually call closeManager to shut it down, or allow the Manager to be shut down automatically based on garbage collection.

Creating a new Manager is a relatively expensive operation, you are advised to share a single Manager between requests instead.

The first argument to this function is often defaultManagerSettings, though add-on libraries may provide a recommended replacement.

Since 0.1.0

closeManager :: Manager -> IO ()

Close all connections in a Manager.

Note that this doesn't affect currently in-flight connections, meaning you can safely use it without hurting any queries you may have concurrently running.

Since 0.1.0


parseUploadResponse :: String -> ApiResult CaptchaIDSource

Parse antigate's upload response

parseCheckResponse :: String -> ApiResult StringSource

Parse antigate's check response

parseMultiCheckResponse :: String -> ApiResult StringSource

Parse antigate's multi-check response

parseMultiCheckResponses :: String -> [ApiResult String]Source

Parse antigate's multi-check response

renderApiResult :: ApiResult String -> StringSource

Marshal ApiResult back to its text form