Skip to content

Commit

Permalink
1.2.0
Browse files Browse the repository at this point in the history
- Added Go implementation
  • Loading branch information
Matthew17-21 committed Oct 7, 2021
1 parent a76f33a commit d4d1288
Show file tree
Hide file tree
Showing 9 changed files with 706 additions and 0 deletions.
Binary file added .DS_Store
Binary file not shown.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# Captcha Tools
Python module to help solve captchas with Capmonster, 2Captcha and Anticaptcha API's!

#### Go(lang)
To see documentation for the Go implementation, [click here](https://github.com/Matthew17-21/Captcha-Tools/captchatools-go)

# Install
```python
pip3 install captchatools
Expand Down
152 changes: 152 additions & 0 deletions captchatools-go/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
# Captcha Tools (Go)
Go package to help solve captchas with Capmonster, 2Captcha and Anticaptcha API's!

# Install
```go
go get github.com/Matthew17-21/Captcha-Tools/captchatools-go
```
##### To update
```go
go get -u github.com/Matthew17-21/Captcha-Tools/captchatools-go
```

# How to use
```go
package main

import (
"fmt"

captchatools "github.com/Matthew17-21/Captcha-Tools/captchatools-go"
)

func main() {
solver, err := captchatools.NewHarvester(captchatools.CapmonsterSite, &captchatools.Config{
Api_key: "ENTER YOUR API KEY HERE",
Sitekey: "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-",
CaptchaURL: "https://www.google.com/recaptcha/api2/demo",
CaptchaType: "V2",
})
if err != nil {
panic(err)
}
fmt.Println(solver.GetToken())
}

```
V3 Captcha Exmaple:
```go
func v3Example() {
solver, err := captchatools.NewHarvester(captchatools.AnticaptchaSite, &captchatools.Config{
Api_key: "ENTER YOUR API KEY HERE",
Sitekey: "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-",
CaptchaURL: "..........",
CaptchaType: "V3",
Action: "submit",
MinScore: 0.9,
})
if err != nil {
panic(err)
}
fmt.Println(solver.GetToken())
}

```
### captchatools.NewHarvester() Parameters:
| Parameter | Required | Type | Default | Description|
| :-------------: |:-------------:| :-----:| :-----:| :-----:|
| solving_site | true | int| -| The captcha solving site that will be used. Refer to [the site IDs](https://github.com/Matthew17-21/Captcha-Tools/captchatools-go#site-specific-support). Alternatively, you can use shortcuts such as `captchatools.AnticaptchaSite` |
| Config| true | captchatools.Config | - | Configurations for the captchas you are solving. |


### Config struct fields:
| Field | Required | Type | Default | Description|
| :-------------: |:-------------:| :-----:| :-----:| :-----:|
| Api_key | true | String| -| The API Key for the captcha solving site|
| Sitekey| true | String | - | Sitekey from the site where captcha is loaded|
| CaptchaURL | true| String | - | URL where the captcha is located|
| CaptchaType| true| String | - | Type of captcha you are solving. Either captcha `v2`, `v3` or `hcaptcha` (`hcap` works aswell)|
| Action | false | String | - | Action that is associated with the V3 captcha.<br />__This param is only required when solving V3 captchas__|
| IsInvisibleCaptcha| false | bool | - | If the captcha is invisible or not.<br />__This param is only required when solving invisible captchas__|
| MinScore | false | float32 | - | Minimum score for v3 captchas.<br />__This param is only required when solving V3 and it needs a higher / lower score__|

<!-- | solving_site| true| String (name of site) or int (site ID) | "capmonster"| Captcha solving site| -->

# Supported Sites
- **[Capmonster](https://capmonster.cloud/)**
- **[2Captcha](https://www.2captcha.com/)**
- **[Anticaptcha](https://www.anti-captcha.com/)**

##### Site-Specific Support:
| Site |Site ID| Captcha Types Supported | Task Types Supported|
| :-------------: |:-------------:|:-------------:| :-----:|
| Capmonster |1| Recaptcha V2,<br />Recaptcha V3,<br />HCaptcha | RecaptchaV2TaskProxyless,<br />RecaptchaV3TaskProxyless,<br />HCaptchaTaskProxyless |
| Anticaptcha |2| Recaptcha V2,<br />Recaptcha V3,<br />HCaptcha | RecaptchaV2TaskProxyless,<br />RecaptchaV3TaskProxyless,<br />HCaptchaTaskProxyless |
| 2Captcha |3| Recaptcha V2,<br />Recaptcha V3,<br />HCaptcha | - |


# Recommendations
1. For 2Captcha, don't run more than 60 tasks per API key.
2. Handle errors appropriately.
* If a `ErrNoBalance` is thrown, tasks should stop. Some sites will temporarily ban IP's if constant requests come in.

# Errors
| Errors | Raised |
| :--------:| :-----:|
| `ErrNoBalance` | Balance is below 0 for captcha solving site|
| `ErrWrongAPIKey` | Incorrect API Key for captcha solving site|
| `ErrWrongSitekey` | Incorrect sitekey |
| `ErrIncorrectCapType` | Incorrectly chose a captcha type. When initializing a new harvester. Refer to [the captcha types](https://github.com/Matthew17-21/Captcha-Tools/captchatools-go#how-to-use) |
| `ErrNoHarvester` | When the user did not / incorrectly chose a captcha harvester. Refer to the [guide](https://github.com/Matthew17-21/Captcha-Tools/captchatools-go#how-to-use) |

```go
package main

import (
"fmt"

captchatools "github.com/Matthew17-21/Captcha-Tools/captchatools-go"
)

func main() {
solver, err := captchatools.NewHarvester(captchatools.AnticaptchaSite, &captchatools.Config{
Api_key: "ENTER YOUR API KEY HERE",
Sitekey: "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-",
CaptchaURL: "https://www.google.com/recaptcha/api2/demo",
CaptchaType: "V2",
})
if err != nil {
switch err {
case captchatools.ErrNoBalance:
fmt.Println("No balance.")
panic(err)
}
}
fmt.Println(solver.GetToken())
}

```


# TO DO
1. [] Document code better
2. [] 2Captcha
* [] Clean up code
* [] Proxy support
* [] Cookie support
* [] User Agent Support
* [] Different type of captchas
3. [] Anticaptcha
* [] Clean up code
* [] Proxy support
* [] Cookie support
* [] User Agent Support
* [] Different type of captchas
4. [] Capmonster
* [] Clean up code
* [] Proxy support
* [] Cookie support
* [] User Agent Support
* [] Different type of captchas
5. [] Add DeathByCaptcha
6. [] Allow for refunds
128 changes: 128 additions & 0 deletions captchatools-go/anticaptcha.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
package captchatoolsgo

import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"time"
)

// This file will contain the code to interact with anticaptcha.com API

func (t *Anticaptcha) GetToken() (string, error) {
return t.getCaptchaAnswer()
}

// Method to get Queue ID from the API.
func (t *Anticaptcha) getID() (int, error) {
// Get Payload
payload, _ := t.createPayload()

// Make request to get answer
response := &capmonsterIDResponse{}
for {
resp, err := http.Post("https://api.anti-captcha.com/createTask", "application/json", bytes.NewBuffer([]byte(payload)))
if err != nil {
time.Sleep(3 * time.Second)
continue
}
body, _ := ioutil.ReadAll(resp.Body)
resp.Body.Close()
json.Unmarshal(body, response)

// Parse the response
if response.ErrorID == 0 { // Means there was no error
return response.TaskID, nil
}
switch response.ErrorCode {
case "ERROR_ZERO_BALANCE":
return 0, ErrNoBalance
case "ERROR_RECAPTCHA_INVALID_SITEKEY":
return 0, ErrWrongSitekey
case "ERROR_KEY_DOES_NOT_EXIST":
return 0, ErrWrongAPIKey
}

}
}

// This method gets the captcha token from the Capmonster API
func (t *Anticaptcha) getCaptchaAnswer() (string, error) {
// Get Queue ID
queueID, err := t.getID()
if err != nil {
return "", err
}

// Get Captcha Answer
payload, _ := json.Marshal(capmonsterCapAnswerPayload{
ClientKey: t.config.Api_key,
TaskID: queueID,
})
response := &capmonsterTokenResponse{}
for {
resp, err := http.Post("https://api.anti-captcha.com/getTaskResult", "application/json", bytes.NewBuffer([]byte(payload)))
if err != nil {
time.Sleep(3 * time.Second)
continue
}

// Parse Response
body, _ := ioutil.ReadAll(resp.Body)
resp.Body.Close()
fmt.Println(string(body))
json.Unmarshal(body, response)
if response.Status == "ready" {
return response.Solution.GRecaptchaResponse, nil
} else if response.ErrorID == 12 || response.ErrorID == 16 { // Captcha unsolvable || TaskID doesn't exist
t.GetToken()
}
time.Sleep(3 * time.Second)
}
}

/*
createPayload returns the payloads required to interact with the API.
Possible errors that can be returned:
1) ErrIncorrectCapType
*/
func (t *Anticaptcha) createPayload() (string, error) {
// Define the payload we are going to send to the API
payload := capmonsterIDPayload{
ClientKey: t.config.Api_key,
Task: struct {
WebsiteURL string "json:\"websiteURL\""
WebsiteKey string "json:\"websiteKey\""
Type string "json:\"type\""
IsInvisible bool "json:\"isInvisible,omitempty\""
MinScore float32 "json:\"minScore,omitempty\""
PageAction string "json:\"pageAction,omitempty\""
}{
WebsiteURL: t.config.CaptchaURL,
WebsiteKey: t.config.Sitekey,
Type: t.config.CaptchaType,
},
}

// Add any other keys to the payload
switch t.config.CaptchaType {
case "v2":
payload.Task.Type = "NoCaptchaTaskProxyless"
if t.config.IsInvisibleCaptcha {
payload.Task.IsInvisible = t.config.IsInvisibleCaptcha
}
case "v3":
payload.Task.Type = "RecaptchaV3TaskProxyless"
payload.Task.MinScore = t.config.MinScore
payload.Task.PageAction = t.config.Action
case "hcaptcha", "hcap":
payload.Task.Type = "HCaptchaTaskProxyless"
default:
return "", ErrIncorrectCapType
}
encoded, _ := json.Marshal(payload)
return string(encoded), nil
}
Loading

0 comments on commit d4d1288

Please sign in to comment.