python3-capsolver 1.1.1__py3-none-any.whl → 1.2.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- python3_capsolver/__version__.py +1 -1
- python3_capsolver/core/aio_captcha_instrument.py +9 -2
- python3_capsolver/core/captcha_instrument.py +4 -1
- python3_capsolver/core/serializer.py +10 -4
- python3_capsolver/core/sio_captcha_instrument.py +9 -1
- python3_capsolver/image_to_text.py +6 -1
- {python3_capsolver-1.1.1.dist-info → python3_capsolver-1.2.1.dist-info}/METADATA +109 -8
- {python3_capsolver-1.1.1.dist-info → python3_capsolver-1.2.1.dist-info}/RECORD +11 -11
- {python3_capsolver-1.1.1.dist-info → python3_capsolver-1.2.1.dist-info}/WHEEL +1 -1
- {python3_capsolver-1.1.1.dist-info → python3_capsolver-1.2.1.dist-info}/licenses/LICENSE +0 -0
- {python3_capsolver-1.1.1.dist-info → python3_capsolver-1.2.1.dist-info}/top_level.txt +0 -0
python3_capsolver/__version__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "1.
|
|
1
|
+
__version__ = "1.2.1"
|
|
@@ -30,6 +30,8 @@ class AIOCaptchaInstrument(CaptchaInstrumentBase):
|
|
|
30
30
|
|
|
31
31
|
# if task created and already ready - return result
|
|
32
32
|
if self.created_task_data.errorId == 0:
|
|
33
|
+
if str(self.created_task_data.status).lower() == ResponseStatusEnm.Ready.value:
|
|
34
|
+
return self.created_task_data.to_dict()
|
|
33
35
|
return (await self.__get_result()).to_dict()
|
|
34
36
|
else:
|
|
35
37
|
self.created_task_data.status = ResponseStatusEnm.Failed
|
|
@@ -72,7 +74,10 @@ class AIOCaptchaInstrument(CaptchaInstrumentBase):
|
|
|
72
74
|
) as resp:
|
|
73
75
|
if resp.status in VALID_STATUS_CODES:
|
|
74
76
|
result_data = CaptchaResponseSer(**await resp.json())
|
|
75
|
-
if result_data.status in (
|
|
77
|
+
if result_data.status in (
|
|
78
|
+
ResponseStatusEnm.Ready,
|
|
79
|
+
ResponseStatusEnm.Failed,
|
|
80
|
+
):
|
|
76
81
|
# if captcha ready\failed or have unknown status - return exist data
|
|
77
82
|
return result_data
|
|
78
83
|
else:
|
|
@@ -90,10 +95,12 @@ class AIOCaptchaInstrument(CaptchaInstrumentBase):
|
|
|
90
95
|
self.result.errorDescription = self.CAPTCHA_UNSOLVABLE_DESCRIPTION
|
|
91
96
|
self.result.taskId = self.created_task_data.taskId
|
|
92
97
|
self.result.status = ResponseStatusEnm.Failed
|
|
98
|
+
return self.result
|
|
93
99
|
|
|
94
100
|
@staticmethod
|
|
95
101
|
async def send_post_request(
|
|
96
|
-
payload: Optional[dict] = None,
|
|
102
|
+
payload: Optional[dict] = None,
|
|
103
|
+
url_postfix: EndpointPostfixEnm = EndpointPostfixEnm.GET_BALANCE,
|
|
97
104
|
) -> dict:
|
|
98
105
|
"""
|
|
99
106
|
Function send ASYNC request to service and wait for result
|
|
@@ -83,7 +83,10 @@ class FileInstrument:
|
|
|
83
83
|
async for attempt in ASYNC_RETRIES:
|
|
84
84
|
with attempt:
|
|
85
85
|
async with session.get(url=url, **kwargs) as resp:
|
|
86
|
-
|
|
86
|
+
if resp.status == 200:
|
|
87
|
+
return await resp.content.read()
|
|
88
|
+
return b""
|
|
89
|
+
return b""
|
|
87
90
|
|
|
88
91
|
def file_processing(
|
|
89
92
|
self,
|
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
from enum import Enum
|
|
2
|
-
from typing import Any, Dict,
|
|
2
|
+
from typing import Any, Dict, Union, Optional
|
|
3
3
|
|
|
4
4
|
from msgspec import Struct
|
|
5
5
|
|
|
6
6
|
from .enum import ResponseStatusEnm
|
|
7
7
|
from .const import APP_ID
|
|
8
8
|
|
|
9
|
-
__all__ = (
|
|
9
|
+
__all__ = (
|
|
10
|
+
"PostRequestSer",
|
|
11
|
+
"TaskSer",
|
|
12
|
+
"RequestCreateTaskSer",
|
|
13
|
+
"CaptchaResponseSer",
|
|
14
|
+
"RequestGetTaskResultSer",
|
|
15
|
+
)
|
|
10
16
|
|
|
11
17
|
|
|
12
18
|
class MyBaseModel(Struct):
|
|
@@ -36,7 +42,7 @@ class TaskSer(MyBaseModel):
|
|
|
36
42
|
|
|
37
43
|
|
|
38
44
|
class RequestCreateTaskSer(PostRequestSer):
|
|
39
|
-
appId:
|
|
45
|
+
appId: str = APP_ID
|
|
40
46
|
|
|
41
47
|
|
|
42
48
|
class RequestGetTaskResultSer(MyBaseModel):
|
|
@@ -58,5 +64,5 @@ class ResponseSer(MyBaseModel):
|
|
|
58
64
|
|
|
59
65
|
class CaptchaResponseSer(ResponseSer):
|
|
60
66
|
taskId: Optional[str] = None
|
|
61
|
-
status: ResponseStatusEnm = ResponseStatusEnm.Processing
|
|
67
|
+
status: Union[ResponseStatusEnm, str] = ResponseStatusEnm.Processing
|
|
62
68
|
solution: Optional[Dict[str, Any]] = None
|
|
@@ -24,6 +24,7 @@ class SIOCaptchaInstrument(CaptchaInstrumentBase):
|
|
|
24
24
|
super().__init__()
|
|
25
25
|
self.captcha_params = captcha_params
|
|
26
26
|
self.created_task_data = CaptchaResponseSer
|
|
27
|
+
|
|
27
28
|
# prepare session
|
|
28
29
|
self.session = requests.Session()
|
|
29
30
|
self.session.mount("http://", HTTPAdapter(max_retries=RETRIES))
|
|
@@ -37,6 +38,8 @@ class SIOCaptchaInstrument(CaptchaInstrumentBase):
|
|
|
37
38
|
|
|
38
39
|
# if task created and ready - return result
|
|
39
40
|
if self.created_task_data.errorId == 0:
|
|
41
|
+
if str(self.created_task_data.status).lower() == ResponseStatusEnm.Ready.value:
|
|
42
|
+
return self.created_task_data.to_dict()
|
|
40
43
|
return self.__get_result().to_dict()
|
|
41
44
|
else:
|
|
42
45
|
self.created_task_data.status = ResponseStatusEnm.Failed
|
|
@@ -78,7 +81,10 @@ class SIOCaptchaInstrument(CaptchaInstrumentBase):
|
|
|
78
81
|
)
|
|
79
82
|
if resp.status_code in VALID_STATUS_CODES:
|
|
80
83
|
result_data = CaptchaResponseSer(**resp.json())
|
|
81
|
-
if result_data.status in (
|
|
84
|
+
if result_data.status in (
|
|
85
|
+
ResponseStatusEnm.Ready,
|
|
86
|
+
ResponseStatusEnm.Failed,
|
|
87
|
+
):
|
|
82
88
|
# if captcha ready\failed or have unknown status - return exist data
|
|
83
89
|
return result_data
|
|
84
90
|
else:
|
|
@@ -89,12 +95,14 @@ class SIOCaptchaInstrument(CaptchaInstrumentBase):
|
|
|
89
95
|
|
|
90
96
|
# if captcha just created or in processing now - wait
|
|
91
97
|
time.sleep(self.captcha_params.sleep_time)
|
|
98
|
+
|
|
92
99
|
# default response if server is silent
|
|
93
100
|
self.result.errorId = 1
|
|
94
101
|
self.result.errorCode = self.CAPTCHA_UNSOLVABLE
|
|
95
102
|
self.result.errorDescription = self.CAPTCHA_UNSOLVABLE_DESCRIPTION
|
|
96
103
|
self.result.taskId = self.created_task_data.taskId
|
|
97
104
|
self.result.status = ResponseStatusEnm.Failed
|
|
105
|
+
return self.result
|
|
98
106
|
|
|
99
107
|
@staticmethod
|
|
100
108
|
def send_post_request(
|
|
@@ -83,7 +83,12 @@ class ImageToText(CaptchaParams):
|
|
|
83
83
|
"""
|
|
84
84
|
|
|
85
85
|
def __init__(
|
|
86
|
-
self,
|
|
86
|
+
self,
|
|
87
|
+
api_key: str,
|
|
88
|
+
captcha_type: Union[CaptchaTypeEnm, str] = CaptchaTypeEnm.ImageToTextTask,
|
|
89
|
+
**kwargs,
|
|
87
90
|
):
|
|
91
|
+
if isinstance(captcha_type, str):
|
|
92
|
+
captcha_type = CaptchaTypeEnm(captcha_type)
|
|
88
93
|
|
|
89
94
|
super().__init__(api_key=api_key, captcha_type=captcha_type, **kwargs)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python3-capsolver
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.2.1
|
|
4
4
|
Summary: Python 3.8+ Capsolver library with AIO module.
|
|
5
5
|
Author-email: AndreiDrang <python-captcha@pm.me>
|
|
6
6
|
License: MIT License
|
|
@@ -30,7 +30,7 @@ Description-Content-Type: text/markdown
|
|
|
30
30
|
License-File: LICENSE
|
|
31
31
|
Requires-Dist: requests>=2.21.0
|
|
32
32
|
Requires-Dist: aiohttp>=3.9.2
|
|
33
|
-
Requires-Dist: msgspec
|
|
33
|
+
Requires-Dist: msgspec>=0.18
|
|
34
34
|
Requires-Dist: tenacity<10,>=8
|
|
35
35
|
Dynamic: license-file
|
|
36
36
|
|
|
@@ -61,11 +61,31 @@ Tested on UNIX based OS.
|
|
|
61
61
|
|
|
62
62
|
The library is intended for software developers and is used to work with the [Capsolver](https://dashboard.capsolver.com/passport/register?inviteCode=kQTn-tG07Jb1) service API.
|
|
63
63
|
|
|
64
|
+
## Features
|
|
65
|
+
- **Modern Tooling**: Uses `uv` for fast, reliable dependency management and environment isolation.
|
|
66
|
+
- **Sync & Async Support**: Full support for both synchronous (`requests`) and asynchronous (`aiohttp`) operations.
|
|
67
|
+
- **Type Safety**: Enums for captcha types and response statuses.
|
|
68
|
+
- **Resilience**: Built-in retries using `tenacity`.
|
|
69
|
+
- **Performance**: High-speed JSON serialization with `msgspec`.
|
|
70
|
+
- **Coverage**: Supports ReCaptcha (V2/V3), Cloudflare, DataDome, GeeTest, MtCaptcha, AWS WAF, Yandex, and ImageToText.
|
|
71
|
+
|
|
64
72
|
## How to install?
|
|
65
73
|
|
|
66
|
-
We recommend using the latest version of Python. `python3-capsolver` supports Python 3.
|
|
74
|
+
We recommend using the latest version of Python. `python3-capsolver` supports Python 3.8+.
|
|
75
|
+
|
|
76
|
+
### Development (using uv)
|
|
67
77
|
|
|
68
|
-
|
|
78
|
+
This project uses [uv](https://github.com/astral-sh/uv) for fast, reliable dependency management.
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
# Install uv (if not already installed)
|
|
82
|
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
83
|
+
|
|
84
|
+
# Install project dependencies
|
|
85
|
+
uv sync --all-groups
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Production (pip)
|
|
69
89
|
|
|
70
90
|
```bash
|
|
71
91
|
pip install python3-capsolver
|
|
@@ -73,18 +93,99 @@ pip install python3-capsolver
|
|
|
73
93
|
|
|
74
94
|
## How to use?
|
|
75
95
|
|
|
76
|
-
|
|
96
|
+
Detailed documentation is available on the [website](https://andreidrang.github.io/python3-capsolver/).
|
|
97
|
+
|
|
98
|
+
### Quick Start
|
|
99
|
+
|
|
100
|
+
#### Synchronous Example (ImageToText)
|
|
101
|
+
```python
|
|
102
|
+
from python3_capsolver.image_to_text import ImageToText
|
|
77
103
|
|
|
104
|
+
# 1. Initialize with API Key
|
|
105
|
+
solver = ImageToText(api_key="YOUR_API_KEY")
|
|
106
|
+
|
|
107
|
+
# 2. Solve
|
|
108
|
+
result = solver.captcha_handler(
|
|
109
|
+
task_payload={
|
|
110
|
+
"body": "base64_encoded_image_string"
|
|
111
|
+
}
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
# 3. Check result
|
|
115
|
+
if result["errorId"] == 0:
|
|
116
|
+
print("Solution:", result["solution"])
|
|
117
|
+
else:
|
|
118
|
+
print("Error:", result["errorCode"])
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
#### Asynchronous Example (ReCaptcha)
|
|
122
|
+
```python
|
|
123
|
+
import asyncio
|
|
124
|
+
from python3_capsolver.recaptcha import ReCaptcha
|
|
125
|
+
from python3_capsolver.core.enum import CaptchaTypeEnm
|
|
126
|
+
|
|
127
|
+
async def main():
|
|
128
|
+
# 1. Initialize
|
|
129
|
+
solver = ReCaptcha(
|
|
130
|
+
api_key="YOUR_API_KEY",
|
|
131
|
+
captcha_type=CaptchaTypeEnm.ReCaptchaV2TaskProxyLess
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
# 2. Solve
|
|
135
|
+
result = await solver.aio_captcha_handler(
|
|
136
|
+
task_payload={
|
|
137
|
+
"websiteURL": "https://example.com",
|
|
138
|
+
"websiteKey": "SITE_KEY"
|
|
139
|
+
}
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
print(result)
|
|
143
|
+
|
|
144
|
+
if __name__ == "__main__":
|
|
145
|
+
asyncio.run(main())
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## Supported Captcha Types
|
|
149
|
+
- **ReCaptcha**: V2 (Task/Enterprise), V3 (Task/Enterprise)
|
|
150
|
+
- **HCaptcha**: Task, Enterprise
|
|
151
|
+
- **Cloudflare**: Turnstile
|
|
152
|
+
- **GeeTest**: V3, V4
|
|
153
|
+
- **DataDome**: Slider
|
|
154
|
+
- **MtCaptcha**
|
|
155
|
+
- **AWS WAF**
|
|
156
|
+
- **Yandex SmartCaptcha**
|
|
157
|
+
- **ImageToText**: General image CAPTCHAs
|
|
158
|
+
|
|
159
|
+
## Documentation & Context (For LLMs)
|
|
160
|
+
- **Project Structure**: See `AGENTS.md` in root and subdirectories for internal architecture.
|
|
161
|
+
- **Entry Points**: `src/python3_capsolver/*.py` contains service-specific classes (e.g., `ReCaptcha`, `HCaptcha`).
|
|
162
|
+
- **Core Logic**: `src/python3_capsolver/core/base.py` handles the API communication loop.
|
|
163
|
+
- **Enums**: Use `python3_capsolver.core.enum` for type-safe parameters.
|
|
78
164
|
|
|
79
165
|
## How to test?
|
|
80
166
|
|
|
81
|
-
|
|
82
|
-
|
|
167
|
+
The project uses `uv` for testing and development tasks.
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
# 1. Set API_KEY in your environment (get this value from your account)
|
|
171
|
+
export API_KEY="your_api_key_here"
|
|
172
|
+
|
|
173
|
+
# 2. Run tests (uses uv internally)
|
|
174
|
+
make tests
|
|
175
|
+
|
|
176
|
+
# Other useful make targets:
|
|
177
|
+
# make install # Install dependencies with uv sync
|
|
178
|
+
# make lint # Run linting checks
|
|
179
|
+
# make build # Build the package
|
|
180
|
+
# make doc # Generate documentation
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
All `make` commands automatically use `uv` to run commands in the isolated environment.
|
|
83
184
|
|
|
84
185
|
|
|
85
186
|
### Changelog
|
|
86
187
|
|
|
87
|
-
|
|
188
|
+
See [CHANGELOG.md](https://github.com/AndreiDrang/python3-capsolver/blob/main/CHANGELOG.md) for version history and detailed changes.
|
|
88
189
|
|
|
89
190
|
### How to get API Key to work with the library
|
|
90
191
|
1. On the page - https://dashboard.capsolver.com/overview/user-center
|
|
@@ -1,28 +1,28 @@
|
|
|
1
1
|
python3_capsolver/__init__.py,sha256=141uoiYvgRblIWZAy7AhQJz6iVqzY4b5cLxExIaKUlg,62
|
|
2
|
-
python3_capsolver/__version__.py,sha256=
|
|
2
|
+
python3_capsolver/__version__.py,sha256=Mlm4Gvmb_6yQxwUbv2Ksc-BJFXLPg9H1Vt2iV7wXrA4,22
|
|
3
3
|
python3_capsolver/aws_waf.py,sha256=wwNjW2bkS-EdxEkTDxW9zwUGCnW_bbEhtruSgw_R94I,5677
|
|
4
4
|
python3_capsolver/cloudflare.py,sha256=SCuC4femAkNWY9taGELuGiGI8mDI5N2ziWAewNhAQrI,5367
|
|
5
5
|
python3_capsolver/control.py,sha256=TEhH2xGpJVX5QSiH3senhqoASnuJlDiFZfEZ1CLD1oA,16982
|
|
6
6
|
python3_capsolver/datadome_slider.py,sha256=kh15W30CQl-RgzcyCm_2ldluYAvbjyTl3mS9SFGj51k,2805
|
|
7
7
|
python3_capsolver/friendly_captcha.py,sha256=S1nenBwG3P2hiB-In13tWMNnITou68s8q-h3QXplubI,4412
|
|
8
8
|
python3_capsolver/gee_test.py,sha256=VjBOVggAkVRx6pGRys8kXl0-ZLFNCOMSYK_Bn95zk7o,2903
|
|
9
|
-
python3_capsolver/image_to_text.py,sha256=
|
|
9
|
+
python3_capsolver/image_to_text.py,sha256=lYEzENjEoKlBMFiyjGeLHgpczZaa184_X5MPommIOgs,3495
|
|
10
10
|
python3_capsolver/mt_captcha.py,sha256=mtHyqGat34odh_2KLBviEHMxnFi3SSSvRaVQAE1k0HA,2267
|
|
11
11
|
python3_capsolver/recaptcha.py,sha256=tiZPC_OGfhA30SH6lnqo2curVDLDwGwGLvx1zVn3gYY,3052
|
|
12
12
|
python3_capsolver/vision_engine.py,sha256=h82S6NvRbQTQUPTsLKQ1xpGMzlqHXaDGRRtDOSa275Q,2918
|
|
13
13
|
python3_capsolver/yandex.py,sha256=4NvopCD9pKVyUNLlQqj2Yra3n_YY0NG8Gqc5sVK9Yis,2770
|
|
14
14
|
python3_capsolver/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
15
|
-
python3_capsolver/core/aio_captcha_instrument.py,sha256=
|
|
15
|
+
python3_capsolver/core/aio_captcha_instrument.py,sha256=9LYx51KodjbDUZ0pcNxlSEW5KCqHQAiPfhCwF2J0PYE,4811
|
|
16
16
|
python3_capsolver/core/base.py,sha256=WScd52oKm28EE-yxOibYwlJRlaZH_q5sFzs8ynQwau0,3110
|
|
17
|
-
python3_capsolver/core/captcha_instrument.py,sha256=
|
|
17
|
+
python3_capsolver/core/captcha_instrument.py,sha256=Lg2fe0mpIre6z5Mb1LDvjHmbi-16BJ5zDS3_sJbMvXE,9262
|
|
18
18
|
python3_capsolver/core/const.py,sha256=AEU2IFQ6xbMRGdXzBNtZflxNFJ4VTshGx1skBtdrQ2w,613
|
|
19
19
|
python3_capsolver/core/context_instr.py,sha256=x3JQNd1ydlNdhuGKX_5gc-5Duq2pZJME0fs2YMQyGv4,503
|
|
20
20
|
python3_capsolver/core/enum.py,sha256=M4gfCzzkIMQ8JZd3qwFsA1iXW8cbfYFxJGTxiVvTUsE,2490
|
|
21
|
-
python3_capsolver/core/serializer.py,sha256=
|
|
22
|
-
python3_capsolver/core/sio_captcha_instrument.py,sha256=
|
|
21
|
+
python3_capsolver/core/serializer.py,sha256=048uf015XtPirdtdijDxpO8sg3xoDIFXucUwmHKLUMo,1363
|
|
22
|
+
python3_capsolver/core/sio_captcha_instrument.py,sha256=LZlcftx_L8IjB0xhH2dFdbd7No_l8ZDSS9aX02feWn8,4681
|
|
23
23
|
python3_capsolver/core/utils.py,sha256=5PMxryy22MIUmUXPIHqz38vg2C2bqa7uXHUNYRF8DlY,633
|
|
24
|
-
python3_capsolver-1.
|
|
25
|
-
python3_capsolver-1.
|
|
26
|
-
python3_capsolver-1.
|
|
27
|
-
python3_capsolver-1.
|
|
28
|
-
python3_capsolver-1.
|
|
24
|
+
python3_capsolver-1.2.1.dist-info/licenses/LICENSE,sha256=N_utAsqhTp1pXXp-PTE-CFMg5BfIIqTbF-phwwzOHeQ,1063
|
|
25
|
+
python3_capsolver-1.2.1.dist-info/METADATA,sha256=ljC80tlxqtijvJwzIu9x-fD3zQWBmHZhjJDaCz_IKqo,8400
|
|
26
|
+
python3_capsolver-1.2.1.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
|
|
27
|
+
python3_capsolver-1.2.1.dist-info/top_level.txt,sha256=yws7CqjoBfrn2ebCkAQmEaVlZ-zhbtflqpCDwAEX4kI,18
|
|
28
|
+
python3_capsolver-1.2.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|