Skip to content

Commit c7b4abd

Browse files
authored
Merge pull request #24 from Matthew17-21/hcap-rqdata
* Added hcaptcha rqdata support for Python and Go * Added Capsolver's `HCaptchaTurboTask` * Added build scripts for PyPi
2 parents 5be7772 + f4fd1fb commit c7b4abd

19 files changed

+188
-43
lines changed

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ captcha_answer = solver.get_token()
3232
| solving_site| true| String (name of site) or int (site ID) | "capmonster"| The captcha solving site that will be used. Refer to [the site IDs](https://github.com/Matthew17-21/Captcha-Tools/tree/main/captchatools-go#site-specific-support)|
3333
| sitekey| true | String | - | Sitekey from the site where captcha is loaded|
3434
| captcha_url | true| String | - | URL where the captcha is located|
35-
| captcha_type| false| String | "v2" | Type of captcha you are solving. Either captcha `image`, `v2`, `v3` or `hcaptcha` (`hcap` works aswell)|
35+
| captcha_type| false| String | "v2" | Type of captcha you are solving. Either captcha `image`, `v2`, `v3`,`hcaptcha` (`hcap` works aswell) or `hcaptchaturbo`|
3636
| invisible_captcha| false | bool | false | If the captcha is invisible or not.<br />__This param is only required when solving invisible captchas__|
3737
| min_score | false | double |0.7 | Minimum score for v3 captchas.<br />__This param is only required when solving V3 and it needs a higher / lower score__|
3838
| action | false | String | "verify" | Action that is associated with the V3 captcha.<br />__This param is only required when solving V3 captchas__|
@@ -44,6 +44,7 @@ captcha_answer = solver.get_token()
4444
| proxy| false | string | Proxy to be used to solve captchas.<br />This will make the captcha be solved from the proxy ip<br /><br />Format: `ip:port:user:pass` |
4545
| proxy_type | false | string | Type of the proxy being used. Options are:<br /> `HTTP`, `HTTPS`, `SOCKS4`, `SOCKS5`|
4646
| user_agent | false | string | UserAgent that will be passed to the service and used to solve the captcha |
47+
| rq_data | false | string | Custom data that is used in some implementations of hCaptcha. Most of the times, you want to set the `invisible_captcha` param to `true`.|
4748
### Examples
4849
##### Example - V2 Captcha / Basic usage
4950
```python
@@ -122,7 +123,7 @@ def main():
122123
| Capmonster | captchatools.CapmonsterSite| Image captchas,<br/> Recaptcha V2,<br />Recaptcha V3,<br />HCaptcha | ImageToTextTask,<br/>NoCaptchaTask,<br/> NoCaptchaTaskProxyless,<br/> RecaptchaV3TaskProxyless,<br />HCaptchaTaskProxyless |
123124
| Anticaptcha | captchatools.AnticaptchaSite| Image captchas,<br/> Recaptcha V2,<br />Recaptcha V3,<br />HCaptcha | ImageToTextTask,<br/> RecaptchaV2Task<br/> RecaptchaV2TaskProxyless,<br />RecaptchaV3TaskProxyless,<br />HCaptchaTaskProxyless |
124125
| 2Captcha | captchatools.TwoCaptchaSite| Image captchas,<br/> Recaptcha V2,<br />Recaptcha V3,<br />HCaptcha | - |
125-
| Capsolver | captchatools.CapsolverSite| Image captchas,<br/> Recaptcha V2,<br />Recaptcha V3,<br />HCaptcha | - |
126+
| Capsolver | captchatools.CapsolverSite| Image captchas,<br/> Recaptcha V2,<br />Recaptcha V3,<br />HCaptcha<br />HcaptchaTurbo | - |
126127
| CaptchaAI | captchatools.CaptchaAISite| Image captchas,<br/> Recaptcha V2,<br />Recaptcha V3,<br />HCaptcha | - |
127128

128129

captchatools-go/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ func main() {
9595
| Proxy| false | *Proxy | Proxy to be used to solve captchas.<br />This will make the captcha be solved from the proxy ip|
9696
| ProxyType | false | string | Type of the proxy being used. Options are:<br /> `HTTP`, `HTTPS`, `SOCKS4`, `SOCKS5`|
9797
| UserAgent | false | string | UserAgent that will be passed to the service and used to solve the captcha |
98+
| RQData | false | string | Custom data that is used in some implementations of hCaptcha. Most of the times, you want to set the `IsInvisibleCaptcha` param to `true`.|
9899
### Examples
99100
##### Example - V2 Captcha / Basic usage
100101
```go
@@ -269,6 +270,7 @@ func addtional_data() {
269270
| Recaptcha V2 | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
270271
| Recaptcha V3 | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
271272
| Hcaptcha | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
273+
| HcaptchaTurbo |:x: | :x: | :x: | :white_check_mark: | :x: |
272274
| Image Captcha | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
273275
| Cloudflare Turnstile | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: |
274276
| Funcaptcha |:x: | :x: | :x: | :x: | :x: |

captchatools-go/anticaptcha.go

Lines changed: 54 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -179,27 +179,43 @@ Possible errors that can be returned:
179179
1) ErrIncorrectCapType
180180
*/
181181
func (a Anticaptcha) createPayload(data *AdditionalData) (string, error) {
182+
type EnterprisePayload struct {
183+
Rqdata string `json:"rqdata,omitempty"`
184+
Sentry bool `json:"sentry,omitempty"`
185+
ApiEndpoint string `json:"apiEndpoint,omitempty"`
186+
Endpoint string `json:"endpoint,omitempty"`
187+
ReportAPI string `json:"reportapi,omitempty"`
188+
AssetHost string `json:"assethost,omitempty"`
189+
ImgHost string `json:"imghost,omitempty"`
190+
}
191+
type Task struct {
192+
Type captchaType `json:"type"`
193+
WebsiteURL string `json:"websiteURL"`
194+
WebsiteKey string `json:"websiteKey"`
195+
IsInvisible bool `json:"isInvisible,omitempty"`
196+
MinScore float32 `json:"minScore,omitempty"`
197+
PageAction string `json:"pageAction,omitempty"`
198+
Body string `json:"body,omitempty"`
199+
ProxyType string `json:"proxyType,omitempty"`
200+
ProxyAddress string `json:"proxyAddress,omitempty"`
201+
ProxyPort int `json:"proxyPort,omitempty"`
202+
ProxyLogin string `json:"proxyLogin,omitempty"`
203+
ProxyPassword string `json:"proxyPassword,omitempty"`
204+
UserAgent string `json:"userAgent,omitempty"`
205+
HcapEnterpriseData *EnterprisePayload `json:"enterprisePayload,omitempty"`
206+
}
207+
type Payload struct {
208+
ClientKey string `json:"clientKey"`
209+
Task Task `json:"task"`
210+
SoftID int `json:"softId,omitempty"`
211+
}
182212
// Define the payload we are going to send to the API
183-
payload := capmonsterIDPayload{
213+
payload := Payload{
184214
ClientKey: a.config.Api_key,
185-
Task: struct {
186-
WebsiteURL string "json:\"websiteURL\""
187-
WebsiteKey string "json:\"websiteKey\""
188-
Type captchaType "json:\"type\""
189-
IsInvisible bool "json:\"isInvisible,omitempty\""
190-
MinScore float32 "json:\"minScore,omitempty\""
191-
PageAction string "json:\"pageAction,omitempty\""
192-
Body string "json:\"body,omitempty\""
193-
ProxyType string "json:\"proxyType,omitempty\""
194-
ProxyAddress string "json:\"proxyAddress,omitempty\""
195-
ProxyPort int "json:\"proxyPort,omitempty\""
196-
ProxyLogin string "json:\"proxyLogin,omitempty\""
197-
ProxyPassword string "json:\"proxyPassword,omitempty\""
198-
UserAgent string "json:\"userAgent,omitempty\""
199-
}{
200-
WebsiteURL: a.config.CaptchaURL,
201-
WebsiteKey: a.config.Sitekey,
215+
Task: Task{
202216
Type: a.config.CaptchaType,
217+
WebsiteKey: a.config.Sitekey,
218+
WebsiteURL: a.config.CaptchaURL,
203219
},
204220
}
205221

@@ -255,6 +271,26 @@ func (a Anticaptcha) createPayload(data *AdditionalData) (string, error) {
255271
default:
256272
return "", ErrIncorrectCapType
257273
}
274+
275+
// Check for any additional data about the task
276+
if data != nil && a.config.CaptchaType != ImageCaptcha {
277+
if data.UserAgent != "" {
278+
payload.Task.UserAgent = data.UserAgent
279+
}
280+
if data.Proxy != nil {
281+
if port, err := strconv.Atoi(data.Proxy.Port); err == nil {
282+
payload.Task.ProxyAddress = data.Proxy.Ip
283+
payload.Task.ProxyPort = port
284+
payload.Task.ProxyLogin = data.Proxy.User
285+
payload.Task.ProxyPassword = data.Proxy.Password
286+
}
287+
}
288+
if data.RQData != "" {
289+
payload.Task.HcapEnterpriseData = &EnterprisePayload{
290+
Rqdata: data.RQData,
291+
}
292+
}
293+
}
258294
encoded, _ := json.Marshal(payload)
259295
return string(encoded), nil
260296
}

captchatools-go/capmonster.go

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ type capmonsterIDPayload struct {
3838
ProxyLogin string `json:"proxyLogin,omitempty"`
3939
ProxyPassword string `json:"proxyPassword,omitempty"`
4040
UserAgent string `json:"userAgent,omitempty"`
41+
RqData string `json:"data,omitempty"` // Custom data that is used in some implementations of hCaptcha, mostly with isInvisible=true. In most cases you see it as rqdata inside network requests.
4142
} `json:"task"`
4243
}
4344
type capmonsterCapAnswerPayload struct {
@@ -228,6 +229,7 @@ func (c Capmonster) createPayload(data *AdditionalData) (string, error) {
228229
ProxyLogin string "json:\"proxyLogin,omitempty\""
229230
ProxyPassword string "json:\"proxyPassword,omitempty\""
230231
UserAgent string "json:\"userAgent,omitempty\""
232+
RqData string "json:\"data,omitempty\""
231233
}{
232234
WebsiteURL: c.config.CaptchaURL,
233235
WebsiteKey: c.config.Sitekey,
@@ -281,8 +283,21 @@ func (c Capmonster) createPayload(data *AdditionalData) (string, error) {
281283
}
282284

283285
// Check for addtional data
284-
if data != nil && data.UserAgent != "" {
285-
payload.Task.UserAgent = data.UserAgent
286+
if data != nil && c.config.CaptchaType != ImageCaptcha {
287+
if data.UserAgent != "" {
288+
payload.Task.UserAgent = data.UserAgent
289+
}
290+
if data.Proxy != nil {
291+
if port, err := strconv.Atoi(data.Proxy.Port); err == nil {
292+
payload.Task.ProxyAddress = data.Proxy.Ip
293+
payload.Task.ProxyPort = port
294+
payload.Task.ProxyLogin = data.Proxy.User
295+
payload.Task.ProxyPassword = data.Proxy.Password
296+
}
297+
}
298+
if data.RQData != "" {
299+
payload.Task.RqData = data.RQData
300+
}
286301
}
287302

288303
encoded, _ := json.Marshal(payload)

captchatools-go/capsolver.go

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,14 +159,17 @@ func (c Capsolver) getCaptchaAnswer(ctx context.Context, additional ...*Addition
159159
solution,
160160
c.Api_key,
161161
c.CaptchaType,
162-
AnticaptchaSite, // TODO change this
162+
CapsolverSite,
163163
ua,
164164
), nil
165165
}
166166
return nil, ErrMaxAttempts
167167
}
168168

169169
func (c Capsolver) createPayload(data *AdditionalData) (string, error) {
170+
type EnterprisePayload struct {
171+
Rqdata string `json:"rqdata"`
172+
}
170173
type Task struct {
171174
Type captchaType `json:"type"`
172175
WebsiteURL string `json:"websiteURL"`
@@ -183,6 +186,9 @@ func (c Capsolver) createPayload(data *AdditionalData) (string, error) {
183186

184187
// Image Captcha data
185188
B64Image string `json:"body,omitempty"`
189+
190+
// Custom data that is used in some implementations of hCaptcha Enterprise.
191+
HcapEnterpriseData *EnterprisePayload `json:"enterprisePayload,omitempty"`
186192
}
187193
type Payload struct {
188194
ClientKey string `json:"clientKey"`
@@ -222,7 +228,8 @@ func (c Capsolver) createPayload(data *AdditionalData) (string, error) {
222228
if data != nil && data.Proxy != nil {
223229
p.Task.Type = "HCaptchaTurboTask"
224230
}
225-
231+
case HcaptchaTurbo:
232+
p.Task.Type = "HCaptchaTurboTask"
226233
}
227234

228235
// Check for any additional data about the task
@@ -233,6 +240,11 @@ func (c Capsolver) createPayload(data *AdditionalData) (string, error) {
233240
if data.Proxy != nil {
234241
p.Task.Proxy = data.Proxy.StringFormatted()
235242
}
243+
if data.RQData != "" {
244+
p.Task.HcapEnterpriseData = &EnterprisePayload{
245+
Rqdata: data.RQData,
246+
}
247+
}
236248
}
237249

238250
// TODO add softkey id

captchatools-go/captchaai.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,9 @@ func (t CaptchaAi) createUrl(data *AdditionalData) (string, error) {
213213
if data.ProxyType != "" {
214214
query.Add("proxytype", data.ProxyType)
215215
}
216+
if data.RQData != "" {
217+
query.Add("data", data.RQData)
218+
}
216219
}
217220

218221
u.RawQuery = query.Encode()

captchatools-go/common.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,12 @@ const (
1010
)
1111

1212
const (
13-
V2Captcha captchaType = "v2"
14-
V3Captcha captchaType = "v3"
15-
HCaptcha captchaType = "hcaptcha"
16-
ImageCaptcha captchaType = "image"
17-
CFTurnstile captchaType = "cfturnstile"
13+
V2Captcha captchaType = "v2"
14+
V3Captcha captchaType = "v3"
15+
HCaptcha captchaType = "hcaptcha"
16+
HcaptchaTurbo captchaType = "hcaptchaturbo"
17+
ImageCaptcha captchaType = "image"
18+
CFTurnstile captchaType = "cfturnstile"
1819
)
1920

2021
type (

captchatools-go/harvester.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ type AdditionalData struct {
4141
Proxy *Proxy // A proxy in correct formatting - such as user:pass@ip:port
4242
ProxyType string // Type of your proxy: HTTP, HTTPS, SOCKS4, SOCKS5
4343
UserAgent string // UserAgent that will be passed to the service and used to solve the captcha
44+
RQData string // Custom rqdata for hcaptcha
4445
}
4546

4647
// Configurations for the captchas you are solving.

captchatools-go/twocaptcha.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ type twoCapIDPayload struct {
3535
UserAgent string `json:"userAgent,omitempty"` // userAgent that will be used to solve the captcha
3636
Proxy string `json:"proxy,omitempty"` // Proxy to use to solve captchas from
3737
ProxyType string `json:"proxytype,omitempty"` // Type of the proxy
38+
RQData string `json:"data,omitempty"` // Custom rqdata. mostly with invisible=1
3839
}
3940

4041
// Type that will be used when getting a response from 2captcha
@@ -232,6 +233,9 @@ func (t Twocaptcha) createPayload(data *AdditionalData) (string, error) {
232233
if data.ProxyType != "" {
233234
payload.ProxyType = data.ProxyType
234235
}
236+
if data.RQData != "" {
237+
payload.RQData = data.RQData
238+
}
235239
}
236240

237241
encoded, _ := json.Marshal(payload)

captchatools/__init__.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ def __init__(self, **kwargs) -> None:
4646
raise captchaExceptions.WrongAPIKeyException()
4747
if self.solving_site is None:
4848
raise captchaExceptions.NoHarvesterException("No solving site selected")
49-
if self.captcha_type not in ["v2", "v3", "hcaptcha", "hcap", "image", "normal"]:
49+
if self.captcha_type not in ["v2", "v3", "hcaptcha", "hcap", "image", "normal", "hcaptchaturbo"]:
5050
raise captchaExceptions.NoCaptchaType("Invalid captcha type")
5151
if self.soft_id is None:
5252
if self.solving_site == 3 or self.solving_site == "2captcha":
@@ -63,7 +63,8 @@ def get_token(
6363
self, b64_img: Optional[str]=None,
6464
user_agent: Optional[str]=None,
6565
proxy: Optional[str]=None,
66-
proxy_type: Optional[str]=None
66+
proxy_type: Optional[str]=None,
67+
rq_data: Optional[str] = None
6768
):
6869
'''
6970
Returns a captcha token

captchatools/__init__.pyi

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ class Harvester(ABC):
2525
self, b64_img: Optional[str]=None,
2626
user_agent: Optional[str]=None,
2727
proxy: Optional[str]=None,
28-
proxy_type: Optional[str]=None
28+
proxy_type: Optional[str]=None,
29+
rq_data: Optional[str]=None
2930
): ...
3031

3132
def new_harvester(

captchatools/anticaptcha.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,21 @@ def get_balance(self) -> float:
1818
except requests.RequestException:
1919
pass
2020

21-
def get_token(self, b64_img: Optional[str] = None, user_agent: Optional[str] = None, proxy: Optional[str] = None, proxy_type: Optional[str] = "HTTP"):
21+
def get_token(
22+
self,
23+
b64_img: Optional[str] = None,
24+
user_agent: Optional[str] = None,
25+
proxy: Optional[str] = None,
26+
proxy_type: Optional[str] = "HTTP",
27+
rq_data: Optional[str] = None
28+
):
2229
# Get ID
2330
task_id = self.__get_id(
2431
b64_img=b64_img,
2532
user_agent=user_agent,
2633
proxy=proxy,
27-
proxy_type=proxy_type
34+
proxy_type=proxy_type,
35+
rq_data=rq_data
2836
)
2937

3038
# Get Answer
@@ -75,6 +83,8 @@ def __create_payload(self, **kwargs):
7583
payload["task"]["proxyPassword"] = splitted[3]
7684
if kwargs.get("user_agent", None) is not None:
7785
payload["task"]["userAgent"] = kwargs.get("user_agent")
86+
if kwargs.get("rq_data", None) is not None:
87+
payload["task"]["enterprisePayload"] ={"rqdata" :kwargs.get("rq_data")}
7888
return payload
7989

8090
def __get_id(self,**kwargs):

captchatools/capmonster.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,21 @@ def get_balance(self) -> float:
2323
except requests.RequestException:
2424
pass
2525

26-
def get_token(self, b64_img: Optional[str] = None, user_agent: Optional[str] = None, proxy: Optional[str] = None, proxy_type: Optional[str] = "HTTP"):
26+
def get_token(
27+
self,
28+
b64_img: Optional[str] = None,
29+
user_agent: Optional[str] = None,
30+
proxy: Optional[str] = None,
31+
proxy_type: Optional[str] = "HTTP",
32+
rq_data: Optional[str] = None
33+
):
2734
# Get ID
2835
task_id = self.__get_id(
2936
b64_img=b64_img,
3037
user_agent=user_agent,
3138
proxy=proxy,
32-
proxy_type=proxy_type
39+
proxy_type=proxy_type,
40+
rq_data=rq_data
3341
)
3442

3543
# Get Answer
@@ -80,6 +88,8 @@ def __create_payload(self, **kwargs):
8088
payload["task"]["proxyType"] = kwargs.get("proxy_type", "http")
8189
if kwargs.get("user_agent", None) is not None:
8290
payload["task"]["userAgent"] = kwargs.get("user_agent")
91+
if kwargs.get("rq_data", None) is not None:
92+
payload["task"]["data"] = kwargs.get("rq_data")
8393
return payload
8494

8595
def __get_id(self,**kwargs):

0 commit comments

Comments
 (0)