captcha-solver-api 1.0.1__tar.gz → 1.0.3__tar.gz
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.
- {captcha_solver_api-1.0.1 → captcha_solver_api-1.0.3}/PKG-INFO +64 -18
- {captcha_solver_api-1.0.1 → captcha_solver_api-1.0.3}/README.md +59 -17
- {captcha_solver_api-1.0.1 → captcha_solver_api-1.0.3}/captcha_solver_api/__init__.py +8 -8
- captcha_solver_api-1.0.3/captcha_solver_api/_version.py +1 -0
- {captcha_solver_api-1.0.1 → captcha_solver_api-1.0.3}/captcha_solver_api/async_client.py +11 -6
- {captcha_solver_api-1.0.1 → captcha_solver_api-1.0.3}/captcha_solver_api/client.py +11 -6
- {captcha_solver_api-1.0.1 → captcha_solver_api-1.0.3}/captcha_solver_api/exceptions.py +0 -8
- {captcha_solver_api-1.0.1 → captcha_solver_api-1.0.3}/captcha_solver_api/tasks.py +24 -15
- {captcha_solver_api-1.0.1 → captcha_solver_api-1.0.3}/captcha_solver_api.egg-info/PKG-INFO +64 -18
- {captcha_solver_api-1.0.1 → captcha_solver_api-1.0.3}/captcha_solver_api.egg-info/requires.txt +4 -0
- {captcha_solver_api-1.0.1 → captcha_solver_api-1.0.3}/pyproject.toml +35 -0
- {captcha_solver_api-1.0.1 → captcha_solver_api-1.0.3}/tests/test_polling.py +29 -27
- captcha_solver_api-1.0.1/captcha_solver_api/_version.py +0 -1
- {captcha_solver_api-1.0.1 → captcha_solver_api-1.0.3}/LICENSE.md +0 -0
- {captcha_solver_api-1.0.1 → captcha_solver_api-1.0.3}/captcha_solver_api/py.typed +0 -0
- {captcha_solver_api-1.0.1 → captcha_solver_api-1.0.3}/captcha_solver_api.egg-info/SOURCES.txt +0 -0
- {captcha_solver_api-1.0.1 → captcha_solver_api-1.0.3}/captcha_solver_api.egg-info/dependency_links.txt +0 -0
- {captcha_solver_api-1.0.1 → captcha_solver_api-1.0.3}/captcha_solver_api.egg-info/top_level.txt +0 -0
- {captcha_solver_api-1.0.1 → captcha_solver_api-1.0.3}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: captcha-solver-api
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.3
|
|
4
4
|
Summary: Official Python SDK for solving reCAPTCHA v2/v3, Cloudflare Turnstile, GeeTest v3/v4, Yandex SmartCaptcha, Tencent, and image/click captchas via the Captcha Solver API
|
|
5
5
|
Author: Captcha Solver Team
|
|
6
6
|
License-Expression: MIT
|
|
@@ -32,11 +32,27 @@ Requires-Dist: pytest>=7; extra == "dev"
|
|
|
32
32
|
Requires-Dist: pytest-asyncio>=0.21; extra == "dev"
|
|
33
33
|
Requires-Dist: pytest-mock>=3; extra == "dev"
|
|
34
34
|
Requires-Dist: python-dotenv>=1.0; extra == "dev"
|
|
35
|
+
Requires-Dist: ruff>=0.6; extra == "dev"
|
|
36
|
+
Requires-Dist: mypy>=1.10; extra == "dev"
|
|
37
|
+
Requires-Dist: types-requests>=2.28; extra == "dev"
|
|
38
|
+
Requires-Dist: pytest-cov>=4; extra == "dev"
|
|
35
39
|
Dynamic: license-file
|
|
36
40
|
|
|
37
41
|
# Captcha Solver Python SDK
|
|
38
42
|
|
|
39
|
-

|
|
43
|
+

|
|
44
|
+
|
|
45
|
+
[](https://pypi.org/project/captcha-solver-api/)
|
|
46
|
+
[](https://pypi.org/project/captcha-solver-api/)
|
|
47
|
+
[](https://pepy.tech/project/captcha-solver-api)
|
|
48
|
+
[](https://github.com/captcha-solver-api/python-sdk/actions/workflows/tests.yml)
|
|
49
|
+
[](https://github.com/captcha-solver-api/python-sdk/actions/workflows/tests.yml)
|
|
50
|
+
[](https://github.com/captcha-solver-api/python-sdk/blob/main/captcha_solver_api/py.typed)
|
|
51
|
+
[](https://github.com/captcha-solver-api/python-sdk/blob/main/LICENSE.md)
|
|
52
|
+
[](https://github.com/astral-sh/ruff)
|
|
53
|
+
[](https://mypy-lang.org/)
|
|
54
|
+
[](https://github.com/captcha-solver-api/python-sdk/releases)
|
|
55
|
+
[](https://github.com/captcha-solver-api/javascript-sdk)
|
|
40
56
|
|
|
41
57
|
Official Python SDK for the Captcha Solver API. Solve reCAPTCHA v2/v3, Cloudflare Turnstile, GeeTest, Yandex SmartCaptcha, Tencent, and image/click captchas with a single method call -- sync or async.
|
|
42
58
|
|
|
@@ -47,6 +63,7 @@ Full API reference (all endpoints, error codes, captcha-type details): **https:/
|
|
|
47
63
|
- [Installation](#installation)
|
|
48
64
|
- [Configuration](#configuration)
|
|
49
65
|
- [Quick Start](#quick-start)
|
|
66
|
+
- [Build Faster with AI](#build-faster-with-ai)
|
|
50
67
|
- [Supported CAPTCHA Types](#supported-captcha-types)
|
|
51
68
|
- [Client Reference](#client-reference)
|
|
52
69
|
- [CaptchaClient(...)](#captchaclient)
|
|
@@ -74,6 +91,7 @@ Full API reference (all endpoints, error codes, captcha-type details): **https:/
|
|
|
74
91
|
- [Running the examples](#running-the-examples)
|
|
75
92
|
- [Requirements](#requirements)
|
|
76
93
|
- [API Documentation](#api-documentation)
|
|
94
|
+
- [Useful Links](#useful-links)
|
|
77
95
|
- [License](#license)
|
|
78
96
|
|
|
79
97
|
## Installation
|
|
@@ -124,6 +142,23 @@ result = client.solve(task)
|
|
|
124
142
|
print(result["gRecaptchaResponse"])
|
|
125
143
|
```
|
|
126
144
|
|
|
145
|
+
## Build Faster with AI
|
|
146
|
+
|
|
147
|
+
Use our [`llms.txt`](https://captcha-solver.com/llms.txt) as context when asking an
|
|
148
|
+
AI assistant to build or update your integration. It contains the current API
|
|
149
|
+
format, supported task parameters, SDK installation instructions, solution
|
|
150
|
+
fields, and error codes in one file.
|
|
151
|
+
|
|
152
|
+
Copy this prompt and add a description of the page and CAPTCHA you need to
|
|
153
|
+
handle:
|
|
154
|
+
|
|
155
|
+
```text
|
|
156
|
+
Read https://captcha-solver.com/llms.txt and use the Captcha Solver Python SDK.
|
|
157
|
+
Write a complete integration for this task: [describe your task here].
|
|
158
|
+
Use the documented task parameters and show how to apply the returned solution
|
|
159
|
+
on the target page.
|
|
160
|
+
```
|
|
161
|
+
|
|
127
162
|
## Supported CAPTCHA Types
|
|
128
163
|
|
|
129
164
|
| Type | Proxyless | With Proxy |
|
|
@@ -157,7 +192,7 @@ Constructor.
|
|
|
157
192
|
| `client_key` | `str` | required | Your Captcha Solver API key. Raises `ValidationError` if empty. |
|
|
158
193
|
| `base_url` | `str` | `https://api.captcha-solver.com` | API base URL. Override only for self-hosted/staging deployments. |
|
|
159
194
|
| `timeout` | `int` | `120` | Polling window after task creation, in seconds. Overridable per call; each HTTP request has a separate 30-second timeout. |
|
|
160
|
-
| `polling_interval` | `int` | `10` | Seconds before the first `getTaskResult` poll and between subsequent polls
|
|
195
|
+
| `polling_interval` | `int` | `10` | Seconds before the first `getTaskResult` poll and between subsequent polls. |
|
|
161
196
|
| `language_pool` | `Optional[str]` | `None` | Default worker pool (`"en"` or `"ru"`) applied to every call that doesn't pass its own `language_pool`. |
|
|
162
197
|
|
|
163
198
|
Both clients hold a reusable connection pool (`requests.Session` / `httpx.AsyncClient`)
|
|
@@ -353,12 +388,13 @@ that the target page expects in `cf-turnstile-response`.
|
|
|
353
388
|
| `action` | no | Value of the widget's `data-action` attribute, if set. |
|
|
354
389
|
| `data` | no | Custom payload from the widget's `data-cdata` attribute, if set. |
|
|
355
390
|
| `pagedata` | no | Value of the `chlPageData` parameter, needed for some Cloudflare challenge pages beyond the basic widget. |
|
|
356
|
-
| `userAgent` | no | User-Agent
|
|
391
|
+
| `userAgent` | no | Current browser User-Agent. Pass it for Cloudflare Challenge pages; it is not needed for a standalone widget. |
|
|
357
392
|
|
|
358
393
|
**Response:** `token` -- submit as `cf-turnstile-response`. For Cloudflare
|
|
359
|
-
Challenge pages,
|
|
360
|
-
|
|
361
|
-
|
|
394
|
+
Challenge pages, pass `action`, `data`, `pagedata`, and the current browser
|
|
395
|
+
`userAgent` in the task. The solution also contains `userAgent`; switch the
|
|
396
|
+
browser or HTTP client to this returned value before invoking the callback with
|
|
397
|
+
the token. The API field is spelled `pagedata`, all lowercase.
|
|
362
398
|
|
|
363
399
|
```python
|
|
364
400
|
from captcha_solver_api import CaptchaClient
|
|
@@ -366,10 +402,15 @@ from captcha_solver_api.tasks import TurnstileTaskProxyless
|
|
|
366
402
|
client = CaptchaClient("your_api_key")
|
|
367
403
|
task = TurnstileTaskProxyless(
|
|
368
404
|
websiteURL="https://example.com/login",
|
|
369
|
-
websiteKey="YOUR_WEBSITE_KEY"
|
|
405
|
+
websiteKey="YOUR_WEBSITE_KEY",
|
|
406
|
+
action="managed",
|
|
407
|
+
data="INTERCEPTED_CDATA",
|
|
408
|
+
pagedata="INTERCEPTED_CHL_PAGE_DATA",
|
|
409
|
+
userAgent="CURRENT_BROWSER_USER_AGENT",
|
|
370
410
|
)
|
|
371
411
|
result = client.solve(task)
|
|
372
412
|
print(result["token"])
|
|
413
|
+
print(result.get("userAgent"))
|
|
373
414
|
```
|
|
374
415
|
|
|
375
416
|
With proxy, use `TurnstileTask` (same proxy fields as reCAPTCHA v2).
|
|
@@ -476,7 +517,7 @@ for the widget on the target page. Use the coordinates method for image challeng
|
|
|
476
517
|
|
|
477
518
|
`YandexSmartCaptchaTaskProxyless` / `YandexSmartCaptchaTask` -- token-based
|
|
478
519
|
challenge. For the image challenge instead, use `CoordinatesTask` with
|
|
479
|
-
|
|
520
|
+
[Coordinates](#coordinates-click-captcha) is available for generic click captchas.
|
|
480
521
|
|
|
481
522
|
| Parameter | Required | Description |
|
|
482
523
|
|---|---|---|
|
|
@@ -519,10 +560,9 @@ SmartCaptcha's image challenge. No proxy variant -- the image is submitted direc
|
|
|
519
560
|
|---|---|---|
|
|
520
561
|
| `body` | yes | The captcha image, base64-encoded. |
|
|
521
562
|
| `comment` | no (recommended) | Hint for the worker, e.g. `"click on the green apple"`. |
|
|
522
|
-
| `imgInstructions` |
|
|
563
|
+
| `imgInstructions` | no | Optional instruction image, base64-encoded. |
|
|
523
564
|
| `minClicks` | no | Minimum number of clicks expected (default `1`). |
|
|
524
565
|
| `maxClicks` | no | Maximum number of clicks allowed. |
|
|
525
|
-
| `imgType` | no | `"smart_captcha"` to solve a Yandex SmartCaptcha image challenge instead of a generic click captcha. |
|
|
526
566
|
|
|
527
567
|
**Response:** `coordinates` -- a list of `{"x": int, "y": int}` pixel positions to click, in order.
|
|
528
568
|
|
|
@@ -540,9 +580,6 @@ task = CoordinatesTask(
|
|
|
540
580
|
result = client.solve(task)
|
|
541
581
|
print(result["coordinates"]) # [{"x": 140, "y": 110}]
|
|
542
582
|
```
|
|
543
|
-
For the Yandex SmartCaptcha image challenge, see
|
|
544
|
-
[examples/sync/yandex_smartcaptcha_image.py](https://github.com/captcha-solver-api/python-sdk/blob/main/examples/sync/yandex_smartcaptcha_image.py)
|
|
545
|
-
(or [examples/async](https://github.com/captcha-solver-api/python-sdk/blob/main/examples/async/yandex_smartcaptcha_image.py)).
|
|
546
583
|
|
|
547
584
|
### Tencent
|
|
548
585
|
|
|
@@ -604,8 +641,8 @@ result = client.solve(task, timeout=300)
|
|
|
604
641
|
```
|
|
605
642
|
|
|
606
643
|
The [API requires at least 5 seconds between polls](https://captcha-solver.com/en/docs/how-it-works).
|
|
607
|
-
The SDK defaults to 10 seconds
|
|
608
|
-
|
|
644
|
+
The SDK defaults to 10 seconds. `solve()` waits for `polling_interval` before
|
|
645
|
+
its first poll and between polls.
|
|
609
646
|
Its default 120-second polling window is independent of the API's five-minute
|
|
610
647
|
task lifetime. A local timeout does not cancel a task or mean that the API
|
|
611
648
|
failed to solve it. Use `create_task()` and keep its `task_id` if you need to
|
|
@@ -695,8 +732,7 @@ Avoid importing it by name: it shadows Python's built-in `TimeoutError`.
|
|
|
695
732
|
See the dedicated [examples documentation](https://github.com/captcha-solver-api/python-sdk/blob/main/examples/README.md) for the full
|
|
696
733
|
sync/async example list, setup steps, expected results, and placeholder guidance.
|
|
697
734
|
|
|
698
|
-
- **Image/click captchas** (`image_to_text.py`, `coordinates.py
|
|
699
|
-
`yandex_smartcaptcha_image.py`) run after installing the dependencies and setting a valid
|
|
735
|
+
- **Image/click captchas** (`image_to_text.py`, `coordinates.py`) run after installing the dependencies and setting a valid
|
|
700
736
|
`CAPTCHA_API_KEY` -- they read sample images bundled in
|
|
701
737
|
[examples/assets](https://github.com/captcha-solver-api/python-sdk/tree/main/examples/assets), no target page needed.
|
|
702
738
|
`python-dotenv` is optional: install it only if you want the scripts to load a `.env` file.
|
|
@@ -738,6 +774,16 @@ page and session parameters.
|
|
|
738
774
|
|
|
739
775
|
Full API reference: https://captcha-solver.com/en/docs/captcha-types
|
|
740
776
|
|
|
777
|
+
## Useful Links
|
|
778
|
+
|
|
779
|
+
- [JavaScript SDK](https://github.com/captcha-solver-api/javascript-sdk)
|
|
780
|
+
- [Python examples](https://github.com/captcha-solver-api/python-examples)
|
|
781
|
+
- [Selenium Python examples](https://github.com/captcha-solver-api/captcha-solver-selenium-python-examples)
|
|
782
|
+
- [JavaScript examples](https://github.com/captcha-solver-api/javascript-examples)
|
|
783
|
+
- [Tencent CAPTCHA automation examples](https://github.com/captcha-solver-api/How-to-Automate-Tencent-CAPTCHA)
|
|
784
|
+
- [Cloudflare Turnstile Puppeteer Demo](https://github.com/captcha-solver-api/cloudflare-turnstile-puppeteer-demo) — a working browser automation example for Cloudflare Turnstile.
|
|
785
|
+
- [How to Automate Tencent CAPTCHA](https://captcha-solver.com/en/blog/how-to-automate-tencent-captcha) — a step-by-step guide with Python and JavaScript SDK examples.
|
|
786
|
+
|
|
741
787
|
## License
|
|
742
788
|
|
|
743
789
|
This project is licensed under the MIT License. See [LICENSE.md](https://github.com/captcha-solver-api/python-sdk/blob/main/LICENSE.md) for details.
|
|
@@ -1,6 +1,18 @@
|
|
|
1
1
|
# Captcha Solver Python SDK
|
|
2
2
|
|
|
3
|
-

|
|
3
|
+

|
|
4
|
+
|
|
5
|
+
[](https://pypi.org/project/captcha-solver-api/)
|
|
6
|
+
[](https://pypi.org/project/captcha-solver-api/)
|
|
7
|
+
[](https://pepy.tech/project/captcha-solver-api)
|
|
8
|
+
[](https://github.com/captcha-solver-api/python-sdk/actions/workflows/tests.yml)
|
|
9
|
+
[](https://github.com/captcha-solver-api/python-sdk/actions/workflows/tests.yml)
|
|
10
|
+
[](https://github.com/captcha-solver-api/python-sdk/blob/main/captcha_solver_api/py.typed)
|
|
11
|
+
[](https://github.com/captcha-solver-api/python-sdk/blob/main/LICENSE.md)
|
|
12
|
+
[](https://github.com/astral-sh/ruff)
|
|
13
|
+
[](https://mypy-lang.org/)
|
|
14
|
+
[](https://github.com/captcha-solver-api/python-sdk/releases)
|
|
15
|
+
[](https://github.com/captcha-solver-api/javascript-sdk)
|
|
4
16
|
|
|
5
17
|
Official Python SDK for the Captcha Solver API. Solve reCAPTCHA v2/v3, Cloudflare Turnstile, GeeTest, Yandex SmartCaptcha, Tencent, and image/click captchas with a single method call -- sync or async.
|
|
6
18
|
|
|
@@ -11,6 +23,7 @@ Full API reference (all endpoints, error codes, captcha-type details): **https:/
|
|
|
11
23
|
- [Installation](#installation)
|
|
12
24
|
- [Configuration](#configuration)
|
|
13
25
|
- [Quick Start](#quick-start)
|
|
26
|
+
- [Build Faster with AI](#build-faster-with-ai)
|
|
14
27
|
- [Supported CAPTCHA Types](#supported-captcha-types)
|
|
15
28
|
- [Client Reference](#client-reference)
|
|
16
29
|
- [CaptchaClient(...)](#captchaclient)
|
|
@@ -38,6 +51,7 @@ Full API reference (all endpoints, error codes, captcha-type details): **https:/
|
|
|
38
51
|
- [Running the examples](#running-the-examples)
|
|
39
52
|
- [Requirements](#requirements)
|
|
40
53
|
- [API Documentation](#api-documentation)
|
|
54
|
+
- [Useful Links](#useful-links)
|
|
41
55
|
- [License](#license)
|
|
42
56
|
|
|
43
57
|
## Installation
|
|
@@ -88,6 +102,23 @@ result = client.solve(task)
|
|
|
88
102
|
print(result["gRecaptchaResponse"])
|
|
89
103
|
```
|
|
90
104
|
|
|
105
|
+
## Build Faster with AI
|
|
106
|
+
|
|
107
|
+
Use our [`llms.txt`](https://captcha-solver.com/llms.txt) as context when asking an
|
|
108
|
+
AI assistant to build or update your integration. It contains the current API
|
|
109
|
+
format, supported task parameters, SDK installation instructions, solution
|
|
110
|
+
fields, and error codes in one file.
|
|
111
|
+
|
|
112
|
+
Copy this prompt and add a description of the page and CAPTCHA you need to
|
|
113
|
+
handle:
|
|
114
|
+
|
|
115
|
+
```text
|
|
116
|
+
Read https://captcha-solver.com/llms.txt and use the Captcha Solver Python SDK.
|
|
117
|
+
Write a complete integration for this task: [describe your task here].
|
|
118
|
+
Use the documented task parameters and show how to apply the returned solution
|
|
119
|
+
on the target page.
|
|
120
|
+
```
|
|
121
|
+
|
|
91
122
|
## Supported CAPTCHA Types
|
|
92
123
|
|
|
93
124
|
| Type | Proxyless | With Proxy |
|
|
@@ -121,7 +152,7 @@ Constructor.
|
|
|
121
152
|
| `client_key` | `str` | required | Your Captcha Solver API key. Raises `ValidationError` if empty. |
|
|
122
153
|
| `base_url` | `str` | `https://api.captcha-solver.com` | API base URL. Override only for self-hosted/staging deployments. |
|
|
123
154
|
| `timeout` | `int` | `120` | Polling window after task creation, in seconds. Overridable per call; each HTTP request has a separate 30-second timeout. |
|
|
124
|
-
| `polling_interval` | `int` | `10` | Seconds before the first `getTaskResult` poll and between subsequent polls
|
|
155
|
+
| `polling_interval` | `int` | `10` | Seconds before the first `getTaskResult` poll and between subsequent polls. |
|
|
125
156
|
| `language_pool` | `Optional[str]` | `None` | Default worker pool (`"en"` or `"ru"`) applied to every call that doesn't pass its own `language_pool`. |
|
|
126
157
|
|
|
127
158
|
Both clients hold a reusable connection pool (`requests.Session` / `httpx.AsyncClient`)
|
|
@@ -317,12 +348,13 @@ that the target page expects in `cf-turnstile-response`.
|
|
|
317
348
|
| `action` | no | Value of the widget's `data-action` attribute, if set. |
|
|
318
349
|
| `data` | no | Custom payload from the widget's `data-cdata` attribute, if set. |
|
|
319
350
|
| `pagedata` | no | Value of the `chlPageData` parameter, needed for some Cloudflare challenge pages beyond the basic widget. |
|
|
320
|
-
| `userAgent` | no | User-Agent
|
|
351
|
+
| `userAgent` | no | Current browser User-Agent. Pass it for Cloudflare Challenge pages; it is not needed for a standalone widget. |
|
|
321
352
|
|
|
322
353
|
**Response:** `token` -- submit as `cf-turnstile-response`. For Cloudflare
|
|
323
|
-
Challenge pages,
|
|
324
|
-
|
|
325
|
-
|
|
354
|
+
Challenge pages, pass `action`, `data`, `pagedata`, and the current browser
|
|
355
|
+
`userAgent` in the task. The solution also contains `userAgent`; switch the
|
|
356
|
+
browser or HTTP client to this returned value before invoking the callback with
|
|
357
|
+
the token. The API field is spelled `pagedata`, all lowercase.
|
|
326
358
|
|
|
327
359
|
```python
|
|
328
360
|
from captcha_solver_api import CaptchaClient
|
|
@@ -330,10 +362,15 @@ from captcha_solver_api.tasks import TurnstileTaskProxyless
|
|
|
330
362
|
client = CaptchaClient("your_api_key")
|
|
331
363
|
task = TurnstileTaskProxyless(
|
|
332
364
|
websiteURL="https://example.com/login",
|
|
333
|
-
websiteKey="YOUR_WEBSITE_KEY"
|
|
365
|
+
websiteKey="YOUR_WEBSITE_KEY",
|
|
366
|
+
action="managed",
|
|
367
|
+
data="INTERCEPTED_CDATA",
|
|
368
|
+
pagedata="INTERCEPTED_CHL_PAGE_DATA",
|
|
369
|
+
userAgent="CURRENT_BROWSER_USER_AGENT",
|
|
334
370
|
)
|
|
335
371
|
result = client.solve(task)
|
|
336
372
|
print(result["token"])
|
|
373
|
+
print(result.get("userAgent"))
|
|
337
374
|
```
|
|
338
375
|
|
|
339
376
|
With proxy, use `TurnstileTask` (same proxy fields as reCAPTCHA v2).
|
|
@@ -440,7 +477,7 @@ for the widget on the target page. Use the coordinates method for image challeng
|
|
|
440
477
|
|
|
441
478
|
`YandexSmartCaptchaTaskProxyless` / `YandexSmartCaptchaTask` -- token-based
|
|
442
479
|
challenge. For the image challenge instead, use `CoordinatesTask` with
|
|
443
|
-
|
|
480
|
+
[Coordinates](#coordinates-click-captcha) is available for generic click captchas.
|
|
444
481
|
|
|
445
482
|
| Parameter | Required | Description |
|
|
446
483
|
|---|---|---|
|
|
@@ -483,10 +520,9 @@ SmartCaptcha's image challenge. No proxy variant -- the image is submitted direc
|
|
|
483
520
|
|---|---|---|
|
|
484
521
|
| `body` | yes | The captcha image, base64-encoded. |
|
|
485
522
|
| `comment` | no (recommended) | Hint for the worker, e.g. `"click on the green apple"`. |
|
|
486
|
-
| `imgInstructions` |
|
|
523
|
+
| `imgInstructions` | no | Optional instruction image, base64-encoded. |
|
|
487
524
|
| `minClicks` | no | Minimum number of clicks expected (default `1`). |
|
|
488
525
|
| `maxClicks` | no | Maximum number of clicks allowed. |
|
|
489
|
-
| `imgType` | no | `"smart_captcha"` to solve a Yandex SmartCaptcha image challenge instead of a generic click captcha. |
|
|
490
526
|
|
|
491
527
|
**Response:** `coordinates` -- a list of `{"x": int, "y": int}` pixel positions to click, in order.
|
|
492
528
|
|
|
@@ -504,9 +540,6 @@ task = CoordinatesTask(
|
|
|
504
540
|
result = client.solve(task)
|
|
505
541
|
print(result["coordinates"]) # [{"x": 140, "y": 110}]
|
|
506
542
|
```
|
|
507
|
-
For the Yandex SmartCaptcha image challenge, see
|
|
508
|
-
[examples/sync/yandex_smartcaptcha_image.py](https://github.com/captcha-solver-api/python-sdk/blob/main/examples/sync/yandex_smartcaptcha_image.py)
|
|
509
|
-
(or [examples/async](https://github.com/captcha-solver-api/python-sdk/blob/main/examples/async/yandex_smartcaptcha_image.py)).
|
|
510
543
|
|
|
511
544
|
### Tencent
|
|
512
545
|
|
|
@@ -568,8 +601,8 @@ result = client.solve(task, timeout=300)
|
|
|
568
601
|
```
|
|
569
602
|
|
|
570
603
|
The [API requires at least 5 seconds between polls](https://captcha-solver.com/en/docs/how-it-works).
|
|
571
|
-
The SDK defaults to 10 seconds
|
|
572
|
-
|
|
604
|
+
The SDK defaults to 10 seconds. `solve()` waits for `polling_interval` before
|
|
605
|
+
its first poll and between polls.
|
|
573
606
|
Its default 120-second polling window is independent of the API's five-minute
|
|
574
607
|
task lifetime. A local timeout does not cancel a task or mean that the API
|
|
575
608
|
failed to solve it. Use `create_task()` and keep its `task_id` if you need to
|
|
@@ -659,8 +692,7 @@ Avoid importing it by name: it shadows Python's built-in `TimeoutError`.
|
|
|
659
692
|
See the dedicated [examples documentation](https://github.com/captcha-solver-api/python-sdk/blob/main/examples/README.md) for the full
|
|
660
693
|
sync/async example list, setup steps, expected results, and placeholder guidance.
|
|
661
694
|
|
|
662
|
-
- **Image/click captchas** (`image_to_text.py`, `coordinates.py
|
|
663
|
-
`yandex_smartcaptcha_image.py`) run after installing the dependencies and setting a valid
|
|
695
|
+
- **Image/click captchas** (`image_to_text.py`, `coordinates.py`) run after installing the dependencies and setting a valid
|
|
664
696
|
`CAPTCHA_API_KEY` -- they read sample images bundled in
|
|
665
697
|
[examples/assets](https://github.com/captcha-solver-api/python-sdk/tree/main/examples/assets), no target page needed.
|
|
666
698
|
`python-dotenv` is optional: install it only if you want the scripts to load a `.env` file.
|
|
@@ -702,6 +734,16 @@ page and session parameters.
|
|
|
702
734
|
|
|
703
735
|
Full API reference: https://captcha-solver.com/en/docs/captcha-types
|
|
704
736
|
|
|
737
|
+
## Useful Links
|
|
738
|
+
|
|
739
|
+
- [JavaScript SDK](https://github.com/captcha-solver-api/javascript-sdk)
|
|
740
|
+
- [Python examples](https://github.com/captcha-solver-api/python-examples)
|
|
741
|
+
- [Selenium Python examples](https://github.com/captcha-solver-api/captcha-solver-selenium-python-examples)
|
|
742
|
+
- [JavaScript examples](https://github.com/captcha-solver-api/javascript-examples)
|
|
743
|
+
- [Tencent CAPTCHA automation examples](https://github.com/captcha-solver-api/How-to-Automate-Tencent-CAPTCHA)
|
|
744
|
+
- [Cloudflare Turnstile Puppeteer Demo](https://github.com/captcha-solver-api/cloudflare-turnstile-puppeteer-demo) — a working browser automation example for Cloudflare Turnstile.
|
|
745
|
+
- [How to Automate Tencent CAPTCHA](https://captcha-solver.com/en/blog/how-to-automate-tencent-captcha) — a step-by-step guide with Python and JavaScript SDK examples.
|
|
746
|
+
|
|
705
747
|
## License
|
|
706
748
|
|
|
707
749
|
This project is licensed under the MIT License. See [LICENSE.md](https://github.com/captcha-solver-api/python-sdk/blob/main/LICENSE.md) for details.
|
|
@@ -13,26 +13,26 @@ Example:
|
|
|
13
13
|
result = client.solve(task)
|
|
14
14
|
"""
|
|
15
15
|
|
|
16
|
-
from .
|
|
16
|
+
from ._version import __version__
|
|
17
17
|
from .async_client import AsyncCaptchaClient
|
|
18
|
+
from .client import CaptchaClient
|
|
18
19
|
from .exceptions import (
|
|
19
|
-
CaptchaError,
|
|
20
20
|
ApiError,
|
|
21
|
-
|
|
21
|
+
CaptchaError,
|
|
22
22
|
CaptchaTimeoutError,
|
|
23
|
+
NetworkError,
|
|
23
24
|
TimeoutError,
|
|
24
25
|
ValidationError,
|
|
25
26
|
)
|
|
26
27
|
|
|
27
|
-
from ._version import __version__
|
|
28
|
-
|
|
29
28
|
__all__ = [
|
|
30
|
-
"
|
|
29
|
+
"ApiError",
|
|
31
30
|
"AsyncCaptchaClient",
|
|
31
|
+
"CaptchaClient",
|
|
32
32
|
"CaptchaError",
|
|
33
|
-
"ApiError",
|
|
34
|
-
"NetworkError",
|
|
35
33
|
"CaptchaTimeoutError",
|
|
34
|
+
"NetworkError",
|
|
36
35
|
"TimeoutError",
|
|
37
36
|
"ValidationError",
|
|
37
|
+
"__version__",
|
|
38
38
|
]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "1.0.3"
|
|
@@ -15,8 +15,8 @@ import httpx
|
|
|
15
15
|
from ._version import __version__
|
|
16
16
|
from .exceptions import (
|
|
17
17
|
ApiError,
|
|
18
|
-
NetworkError,
|
|
19
18
|
CaptchaTimeoutError,
|
|
19
|
+
NetworkError,
|
|
20
20
|
ValidationError,
|
|
21
21
|
)
|
|
22
22
|
|
|
@@ -54,7 +54,7 @@ class AsyncCaptchaClient:
|
|
|
54
54
|
raising `CaptchaTimeoutError`. Can be overridden per call.
|
|
55
55
|
polling_interval: Seconds to wait before the first `getTaskResult`
|
|
56
56
|
poll and between subsequent polls inside `solve()`. Defaults
|
|
57
|
-
to 10 seconds
|
|
57
|
+
to 10 seconds.
|
|
58
58
|
language_pool: Default worker pool selector (e.g. `"en"` or `"ru"`)
|
|
59
59
|
applied to every `create_task()`/`solve()` call that doesn't pass
|
|
60
60
|
its own `language_pool`. Leave unset to use the account's default
|
|
@@ -87,7 +87,7 @@ class AsyncCaptchaClient:
|
|
|
87
87
|
(`async with AsyncCaptchaClient(...) as c:`) to have it closed automatically."""
|
|
88
88
|
await self._client.aclose()
|
|
89
89
|
|
|
90
|
-
async def __aenter__(self) ->
|
|
90
|
+
async def __aenter__(self) -> AsyncCaptchaClient:
|
|
91
91
|
return self
|
|
92
92
|
|
|
93
93
|
async def __aexit__(self, *exc_info: Any) -> None:
|
|
@@ -113,6 +113,8 @@ class AsyncCaptchaClient:
|
|
|
113
113
|
except ValueError as exc:
|
|
114
114
|
raise NetworkError(f"Non-JSON response from API: {response.text[:200]!r}") from exc
|
|
115
115
|
|
|
116
|
+
if not isinstance(data, dict):
|
|
117
|
+
raise NetworkError(f"Unexpected API response shape: {type(data).__name__}")
|
|
116
118
|
return data
|
|
117
119
|
|
|
118
120
|
def _ensure_success(self, data: Dict[str, Any]) -> None:
|
|
@@ -154,7 +156,7 @@ class AsyncCaptchaClient:
|
|
|
154
156
|
|
|
155
157
|
data = await self._request("createTask", payload)
|
|
156
158
|
self._ensure_success(data)
|
|
157
|
-
return data["taskId"]
|
|
159
|
+
return int(data["taskId"])
|
|
158
160
|
|
|
159
161
|
async def get_task_result(self, task_id: int) -> Dict[str, Any]:
|
|
160
162
|
"""Fetch the current status of a previously submitted task.
|
|
@@ -203,7 +205,7 @@ class AsyncCaptchaClient:
|
|
|
203
205
|
payload = {"clientKey": self.client_key}
|
|
204
206
|
data = await self._request("getBalance", payload)
|
|
205
207
|
self._ensure_success(data)
|
|
206
|
-
return data["balance"]
|
|
208
|
+
return float(data["balance"])
|
|
207
209
|
|
|
208
210
|
async def solve(
|
|
209
211
|
self,
|
|
@@ -248,6 +250,9 @@ class AsyncCaptchaClient:
|
|
|
248
250
|
result = await self.get_task_result(task_id)
|
|
249
251
|
|
|
250
252
|
if result.get("status") == "ready":
|
|
251
|
-
|
|
253
|
+
solution = result["solution"]
|
|
254
|
+
if not isinstance(solution, dict):
|
|
255
|
+
raise NetworkError("API returned a ready task without a solution object")
|
|
256
|
+
return solution
|
|
252
257
|
|
|
253
258
|
raise CaptchaTimeoutError("Task solving timed out.")
|
|
@@ -12,8 +12,8 @@ import requests
|
|
|
12
12
|
from ._version import __version__
|
|
13
13
|
from .exceptions import (
|
|
14
14
|
ApiError,
|
|
15
|
-
NetworkError,
|
|
16
15
|
CaptchaTimeoutError,
|
|
16
|
+
NetworkError,
|
|
17
17
|
ValidationError,
|
|
18
18
|
)
|
|
19
19
|
|
|
@@ -43,7 +43,7 @@ class CaptchaClient:
|
|
|
43
43
|
raising `CaptchaTimeoutError`. Can be overridden per call.
|
|
44
44
|
polling_interval: Seconds to wait before the first `getTaskResult`
|
|
45
45
|
poll and between subsequent polls inside `solve()`. Defaults
|
|
46
|
-
to 10 seconds
|
|
46
|
+
to 10 seconds.
|
|
47
47
|
language_pool: Default worker pool selector (e.g. `"en"` or `"ru"`)
|
|
48
48
|
applied to every `create_task()`/`solve()` call that doesn't pass
|
|
49
49
|
its own `language_pool`. Leave unset to use the account's default
|
|
@@ -76,7 +76,7 @@ class CaptchaClient:
|
|
|
76
76
|
to have it closed automatically."""
|
|
77
77
|
self.session.close()
|
|
78
78
|
|
|
79
|
-
def __enter__(self) ->
|
|
79
|
+
def __enter__(self) -> CaptchaClient:
|
|
80
80
|
return self
|
|
81
81
|
|
|
82
82
|
def __exit__(self, *exc_info: Any) -> None:
|
|
@@ -102,6 +102,8 @@ class CaptchaClient:
|
|
|
102
102
|
except ValueError as exc:
|
|
103
103
|
raise NetworkError(f"Non-JSON response from API: {response.text[:200]!r}") from exc
|
|
104
104
|
|
|
105
|
+
if not isinstance(data, dict):
|
|
106
|
+
raise NetworkError(f"Unexpected API response shape: {type(data).__name__}")
|
|
105
107
|
return data
|
|
106
108
|
|
|
107
109
|
def _ensure_success(self, data: Dict[str, Any]) -> None:
|
|
@@ -141,7 +143,7 @@ class CaptchaClient:
|
|
|
141
143
|
|
|
142
144
|
data = self._request("createTask", payload)
|
|
143
145
|
self._ensure_success(data)
|
|
144
|
-
return data["taskId"]
|
|
146
|
+
return int(data["taskId"])
|
|
145
147
|
|
|
146
148
|
def get_task_result(self, task_id: int) -> Dict[str, Any]:
|
|
147
149
|
"""Fetches the current status of a task created with `create_task()`.
|
|
@@ -187,7 +189,7 @@ class CaptchaClient:
|
|
|
187
189
|
payload = {"clientKey": self.client_key}
|
|
188
190
|
data = self._request("getBalance", payload)
|
|
189
191
|
self._ensure_success(data)
|
|
190
|
-
return data["balance"]
|
|
192
|
+
return float(data["balance"])
|
|
191
193
|
|
|
192
194
|
def solve(
|
|
193
195
|
self,
|
|
@@ -230,6 +232,9 @@ class CaptchaClient:
|
|
|
230
232
|
result = self.get_task_result(task_id)
|
|
231
233
|
|
|
232
234
|
if result.get("status") == "ready":
|
|
233
|
-
|
|
235
|
+
solution = result["solution"]
|
|
236
|
+
if not isinstance(solution, dict):
|
|
237
|
+
raise NetworkError("API returned a ready task without a solution object")
|
|
238
|
+
return solution
|
|
234
239
|
|
|
235
240
|
raise CaptchaTimeoutError("Task solving timed out.")
|
|
@@ -6,20 +6,14 @@ Custom exceptions used by the Captcha Solver SDK.
|
|
|
6
6
|
class CaptchaError(Exception):
|
|
7
7
|
"""Base exception for all SDK errors."""
|
|
8
8
|
|
|
9
|
-
pass
|
|
10
|
-
|
|
11
9
|
|
|
12
10
|
class NetworkError(CaptchaError):
|
|
13
11
|
"""Raised when a network request fails."""
|
|
14
12
|
|
|
15
|
-
pass
|
|
16
|
-
|
|
17
13
|
|
|
18
14
|
class CaptchaTimeoutError(CaptchaError):
|
|
19
15
|
"""Raised when the operation exceeds the configured timeout."""
|
|
20
16
|
|
|
21
|
-
pass
|
|
22
|
-
|
|
23
17
|
|
|
24
18
|
# Deprecated alias kept for backward compatibility. It shadows the built-in
|
|
25
19
|
# ``TimeoutError`` when imported by name, so prefer ``CaptchaTimeoutError``.
|
|
@@ -37,5 +31,3 @@ class ApiError(CaptchaError):
|
|
|
37
31
|
|
|
38
32
|
class ValidationError(CaptchaError):
|
|
39
33
|
"""Raised for client-side argument problems caught before any request is sent."""
|
|
40
|
-
|
|
41
|
-
pass
|
|
@@ -12,7 +12,7 @@ once the task is `"ready"`.
|
|
|
12
12
|
|
|
13
13
|
from __future__ import annotations
|
|
14
14
|
|
|
15
|
-
from typing import Any, Dict,
|
|
15
|
+
from typing import Any, Dict, Optional
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
class BaseTask:
|
|
@@ -55,6 +55,15 @@ class ProxyMixin:
|
|
|
55
55
|
proxy_login: Optional[str] = None,
|
|
56
56
|
proxy_password: Optional[str] = None,
|
|
57
57
|
) -> None:
|
|
58
|
+
"""Sets the proxy fields on this task.
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
proxy_type: `"http"`, `"socks4"`, or `"socks5"`.
|
|
62
|
+
proxy_address: Proxy IP address or hostname.
|
|
63
|
+
proxy_port: Proxy port.
|
|
64
|
+
proxy_login: Proxy auth username, if required.
|
|
65
|
+
proxy_password: Proxy auth password, if required.
|
|
66
|
+
"""
|
|
58
67
|
self.proxyType = proxy_type
|
|
59
68
|
self.proxyAddress = proxy_address
|
|
60
69
|
self.proxyPort = proxy_port
|
|
@@ -294,11 +303,14 @@ class TurnstileTaskProxyless(BaseTask):
|
|
|
294
303
|
challenge pages beyond the basic widget. Named lowercase (not `pageData`)
|
|
295
304
|
to match the API field name exactly -- Cloudflare-specific fields are
|
|
296
305
|
the one place this API doesn't camelCase.
|
|
297
|
-
userAgent: User-Agent
|
|
298
|
-
|
|
306
|
+
userAgent: User-Agent of the browser that loaded the challenge. Pass it
|
|
307
|
+
together with `action`, `data`, and `pagedata` for Cloudflare
|
|
308
|
+
Challenge pages. It is not needed for a standalone widget.
|
|
299
309
|
|
|
300
310
|
Returns (`solution` from `solve()`):
|
|
301
311
|
`token` -- the value to submit as `cf-turnstile-response`.
|
|
312
|
+
`userAgent` -- for Cloudflare Challenge pages, switch the browser or HTTP
|
|
313
|
+
client to this returned User-Agent before invoking the callback.
|
|
302
314
|
"""
|
|
303
315
|
|
|
304
316
|
type = "TurnstileTaskProxyless"
|
|
@@ -336,10 +348,14 @@ class TurnstileTask(BaseTask, ProxyMixin):
|
|
|
336
348
|
pagedata: Value of the `chlPageData` parameter, needed for some Cloudflare
|
|
337
349
|
challenge pages beyond the basic widget. Named lowercase (not `pageData`)
|
|
338
350
|
to match the API field name exactly.
|
|
339
|
-
userAgent: User-Agent
|
|
351
|
+
userAgent: User-Agent of the browser that loaded the challenge. Pass it
|
|
352
|
+
for Cloudflare Challenge pages; it is not needed for a standalone
|
|
353
|
+
widget.
|
|
340
354
|
|
|
341
355
|
Returns (`solution` from `solve()`):
|
|
342
356
|
`token` -- the value to submit as `cf-turnstile-response`.
|
|
357
|
+
`userAgent` -- for Cloudflare Challenge pages, switch the browser or HTTP
|
|
358
|
+
client to this returned User-Agent before invoking the callback.
|
|
343
359
|
"""
|
|
344
360
|
|
|
345
361
|
type = "TurnstileTask"
|
|
@@ -525,8 +541,7 @@ class GeeTestTask(BaseTask, ProxyMixin):
|
|
|
525
541
|
|
|
526
542
|
|
|
527
543
|
class YandexSmartCaptchaTaskProxyless(BaseTask):
|
|
528
|
-
"""Yandex SmartCaptcha (token challenge) without proxy.
|
|
529
|
-
challenge instead, use `CoordinatesTask` with `imgType="smart_captcha"`.
|
|
544
|
+
"""Yandex SmartCaptcha (token challenge) without proxy.
|
|
530
545
|
|
|
531
546
|
Args:
|
|
532
547
|
websiteURL: Full URL of the page where the widget is located.
|
|
@@ -597,20 +612,16 @@ class YandexSmartCaptchaTask(BaseTask, ProxyMixin):
|
|
|
597
612
|
|
|
598
613
|
|
|
599
614
|
class CoordinatesTask(BaseTask):
|
|
600
|
-
"""Coordinate-based (click) image captcha.
|
|
601
|
-
|
|
602
|
-
`imgType` accordingly). No proxy variant -- the image is submitted directly.
|
|
615
|
+
"""Coordinate-based (click) image captcha. No proxy variant -- the image
|
|
616
|
+
is submitted directly.
|
|
603
617
|
|
|
604
618
|
Args:
|
|
605
619
|
body: The captcha image, base64-encoded (no `data:image/...;base64,` prefix).
|
|
606
620
|
comment: Hint for the worker, e.g. `"click on the green apple"`. Recommended
|
|
607
621
|
for generic click captchas.
|
|
608
|
-
imgInstructions: Optional instruction image, base64-encoded
|
|
609
|
-
to click and in what order. Required when `imgType="smart_captcha"`.
|
|
622
|
+
imgInstructions: Optional instruction image, base64-encoded.
|
|
610
623
|
minClicks: Minimum number of clicks expected (default `1`).
|
|
611
624
|
maxClicks: Maximum number of clicks allowed.
|
|
612
|
-
imgType: Set to `"smart_captcha"` to solve a Yandex SmartCaptcha image
|
|
613
|
-
challenge instead of a generic click captcha.
|
|
614
625
|
|
|
615
626
|
Returns (`solution` from `solve()`):
|
|
616
627
|
`coordinates` -- a list of `{"x": int, "y": int}` pixel positions to click,
|
|
@@ -626,14 +637,12 @@ class CoordinatesTask(BaseTask):
|
|
|
626
637
|
imgInstructions: Optional[str] = None,
|
|
627
638
|
minClicks: Optional[int] = None,
|
|
628
639
|
maxClicks: Optional[int] = None,
|
|
629
|
-
imgType: Optional[str] = None,
|
|
630
640
|
) -> None:
|
|
631
641
|
self.body = body
|
|
632
642
|
self.comment = comment
|
|
633
643
|
self.imgInstructions = imgInstructions
|
|
634
644
|
self.minClicks = minClicks
|
|
635
645
|
self.maxClicks = maxClicks
|
|
636
|
-
self.imgType = imgType
|
|
637
646
|
|
|
638
647
|
|
|
639
648
|
class TencentTaskProxyless(BaseTask):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: captcha-solver-api
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.3
|
|
4
4
|
Summary: Official Python SDK for solving reCAPTCHA v2/v3, Cloudflare Turnstile, GeeTest v3/v4, Yandex SmartCaptcha, Tencent, and image/click captchas via the Captcha Solver API
|
|
5
5
|
Author: Captcha Solver Team
|
|
6
6
|
License-Expression: MIT
|
|
@@ -32,11 +32,27 @@ Requires-Dist: pytest>=7; extra == "dev"
|
|
|
32
32
|
Requires-Dist: pytest-asyncio>=0.21; extra == "dev"
|
|
33
33
|
Requires-Dist: pytest-mock>=3; extra == "dev"
|
|
34
34
|
Requires-Dist: python-dotenv>=1.0; extra == "dev"
|
|
35
|
+
Requires-Dist: ruff>=0.6; extra == "dev"
|
|
36
|
+
Requires-Dist: mypy>=1.10; extra == "dev"
|
|
37
|
+
Requires-Dist: types-requests>=2.28; extra == "dev"
|
|
38
|
+
Requires-Dist: pytest-cov>=4; extra == "dev"
|
|
35
39
|
Dynamic: license-file
|
|
36
40
|
|
|
37
41
|
# Captcha Solver Python SDK
|
|
38
42
|
|
|
39
|
-

|
|
43
|
+

|
|
44
|
+
|
|
45
|
+
[](https://pypi.org/project/captcha-solver-api/)
|
|
46
|
+
[](https://pypi.org/project/captcha-solver-api/)
|
|
47
|
+
[](https://pepy.tech/project/captcha-solver-api)
|
|
48
|
+
[](https://github.com/captcha-solver-api/python-sdk/actions/workflows/tests.yml)
|
|
49
|
+
[](https://github.com/captcha-solver-api/python-sdk/actions/workflows/tests.yml)
|
|
50
|
+
[](https://github.com/captcha-solver-api/python-sdk/blob/main/captcha_solver_api/py.typed)
|
|
51
|
+
[](https://github.com/captcha-solver-api/python-sdk/blob/main/LICENSE.md)
|
|
52
|
+
[](https://github.com/astral-sh/ruff)
|
|
53
|
+
[](https://mypy-lang.org/)
|
|
54
|
+
[](https://github.com/captcha-solver-api/python-sdk/releases)
|
|
55
|
+
[](https://github.com/captcha-solver-api/javascript-sdk)
|
|
40
56
|
|
|
41
57
|
Official Python SDK for the Captcha Solver API. Solve reCAPTCHA v2/v3, Cloudflare Turnstile, GeeTest, Yandex SmartCaptcha, Tencent, and image/click captchas with a single method call -- sync or async.
|
|
42
58
|
|
|
@@ -47,6 +63,7 @@ Full API reference (all endpoints, error codes, captcha-type details): **https:/
|
|
|
47
63
|
- [Installation](#installation)
|
|
48
64
|
- [Configuration](#configuration)
|
|
49
65
|
- [Quick Start](#quick-start)
|
|
66
|
+
- [Build Faster with AI](#build-faster-with-ai)
|
|
50
67
|
- [Supported CAPTCHA Types](#supported-captcha-types)
|
|
51
68
|
- [Client Reference](#client-reference)
|
|
52
69
|
- [CaptchaClient(...)](#captchaclient)
|
|
@@ -74,6 +91,7 @@ Full API reference (all endpoints, error codes, captcha-type details): **https:/
|
|
|
74
91
|
- [Running the examples](#running-the-examples)
|
|
75
92
|
- [Requirements](#requirements)
|
|
76
93
|
- [API Documentation](#api-documentation)
|
|
94
|
+
- [Useful Links](#useful-links)
|
|
77
95
|
- [License](#license)
|
|
78
96
|
|
|
79
97
|
## Installation
|
|
@@ -124,6 +142,23 @@ result = client.solve(task)
|
|
|
124
142
|
print(result["gRecaptchaResponse"])
|
|
125
143
|
```
|
|
126
144
|
|
|
145
|
+
## Build Faster with AI
|
|
146
|
+
|
|
147
|
+
Use our [`llms.txt`](https://captcha-solver.com/llms.txt) as context when asking an
|
|
148
|
+
AI assistant to build or update your integration. It contains the current API
|
|
149
|
+
format, supported task parameters, SDK installation instructions, solution
|
|
150
|
+
fields, and error codes in one file.
|
|
151
|
+
|
|
152
|
+
Copy this prompt and add a description of the page and CAPTCHA you need to
|
|
153
|
+
handle:
|
|
154
|
+
|
|
155
|
+
```text
|
|
156
|
+
Read https://captcha-solver.com/llms.txt and use the Captcha Solver Python SDK.
|
|
157
|
+
Write a complete integration for this task: [describe your task here].
|
|
158
|
+
Use the documented task parameters and show how to apply the returned solution
|
|
159
|
+
on the target page.
|
|
160
|
+
```
|
|
161
|
+
|
|
127
162
|
## Supported CAPTCHA Types
|
|
128
163
|
|
|
129
164
|
| Type | Proxyless | With Proxy |
|
|
@@ -157,7 +192,7 @@ Constructor.
|
|
|
157
192
|
| `client_key` | `str` | required | Your Captcha Solver API key. Raises `ValidationError` if empty. |
|
|
158
193
|
| `base_url` | `str` | `https://api.captcha-solver.com` | API base URL. Override only for self-hosted/staging deployments. |
|
|
159
194
|
| `timeout` | `int` | `120` | Polling window after task creation, in seconds. Overridable per call; each HTTP request has a separate 30-second timeout. |
|
|
160
|
-
| `polling_interval` | `int` | `10` | Seconds before the first `getTaskResult` poll and between subsequent polls
|
|
195
|
+
| `polling_interval` | `int` | `10` | Seconds before the first `getTaskResult` poll and between subsequent polls. |
|
|
161
196
|
| `language_pool` | `Optional[str]` | `None` | Default worker pool (`"en"` or `"ru"`) applied to every call that doesn't pass its own `language_pool`. |
|
|
162
197
|
|
|
163
198
|
Both clients hold a reusable connection pool (`requests.Session` / `httpx.AsyncClient`)
|
|
@@ -353,12 +388,13 @@ that the target page expects in `cf-turnstile-response`.
|
|
|
353
388
|
| `action` | no | Value of the widget's `data-action` attribute, if set. |
|
|
354
389
|
| `data` | no | Custom payload from the widget's `data-cdata` attribute, if set. |
|
|
355
390
|
| `pagedata` | no | Value of the `chlPageData` parameter, needed for some Cloudflare challenge pages beyond the basic widget. |
|
|
356
|
-
| `userAgent` | no | User-Agent
|
|
391
|
+
| `userAgent` | no | Current browser User-Agent. Pass it for Cloudflare Challenge pages; it is not needed for a standalone widget. |
|
|
357
392
|
|
|
358
393
|
**Response:** `token` -- submit as `cf-turnstile-response`. For Cloudflare
|
|
359
|
-
Challenge pages,
|
|
360
|
-
|
|
361
|
-
|
|
394
|
+
Challenge pages, pass `action`, `data`, `pagedata`, and the current browser
|
|
395
|
+
`userAgent` in the task. The solution also contains `userAgent`; switch the
|
|
396
|
+
browser or HTTP client to this returned value before invoking the callback with
|
|
397
|
+
the token. The API field is spelled `pagedata`, all lowercase.
|
|
362
398
|
|
|
363
399
|
```python
|
|
364
400
|
from captcha_solver_api import CaptchaClient
|
|
@@ -366,10 +402,15 @@ from captcha_solver_api.tasks import TurnstileTaskProxyless
|
|
|
366
402
|
client = CaptchaClient("your_api_key")
|
|
367
403
|
task = TurnstileTaskProxyless(
|
|
368
404
|
websiteURL="https://example.com/login",
|
|
369
|
-
websiteKey="YOUR_WEBSITE_KEY"
|
|
405
|
+
websiteKey="YOUR_WEBSITE_KEY",
|
|
406
|
+
action="managed",
|
|
407
|
+
data="INTERCEPTED_CDATA",
|
|
408
|
+
pagedata="INTERCEPTED_CHL_PAGE_DATA",
|
|
409
|
+
userAgent="CURRENT_BROWSER_USER_AGENT",
|
|
370
410
|
)
|
|
371
411
|
result = client.solve(task)
|
|
372
412
|
print(result["token"])
|
|
413
|
+
print(result.get("userAgent"))
|
|
373
414
|
```
|
|
374
415
|
|
|
375
416
|
With proxy, use `TurnstileTask` (same proxy fields as reCAPTCHA v2).
|
|
@@ -476,7 +517,7 @@ for the widget on the target page. Use the coordinates method for image challeng
|
|
|
476
517
|
|
|
477
518
|
`YandexSmartCaptchaTaskProxyless` / `YandexSmartCaptchaTask` -- token-based
|
|
478
519
|
challenge. For the image challenge instead, use `CoordinatesTask` with
|
|
479
|
-
|
|
520
|
+
[Coordinates](#coordinates-click-captcha) is available for generic click captchas.
|
|
480
521
|
|
|
481
522
|
| Parameter | Required | Description |
|
|
482
523
|
|---|---|---|
|
|
@@ -519,10 +560,9 @@ SmartCaptcha's image challenge. No proxy variant -- the image is submitted direc
|
|
|
519
560
|
|---|---|---|
|
|
520
561
|
| `body` | yes | The captcha image, base64-encoded. |
|
|
521
562
|
| `comment` | no (recommended) | Hint for the worker, e.g. `"click on the green apple"`. |
|
|
522
|
-
| `imgInstructions` |
|
|
563
|
+
| `imgInstructions` | no | Optional instruction image, base64-encoded. |
|
|
523
564
|
| `minClicks` | no | Minimum number of clicks expected (default `1`). |
|
|
524
565
|
| `maxClicks` | no | Maximum number of clicks allowed. |
|
|
525
|
-
| `imgType` | no | `"smart_captcha"` to solve a Yandex SmartCaptcha image challenge instead of a generic click captcha. |
|
|
526
566
|
|
|
527
567
|
**Response:** `coordinates` -- a list of `{"x": int, "y": int}` pixel positions to click, in order.
|
|
528
568
|
|
|
@@ -540,9 +580,6 @@ task = CoordinatesTask(
|
|
|
540
580
|
result = client.solve(task)
|
|
541
581
|
print(result["coordinates"]) # [{"x": 140, "y": 110}]
|
|
542
582
|
```
|
|
543
|
-
For the Yandex SmartCaptcha image challenge, see
|
|
544
|
-
[examples/sync/yandex_smartcaptcha_image.py](https://github.com/captcha-solver-api/python-sdk/blob/main/examples/sync/yandex_smartcaptcha_image.py)
|
|
545
|
-
(or [examples/async](https://github.com/captcha-solver-api/python-sdk/blob/main/examples/async/yandex_smartcaptcha_image.py)).
|
|
546
583
|
|
|
547
584
|
### Tencent
|
|
548
585
|
|
|
@@ -604,8 +641,8 @@ result = client.solve(task, timeout=300)
|
|
|
604
641
|
```
|
|
605
642
|
|
|
606
643
|
The [API requires at least 5 seconds between polls](https://captcha-solver.com/en/docs/how-it-works).
|
|
607
|
-
The SDK defaults to 10 seconds
|
|
608
|
-
|
|
644
|
+
The SDK defaults to 10 seconds. `solve()` waits for `polling_interval` before
|
|
645
|
+
its first poll and between polls.
|
|
609
646
|
Its default 120-second polling window is independent of the API's five-minute
|
|
610
647
|
task lifetime. A local timeout does not cancel a task or mean that the API
|
|
611
648
|
failed to solve it. Use `create_task()` and keep its `task_id` if you need to
|
|
@@ -695,8 +732,7 @@ Avoid importing it by name: it shadows Python's built-in `TimeoutError`.
|
|
|
695
732
|
See the dedicated [examples documentation](https://github.com/captcha-solver-api/python-sdk/blob/main/examples/README.md) for the full
|
|
696
733
|
sync/async example list, setup steps, expected results, and placeholder guidance.
|
|
697
734
|
|
|
698
|
-
- **Image/click captchas** (`image_to_text.py`, `coordinates.py
|
|
699
|
-
`yandex_smartcaptcha_image.py`) run after installing the dependencies and setting a valid
|
|
735
|
+
- **Image/click captchas** (`image_to_text.py`, `coordinates.py`) run after installing the dependencies and setting a valid
|
|
700
736
|
`CAPTCHA_API_KEY` -- they read sample images bundled in
|
|
701
737
|
[examples/assets](https://github.com/captcha-solver-api/python-sdk/tree/main/examples/assets), no target page needed.
|
|
702
738
|
`python-dotenv` is optional: install it only if you want the scripts to load a `.env` file.
|
|
@@ -738,6 +774,16 @@ page and session parameters.
|
|
|
738
774
|
|
|
739
775
|
Full API reference: https://captcha-solver.com/en/docs/captcha-types
|
|
740
776
|
|
|
777
|
+
## Useful Links
|
|
778
|
+
|
|
779
|
+
- [JavaScript SDK](https://github.com/captcha-solver-api/javascript-sdk)
|
|
780
|
+
- [Python examples](https://github.com/captcha-solver-api/python-examples)
|
|
781
|
+
- [Selenium Python examples](https://github.com/captcha-solver-api/captcha-solver-selenium-python-examples)
|
|
782
|
+
- [JavaScript examples](https://github.com/captcha-solver-api/javascript-examples)
|
|
783
|
+
- [Tencent CAPTCHA automation examples](https://github.com/captcha-solver-api/How-to-Automate-Tencent-CAPTCHA)
|
|
784
|
+
- [Cloudflare Turnstile Puppeteer Demo](https://github.com/captcha-solver-api/cloudflare-turnstile-puppeteer-demo) — a working browser automation example for Cloudflare Turnstile.
|
|
785
|
+
- [How to Automate Tencent CAPTCHA](https://captcha-solver.com/en/blog/how-to-automate-tencent-captcha) — a step-by-step guide with Python and JavaScript SDK examples.
|
|
786
|
+
|
|
741
787
|
## License
|
|
742
788
|
|
|
743
789
|
This project is licensed under the MIT License. See [LICENSE.md](https://github.com/captcha-solver-api/python-sdk/blob/main/LICENSE.md) for details.
|
|
@@ -45,6 +45,10 @@ dev = [
|
|
|
45
45
|
"pytest-asyncio>=0.21",
|
|
46
46
|
"pytest-mock>=3",
|
|
47
47
|
"python-dotenv>=1.0",
|
|
48
|
+
"ruff>=0.6",
|
|
49
|
+
"mypy>=1.10",
|
|
50
|
+
"types-requests>=2.28",
|
|
51
|
+
"pytest-cov>=4",
|
|
48
52
|
]
|
|
49
53
|
|
|
50
54
|
[project.urls]
|
|
@@ -63,3 +67,34 @@ captcha_solver_api = ["py.typed"]
|
|
|
63
67
|
|
|
64
68
|
[tool.pytest.ini_options]
|
|
65
69
|
asyncio_mode = "auto"
|
|
70
|
+
|
|
71
|
+
[tool.coverage.run]
|
|
72
|
+
source = ["captcha_solver_api"]
|
|
73
|
+
branch = true
|
|
74
|
+
|
|
75
|
+
[tool.coverage.report]
|
|
76
|
+
show_missing = true
|
|
77
|
+
|
|
78
|
+
[tool.mypy]
|
|
79
|
+
# mypy 2.x cannot target 3.9; 3.10 is the lowest it accepts. Runtime
|
|
80
|
+
# compatibility with 3.9 is still covered by the CI test matrix.
|
|
81
|
+
python_version = "3.10"
|
|
82
|
+
strict = true
|
|
83
|
+
files = ["captcha_solver_api"]
|
|
84
|
+
|
|
85
|
+
[tool.ruff]
|
|
86
|
+
target-version = "py39"
|
|
87
|
+
line-length = 100
|
|
88
|
+
extend-exclude = [".pytest_cache", "*.md"]
|
|
89
|
+
|
|
90
|
+
[tool.ruff.lint]
|
|
91
|
+
select = ["E", "F", "W", "I", "UP", "B", "N", "PIE", "RUF"]
|
|
92
|
+
ignore = [
|
|
93
|
+
"UP006", "UP035", "UP045", # keep typing.Optional/Dict/List for 3.9 readability
|
|
94
|
+
"N803", "N815", # task fields mirror API camelCase on purpose
|
|
95
|
+
"E501", # long lines in docstrings/tables
|
|
96
|
+
]
|
|
97
|
+
|
|
98
|
+
[tool.ruff.lint.per-file-ignores]
|
|
99
|
+
"examples/**" = ["E402"] # imports after sys.path/dotenv setup
|
|
100
|
+
"tests/**" = ["RUF012"]
|
|
@@ -5,9 +5,9 @@ from unittest.mock import AsyncMock
|
|
|
5
5
|
|
|
6
6
|
import pytest
|
|
7
7
|
|
|
8
|
-
import captcha_solver_api.client as sync_module
|
|
9
8
|
import captcha_solver_api.async_client as async_module
|
|
10
|
-
|
|
9
|
+
import captcha_solver_api.client as sync_module
|
|
10
|
+
from captcha_solver_api import AsyncCaptchaClient, CaptchaClient, CaptchaTimeoutError
|
|
11
11
|
from captcha_solver_api.tasks import RecaptchaV2TaskProxyless
|
|
12
12
|
|
|
13
13
|
|
|
@@ -30,60 +30,62 @@ CASES = [
|
|
|
30
30
|
]
|
|
31
31
|
|
|
32
32
|
|
|
33
|
-
@pytest.mark.parametrize(
|
|
33
|
+
@pytest.mark.parametrize("interval,timeout,expected_polls,times_out", CASES)
|
|
34
34
|
def test_sync_polling_schedule(monkeypatch, interval, timeout, expected_polls, times_out):
|
|
35
35
|
clock = Clock()
|
|
36
36
|
polls = []
|
|
37
|
-
monkeypatch.setattr(sync_module,
|
|
37
|
+
monkeypatch.setattr(sync_module, "time", clock)
|
|
38
38
|
|
|
39
39
|
def request(endpoint, payload):
|
|
40
|
-
if endpoint ==
|
|
40
|
+
if endpoint == "createTask":
|
|
41
41
|
assert clock.now == 0
|
|
42
|
-
return {
|
|
43
|
-
assert payload[
|
|
42
|
+
return {"errorId": 0, "taskId": 100}
|
|
43
|
+
assert payload["taskId"] == 100
|
|
44
44
|
polls.append(clock.now)
|
|
45
45
|
if len(polls) == 2:
|
|
46
|
-
return {
|
|
47
|
-
return {
|
|
46
|
+
return {"errorId": 0, "status": "ready", "solution": {"token": "done"}}
|
|
47
|
+
return {"errorId": 0, "status": "processing"}
|
|
48
48
|
|
|
49
|
-
options = {} if interval is None else {
|
|
50
|
-
with CaptchaClient(
|
|
51
|
-
monkeypatch.setattr(client,
|
|
52
|
-
task = RecaptchaV2TaskProxyless(
|
|
49
|
+
options = {} if interval is None else {"polling_interval": interval}
|
|
50
|
+
with CaptchaClient("test-key", **options) as client:
|
|
51
|
+
monkeypatch.setattr(client, "_request", request)
|
|
52
|
+
task = RecaptchaV2TaskProxyless("https://example.com", "site-key")
|
|
53
53
|
if times_out:
|
|
54
54
|
with pytest.raises(CaptchaTimeoutError):
|
|
55
55
|
client.solve(task, timeout=timeout)
|
|
56
56
|
assert clock.now == timeout
|
|
57
57
|
else:
|
|
58
|
-
assert client.solve(task, timeout=timeout) == {
|
|
58
|
+
assert client.solve(task, timeout=timeout) == {"token": "done"}
|
|
59
59
|
assert polls == expected_polls
|
|
60
60
|
|
|
61
61
|
|
|
62
|
-
@pytest.mark.parametrize(
|
|
62
|
+
@pytest.mark.parametrize("interval,timeout,expected_polls,times_out", CASES)
|
|
63
63
|
async def test_async_polling_schedule(monkeypatch, interval, timeout, expected_polls, times_out):
|
|
64
64
|
clock = Clock()
|
|
65
65
|
polls = []
|
|
66
|
-
monkeypatch.setattr(async_module,
|
|
67
|
-
monkeypatch.setattr(
|
|
66
|
+
monkeypatch.setattr(async_module, "time", clock)
|
|
67
|
+
monkeypatch.setattr(
|
|
68
|
+
async_module, "asyncio", SimpleNamespace(sleep=AsyncMock(side_effect=clock.sleep))
|
|
69
|
+
)
|
|
68
70
|
|
|
69
71
|
async def request(endpoint, payload):
|
|
70
|
-
if endpoint ==
|
|
72
|
+
if endpoint == "createTask":
|
|
71
73
|
assert clock.now == 0
|
|
72
|
-
return {
|
|
73
|
-
assert payload[
|
|
74
|
+
return {"errorId": 0, "taskId": 100}
|
|
75
|
+
assert payload["taskId"] == 100
|
|
74
76
|
polls.append(clock.now)
|
|
75
77
|
if len(polls) == 2:
|
|
76
|
-
return {
|
|
77
|
-
return {
|
|
78
|
+
return {"errorId": 0, "status": "ready", "solution": {"token": "done"}}
|
|
79
|
+
return {"errorId": 0, "status": "processing"}
|
|
78
80
|
|
|
79
|
-
options = {} if interval is None else {
|
|
80
|
-
async with AsyncCaptchaClient(
|
|
81
|
-
monkeypatch.setattr(client,
|
|
82
|
-
task = RecaptchaV2TaskProxyless(
|
|
81
|
+
options = {} if interval is None else {"polling_interval": interval}
|
|
82
|
+
async with AsyncCaptchaClient("test-key", **options) as client:
|
|
83
|
+
monkeypatch.setattr(client, "_request", request)
|
|
84
|
+
task = RecaptchaV2TaskProxyless("https://example.com", "site-key")
|
|
83
85
|
if times_out:
|
|
84
86
|
with pytest.raises(CaptchaTimeoutError):
|
|
85
87
|
await client.solve(task, timeout=timeout)
|
|
86
88
|
assert clock.now == timeout
|
|
87
89
|
else:
|
|
88
|
-
assert await client.solve(task, timeout=timeout) == {
|
|
90
|
+
assert await client.solve(task, timeout=timeout) == {"token": "done"}
|
|
89
91
|
assert polls == expected_polls
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "1.0.1"
|
|
File without changes
|
|
File without changes
|
{captcha_solver_api-1.0.1 → captcha_solver_api-1.0.3}/captcha_solver_api.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
{captcha_solver_api-1.0.1 → captcha_solver_api-1.0.3}/captcha_solver_api.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|