captcha-solver-api 1.0.3__tar.gz → 1.1.0__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.
Files changed (21) hide show
  1. {captcha_solver_api-1.0.3 → captcha_solver_api-1.1.0}/PKG-INFO +117 -27
  2. {captcha_solver_api-1.0.3 → captcha_solver_api-1.1.0}/README.md +113 -23
  3. captcha_solver_api-1.1.0/captcha_solver_api/_version.py +1 -0
  4. {captcha_solver_api-1.0.3 → captcha_solver_api-1.1.0}/captcha_solver_api/async_client.py +111 -21
  5. {captcha_solver_api-1.0.3 → captcha_solver_api-1.1.0}/captcha_solver_api/client.py +104 -18
  6. captcha_solver_api-1.1.0/captcha_solver_api/exceptions.py +85 -0
  7. captcha_solver_api-1.1.0/captcha_solver_api/tasks.py +1025 -0
  8. {captcha_solver_api-1.0.3 → captcha_solver_api-1.1.0}/captcha_solver_api.egg-info/PKG-INFO +117 -27
  9. {captcha_solver_api-1.0.3 → captcha_solver_api-1.1.0}/captcha_solver_api.egg-info/requires.txt +2 -2
  10. {captcha_solver_api-1.0.3 → captcha_solver_api-1.1.0}/pyproject.toml +3 -3
  11. captcha_solver_api-1.0.3/captcha_solver_api/_version.py +0 -1
  12. captcha_solver_api-1.0.3/captcha_solver_api/exceptions.py +0 -33
  13. captcha_solver_api-1.0.3/captcha_solver_api/tasks.py +0 -714
  14. {captcha_solver_api-1.0.3 → captcha_solver_api-1.1.0}/LICENSE.md +0 -0
  15. {captcha_solver_api-1.0.3 → captcha_solver_api-1.1.0}/captcha_solver_api/__init__.py +0 -0
  16. {captcha_solver_api-1.0.3 → captcha_solver_api-1.1.0}/captcha_solver_api/py.typed +0 -0
  17. {captcha_solver_api-1.0.3 → captcha_solver_api-1.1.0}/captcha_solver_api.egg-info/SOURCES.txt +0 -0
  18. {captcha_solver_api-1.0.3 → captcha_solver_api-1.1.0}/captcha_solver_api.egg-info/dependency_links.txt +0 -0
  19. {captcha_solver_api-1.0.3 → captcha_solver_api-1.1.0}/captcha_solver_api.egg-info/top_level.txt +0 -0
  20. {captcha_solver_api-1.0.3 → captcha_solver_api-1.1.0}/setup.cfg +0 -0
  21. {captcha_solver_api-1.0.3 → captcha_solver_api-1.1.0}/tests/test_polling.py +0 -0
@@ -1,11 +1,11 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: captcha-solver-api
3
- Version: 1.0.3
3
+ Version: 1.1.0
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
7
7
  Project-URL: Homepage, https://captcha-solver.com
8
- Project-URL: Documentation, https://captcha-solver.com/en/docs/captcha-types
8
+ Project-URL: Documentation, https://github.com/captcha-solver-api/python-sdk#readme
9
9
  Project-URL: Repository, https://github.com/captcha-solver-api/python-sdk
10
10
  Keywords: captcha,captcha solver,recaptcha,recaptcha v2,recaptcha v3,cloudflare turnstile,geetest,geetest v4,yandex smartcaptcha,tencent captcha,image captcha,coordinates,click captcha,api
11
11
  Classifier: Development Status :: 5 - Production/Stable
@@ -25,8 +25,8 @@ Classifier: Typing :: Typed
25
25
  Requires-Python: >=3.9
26
26
  Description-Content-Type: text/markdown
27
27
  License-File: LICENSE.md
28
- Requires-Dist: requests>=2.28
29
- Requires-Dist: httpx>=0.24
28
+ Requires-Dist: requests>=2.32.4
29
+ Requires-Dist: httpx>=0.27
30
30
  Provides-Extra: dev
31
31
  Requires-Dist: pytest>=7; extra == "dev"
32
32
  Requires-Dist: pytest-asyncio>=0.21; extra == "dev"
@@ -61,6 +61,7 @@ Full API reference (all endpoints, error codes, captcha-type details): **https:/
61
61
  ## Table of Contents
62
62
 
63
63
  - [Installation](#installation)
64
+ - [Editor documentation](#editor-documentation)
64
65
  - [Configuration](#configuration)
65
66
  - [Quick Start](#quick-start)
66
67
  - [Build Faster with AI](#build-faster-with-ai)
@@ -106,6 +107,35 @@ Or install the latest version from GitHub:
106
107
  pip install git+https://github.com/captcha-solver-api/python-sdk.git
107
108
  ```
108
109
 
110
+ ## Editor documentation
111
+
112
+ The SDK includes Python docstrings (the equivalent of JSDoc), type annotations,
113
+ and a `py.typed` marker in the installed package. With Python language support
114
+ enabled in your editor, hover over `CaptchaClient`, `AsyncCaptchaClient`, their
115
+ methods, or a task class such as `RecaptchaV2TaskProxyless` to read the documentation.
116
+ Signature help shows argument names, types, and defaults while you type a call.
117
+
118
+ The `captcha_solver_api/py.typed` file is intentionally empty. It is the standard
119
+ [PEP 561](https://peps.python.org/pep-0561/) marker that tells type checkers to use
120
+ the inline type annotations shipped with this package.
121
+
122
+ Docstrings describe parameters, solution fields, exceptions, and usage examples.
123
+ Task examples assume an existing synchronous `client`; with `AsyncCaptchaClient`,
124
+ use `solution = await client.solve(task)` instead. Async snippets run inside an
125
+ `async def` function. In VS Code, select the Python interpreter where the SDK is
126
+ installed and enable the Python and Pylance extensions. In PyCharm, use Quick
127
+ Documentation. The exact presentation depends on the editor.
128
+
129
+ You can also read the same documentation without an editor:
130
+
131
+ ```python
132
+ from captcha_solver_api import CaptchaClient
133
+ from captcha_solver_api.tasks import RecaptchaV2TaskProxyless
134
+
135
+ help(CaptchaClient.solve)
136
+ help(RecaptchaV2TaskProxyless)
137
+ ```
138
+
109
139
  ## Configuration
110
140
 
111
141
  The client always takes the API key as an explicit argument -- it does not read
@@ -165,15 +195,19 @@ on the target page.
165
195
  |---|---|---|
166
196
  | reCAPTCHA v2 | ✅ | ✅ |
167
197
  | reCAPTCHA v2 Enterprise | ✅ | ✅ |
168
- | reCAPTCHA v3 | ✅ | ❌ |
198
+ | reCAPTCHA v3 | ✅ | - |
169
199
  | Cloudflare Turnstile | ✅ | ✅ |
170
200
  | GeeTest v3 | ✅ | ✅ |
171
201
  | GeeTest v4 | ✅ | ✅ |
172
- | Image to Text | ✅ | ❌ |
202
+ | Image to Text | ✅ | - |
173
203
  | Yandex SmartCaptcha | ✅ | ✅ |
174
- | Coordinates (click captcha) | ✅ | ❌ |
204
+ | Yandex SmartCaptcha Image | ✅ | - |
205
+ | Coordinates (click captcha) | ✅ | - |
175
206
  | Tencent | ✅ | ✅ |
176
207
 
208
+ A dash (`-`) means that this CAPTCHA type has no separate task class that accepts
209
+ your own proxy; it does not indicate that solving the CAPTCHA is unsupported.
210
+
177
211
  ## Client Reference
178
212
 
179
213
  Every method below is available on both `CaptchaClient` (sync, `requests`-based) and
@@ -221,14 +255,17 @@ solution -- wraps `create_task()` + `get_task_result()` so you don't poll by han
221
255
 
222
256
  Returns the `solution` dict once `status` is `"ready"` -- its shape depends on
223
257
  the task type (see [Captcha Types](#captcha-types)).
224
- Raises `ApiError`, `CaptchaTimeoutError`, or `NetworkError`.
258
+ Raises `ValidationError` before any request if `task` is not a task object or a
259
+ required task parameter is missing or empty. Otherwise raises `ApiError`,
260
+ `CaptchaTimeoutError`, or `NetworkError`.
225
261
 
226
262
  ### `create_task(task, language_pool=None)`
227
263
 
228
264
  Submits `task` and returns its numeric task ID without waiting for a solution.
229
265
  Accepts `task` and `language_pool`; it does not accept `timeout`. Use this instead of `solve()` if you need to
230
266
  manage polling yourself (e.g. checking on many tasks from a different process).
231
- Raises `ApiError`, `CaptchaTimeoutError`, or `NetworkError`.
267
+ Raises `ValidationError` before any request if `task` is invalid (same rules as
268
+ `solve()`). Otherwise raises `ApiError`, `CaptchaTimeoutError`, or `NetworkError`.
232
269
 
233
270
  ### `get_task_result(task_id)`
234
271
 
@@ -493,7 +530,7 @@ print(result["validate"])
493
530
  print(result["seccode"])
494
531
  ```
495
532
  `challenge` is session-specific and expires quickly, so it can't be hardcoded
496
- into a static example -- see [examples/sync/geetest_v3.py](https://github.com/captcha-solver-api/python-sdk/blob/main/examples/sync/geetest_v3.py)
533
+ into a static example -- see [examples/sync/geetest_v3_proxyless.py](https://github.com/captcha-solver-api/python-sdk/blob/main/examples/sync/geetest_v3_proxyless.py)
497
534
  for where the fetch belongs in the flow.
498
535
 
499
536
  ```python
@@ -513,11 +550,9 @@ With proxy, use `GeeTestTask` (same proxy fields as reCAPTCHA v2).
513
550
  <sup>[API method description.](https://captcha-solver.com/en/docs/captcha-types#yandex-smartcaptcha)</sup>
514
551
 
515
552
  Use this method to solve the token-based Yandex SmartCaptcha and obtain a token
516
- for the widget on the target page. Use the coordinates method for image challenges.
553
+ for the widget on the target page. Use the dedicated image method for image challenges.
517
554
 
518
- `YandexSmartCaptchaTaskProxyless` / `YandexSmartCaptchaTask` -- token-based
519
- challenge. For the image challenge instead, use `CoordinatesTask` with
520
- [Coordinates](#coordinates-click-captcha) is available for generic click captchas.
555
+ `YandexSmartCaptchaTaskProxyless` / `YandexSmartCaptchaTask` -- token-based challenge.
521
556
 
522
557
  | Parameter | Required | Description |
523
558
  |---|---|---|
@@ -546,15 +581,45 @@ print(result["token"])
546
581
  With proxy, use `YandexSmartCaptchaTask` (same proxy fields as reCAPTCHA v2,
547
582
  plus the `https` option above).
548
583
 
584
+ #### Image challenge
585
+
586
+ Use `YandexSmartCaptchaImageTask` when SmartCaptcha shows a main image and a
587
+ separate strip indicating the symbols to click. The SDK sends API v2 type
588
+ `SmartCaptchaTask`; both images must be base64-encoded.
589
+
590
+ | Parameter | Required | Description |
591
+ |---|---|---|
592
+ | `image` | yes | Main captcha image, base64-encoded. |
593
+ | `imgInstructions` | yes | Click-order instruction image, base64-encoded. |
594
+ | `comment` | no | Optional text hint for the worker. |
595
+
596
+ **Response:** `coordinates` -- ordered `{"x": int, "y": int}` click positions.
597
+
598
+ ```python
599
+ import base64
600
+ from captcha_solver_api import CaptchaClient
601
+ from captcha_solver_api.tasks import YandexSmartCaptchaImageTask
602
+
603
+ with open("captcha.png", "rb") as f:
604
+ image = base64.b64encode(f.read()).decode("utf-8")
605
+ with open("instructions.png", "rb") as f:
606
+ instructions = base64.b64encode(f.read()).decode("utf-8")
607
+
608
+ task = YandexSmartCaptchaImageTask(
609
+ image=image,
610
+ imgInstructions=instructions,
611
+ )
612
+ result = CaptchaClient("your_api_key").solve(task)
613
+ print(result["coordinates"])
614
+ ```
615
+
549
616
  ### Coordinates (click captcha)
550
617
 
551
618
  <sup>[API method description.](https://captcha-solver.com/en/docs/captcha-types#coordinates)</sup>
552
619
 
553
- Use this method to identify points that a worker should click in an image. It
554
- supports generic click captchas and the image version of Yandex SmartCaptcha.
620
+ Use this method to identify points that a worker should click in a generic image.
555
621
 
556
- `CoordinatesTask`. Used both for generic "click on X" captchas and for Yandex
557
- SmartCaptcha's image challenge. No proxy variant -- the image is submitted directly.
622
+ `CoordinatesTask`. No proxy variant -- the image is submitted directly.
558
623
 
559
624
  | Parameter | Required | Description |
560
625
  |---|---|---|
@@ -648,6 +713,16 @@ task lifetime. A local timeout does not cancel a task or mean that the API
648
713
  failed to solve it. Use `create_task()` and keep its `task_id` if you need to
649
714
  check the same task later; calling `solve()` again creates a new task.
650
715
 
716
+ While polling, `solve()` retries short network failures and HTTP timeouts of
717
+ `getTaskResult` on the next poll, so a brief outage does not lose an already
718
+ created task. After `poll_retries` (default 3) consecutive failures the error is
719
+ raised. API errors are not retried, and `createTask` is never retried because
720
+ that could create and pay for a second task. To change the limit:
721
+
722
+ ```python
723
+ client.poll_retries = 5
724
+ ```
725
+
651
726
  ### Worker language pool
652
727
 
653
728
  Set a default `language_pool` once at construction instead of passing it to every call:
@@ -717,13 +792,26 @@ try:
717
792
  except ValidationError as e:
718
793
  print(f"Invalid argument: {e}")
719
794
  except ApiError as e:
720
- print(f"API error: {e.error_code} {e.error_description}")
721
- except CaptchaTimeoutError:
722
- print("Task timed out")
795
+ print(f"API error: {e.error_code} {e.error_description} (task {e.task_id})")
796
+ except CaptchaTimeoutError as e:
797
+ print(f"Task {e.task_id} timed out")
723
798
  except NetworkError as e:
724
799
  print(f"Network error: {e}")
725
800
  ```
726
801
 
802
+ Every SDK error has a `task_id` attribute. It is set when the error happens
803
+ after the task was created (while polling in `solve()` or in `get_task_result()`)
804
+ and is `None` otherwise. A polling timeout does not cancel the task, so you can
805
+ keep checking it:
806
+
807
+ ```python
808
+ try:
809
+ result = client.solve(task)
810
+ except CaptchaTimeoutError as e:
811
+ if e.task_id is not None:
812
+ status = client.get_task_result(e.task_id)
813
+ ```
814
+
727
815
  `TimeoutError` is still exported as a deprecated alias of `CaptchaTimeoutError`.
728
816
  Avoid importing it by name: it shadows Python's built-in `TimeoutError`.
729
817
 
@@ -732,16 +820,17 @@ Avoid importing it by name: it shadows Python's built-in `TimeoutError`.
732
820
  See the dedicated [examples documentation](https://github.com/captcha-solver-api/python-sdk/blob/main/examples/README.md) for the full
733
821
  sync/async example list, setup steps, expected results, and placeholder guidance.
734
822
 
735
- - **Image/click captchas** (`image_to_text.py`, `coordinates.py`) run after installing the dependencies and setting a valid
823
+ - **Image/click captchas** (`image_to_text.py`, `coordinates.py`,
824
+ `yandex_smartcaptcha_image.py`) run after installing the dependencies and setting a valid
736
825
  `CAPTCHA_API_KEY` -- they read sample images bundled in
737
826
  [examples/assets](https://github.com/captcha-solver-api/python-sdk/tree/main/examples/assets), no target page needed.
738
827
  `python-dotenv` is optional: install it only if you want the scripts to load a `.env` file.
739
- - **Token captchas** (`recaptcha_v2.py`, `recaptcha_v2_enterprise.py`, `recaptcha_v3.py`,
740
- `turnstile.py`, `yandex_smartcaptcha.py`, `geetest_v4.py`, `tencent.py`) use
828
+ - **Token captchas** (`recaptcha_v2_*.py`, `recaptcha_v2_enterprise_*.py`, `recaptcha_v3.py`,
829
+ `turnstile_*.py`, `yandex_smartcaptcha_*.py`, `geetest_v4_*.py`, `tencent_*.py`) use
741
830
  placeholder values (`https://example.com/...`, `YOUR_WEBSITE_KEY`, `YOUR_APP_ID`,
742
831
  `YOUR_CAPTCHA_ID`) -- replace these with the real values from your own target
743
832
  page before running.
744
- - **`geetest_v3.py`** additionally needs `challenge` fetched fresh for every
833
+ - **`geetest_v3_*.py`** additionally needs `challenge` fetched fresh for every
745
834
  request -- it's single-use and expires within seconds, so it can't be
746
835
  hardcoded into a static example. `"https://target-site.com/path/to/geetest/init"`
747
836
  is a placeholder; replace it with a request to your own target's equivalent
@@ -757,6 +846,7 @@ export CAPTCHA_API_KEY=your_api_key
757
846
  python examples/sync/balance.py
758
847
  python examples/sync/image_to_text.py
759
848
  python examples/sync/coordinates.py
849
+ python examples/sync/yandex_smartcaptcha_image.py
760
850
  ```
761
851
 
762
852
  Live checks with real parameters have exercised all supported task types.
@@ -781,8 +871,8 @@ Full API reference: https://captcha-solver.com/en/docs/captcha-types
781
871
  - [Selenium Python examples](https://github.com/captcha-solver-api/captcha-solver-selenium-python-examples)
782
872
  - [JavaScript examples](https://github.com/captcha-solver-api/javascript-examples)
783
873
  - [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.
874
+ - [Cloudflare Turnstile Puppeteer Demo](https://github.com/captcha-solver-api/cloudflare-turnstile-puppeteer-demo) - a working browser automation example for Cloudflare Turnstile.
875
+ - [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
876
 
787
877
  ## License
788
878
 
@@ -21,6 +21,7 @@ Full API reference (all endpoints, error codes, captcha-type details): **https:/
21
21
  ## Table of Contents
22
22
 
23
23
  - [Installation](#installation)
24
+ - [Editor documentation](#editor-documentation)
24
25
  - [Configuration](#configuration)
25
26
  - [Quick Start](#quick-start)
26
27
  - [Build Faster with AI](#build-faster-with-ai)
@@ -66,6 +67,35 @@ Or install the latest version from GitHub:
66
67
  pip install git+https://github.com/captcha-solver-api/python-sdk.git
67
68
  ```
68
69
 
70
+ ## Editor documentation
71
+
72
+ The SDK includes Python docstrings (the equivalent of JSDoc), type annotations,
73
+ and a `py.typed` marker in the installed package. With Python language support
74
+ enabled in your editor, hover over `CaptchaClient`, `AsyncCaptchaClient`, their
75
+ methods, or a task class such as `RecaptchaV2TaskProxyless` to read the documentation.
76
+ Signature help shows argument names, types, and defaults while you type a call.
77
+
78
+ The `captcha_solver_api/py.typed` file is intentionally empty. It is the standard
79
+ [PEP 561](https://peps.python.org/pep-0561/) marker that tells type checkers to use
80
+ the inline type annotations shipped with this package.
81
+
82
+ Docstrings describe parameters, solution fields, exceptions, and usage examples.
83
+ Task examples assume an existing synchronous `client`; with `AsyncCaptchaClient`,
84
+ use `solution = await client.solve(task)` instead. Async snippets run inside an
85
+ `async def` function. In VS Code, select the Python interpreter where the SDK is
86
+ installed and enable the Python and Pylance extensions. In PyCharm, use Quick
87
+ Documentation. The exact presentation depends on the editor.
88
+
89
+ You can also read the same documentation without an editor:
90
+
91
+ ```python
92
+ from captcha_solver_api import CaptchaClient
93
+ from captcha_solver_api.tasks import RecaptchaV2TaskProxyless
94
+
95
+ help(CaptchaClient.solve)
96
+ help(RecaptchaV2TaskProxyless)
97
+ ```
98
+
69
99
  ## Configuration
70
100
 
71
101
  The client always takes the API key as an explicit argument -- it does not read
@@ -125,15 +155,19 @@ on the target page.
125
155
  |---|---|---|
126
156
  | reCAPTCHA v2 | ✅ | ✅ |
127
157
  | reCAPTCHA v2 Enterprise | ✅ | ✅ |
128
- | reCAPTCHA v3 | ✅ | ❌ |
158
+ | reCAPTCHA v3 | ✅ | - |
129
159
  | Cloudflare Turnstile | ✅ | ✅ |
130
160
  | GeeTest v3 | ✅ | ✅ |
131
161
  | GeeTest v4 | ✅ | ✅ |
132
- | Image to Text | ✅ | ❌ |
162
+ | Image to Text | ✅ | - |
133
163
  | Yandex SmartCaptcha | ✅ | ✅ |
134
- | Coordinates (click captcha) | ✅ | ❌ |
164
+ | Yandex SmartCaptcha Image | ✅ | - |
165
+ | Coordinates (click captcha) | ✅ | - |
135
166
  | Tencent | ✅ | ✅ |
136
167
 
168
+ A dash (`-`) means that this CAPTCHA type has no separate task class that accepts
169
+ your own proxy; it does not indicate that solving the CAPTCHA is unsupported.
170
+
137
171
  ## Client Reference
138
172
 
139
173
  Every method below is available on both `CaptchaClient` (sync, `requests`-based) and
@@ -181,14 +215,17 @@ solution -- wraps `create_task()` + `get_task_result()` so you don't poll by han
181
215
 
182
216
  Returns the `solution` dict once `status` is `"ready"` -- its shape depends on
183
217
  the task type (see [Captcha Types](#captcha-types)).
184
- Raises `ApiError`, `CaptchaTimeoutError`, or `NetworkError`.
218
+ Raises `ValidationError` before any request if `task` is not a task object or a
219
+ required task parameter is missing or empty. Otherwise raises `ApiError`,
220
+ `CaptchaTimeoutError`, or `NetworkError`.
185
221
 
186
222
  ### `create_task(task, language_pool=None)`
187
223
 
188
224
  Submits `task` and returns its numeric task ID without waiting for a solution.
189
225
  Accepts `task` and `language_pool`; it does not accept `timeout`. Use this instead of `solve()` if you need to
190
226
  manage polling yourself (e.g. checking on many tasks from a different process).
191
- Raises `ApiError`, `CaptchaTimeoutError`, or `NetworkError`.
227
+ Raises `ValidationError` before any request if `task` is invalid (same rules as
228
+ `solve()`). Otherwise raises `ApiError`, `CaptchaTimeoutError`, or `NetworkError`.
192
229
 
193
230
  ### `get_task_result(task_id)`
194
231
 
@@ -453,7 +490,7 @@ print(result["validate"])
453
490
  print(result["seccode"])
454
491
  ```
455
492
  `challenge` is session-specific and expires quickly, so it can't be hardcoded
456
- into a static example -- see [examples/sync/geetest_v3.py](https://github.com/captcha-solver-api/python-sdk/blob/main/examples/sync/geetest_v3.py)
493
+ into a static example -- see [examples/sync/geetest_v3_proxyless.py](https://github.com/captcha-solver-api/python-sdk/blob/main/examples/sync/geetest_v3_proxyless.py)
457
494
  for where the fetch belongs in the flow.
458
495
 
459
496
  ```python
@@ -473,11 +510,9 @@ With proxy, use `GeeTestTask` (same proxy fields as reCAPTCHA v2).
473
510
  <sup>[API method description.](https://captcha-solver.com/en/docs/captcha-types#yandex-smartcaptcha)</sup>
474
511
 
475
512
  Use this method to solve the token-based Yandex SmartCaptcha and obtain a token
476
- for the widget on the target page. Use the coordinates method for image challenges.
513
+ for the widget on the target page. Use the dedicated image method for image challenges.
477
514
 
478
- `YandexSmartCaptchaTaskProxyless` / `YandexSmartCaptchaTask` -- token-based
479
- challenge. For the image challenge instead, use `CoordinatesTask` with
480
- [Coordinates](#coordinates-click-captcha) is available for generic click captchas.
515
+ `YandexSmartCaptchaTaskProxyless` / `YandexSmartCaptchaTask` -- token-based challenge.
481
516
 
482
517
  | Parameter | Required | Description |
483
518
  |---|---|---|
@@ -506,15 +541,45 @@ print(result["token"])
506
541
  With proxy, use `YandexSmartCaptchaTask` (same proxy fields as reCAPTCHA v2,
507
542
  plus the `https` option above).
508
543
 
544
+ #### Image challenge
545
+
546
+ Use `YandexSmartCaptchaImageTask` when SmartCaptcha shows a main image and a
547
+ separate strip indicating the symbols to click. The SDK sends API v2 type
548
+ `SmartCaptchaTask`; both images must be base64-encoded.
549
+
550
+ | Parameter | Required | Description |
551
+ |---|---|---|
552
+ | `image` | yes | Main captcha image, base64-encoded. |
553
+ | `imgInstructions` | yes | Click-order instruction image, base64-encoded. |
554
+ | `comment` | no | Optional text hint for the worker. |
555
+
556
+ **Response:** `coordinates` -- ordered `{"x": int, "y": int}` click positions.
557
+
558
+ ```python
559
+ import base64
560
+ from captcha_solver_api import CaptchaClient
561
+ from captcha_solver_api.tasks import YandexSmartCaptchaImageTask
562
+
563
+ with open("captcha.png", "rb") as f:
564
+ image = base64.b64encode(f.read()).decode("utf-8")
565
+ with open("instructions.png", "rb") as f:
566
+ instructions = base64.b64encode(f.read()).decode("utf-8")
567
+
568
+ task = YandexSmartCaptchaImageTask(
569
+ image=image,
570
+ imgInstructions=instructions,
571
+ )
572
+ result = CaptchaClient("your_api_key").solve(task)
573
+ print(result["coordinates"])
574
+ ```
575
+
509
576
  ### Coordinates (click captcha)
510
577
 
511
578
  <sup>[API method description.](https://captcha-solver.com/en/docs/captcha-types#coordinates)</sup>
512
579
 
513
- Use this method to identify points that a worker should click in an image. It
514
- supports generic click captchas and the image version of Yandex SmartCaptcha.
580
+ Use this method to identify points that a worker should click in a generic image.
515
581
 
516
- `CoordinatesTask`. Used both for generic "click on X" captchas and for Yandex
517
- SmartCaptcha's image challenge. No proxy variant -- the image is submitted directly.
582
+ `CoordinatesTask`. No proxy variant -- the image is submitted directly.
518
583
 
519
584
  | Parameter | Required | Description |
520
585
  |---|---|---|
@@ -608,6 +673,16 @@ task lifetime. A local timeout does not cancel a task or mean that the API
608
673
  failed to solve it. Use `create_task()` and keep its `task_id` if you need to
609
674
  check the same task later; calling `solve()` again creates a new task.
610
675
 
676
+ While polling, `solve()` retries short network failures and HTTP timeouts of
677
+ `getTaskResult` on the next poll, so a brief outage does not lose an already
678
+ created task. After `poll_retries` (default 3) consecutive failures the error is
679
+ raised. API errors are not retried, and `createTask` is never retried because
680
+ that could create and pay for a second task. To change the limit:
681
+
682
+ ```python
683
+ client.poll_retries = 5
684
+ ```
685
+
611
686
  ### Worker language pool
612
687
 
613
688
  Set a default `language_pool` once at construction instead of passing it to every call:
@@ -677,13 +752,26 @@ try:
677
752
  except ValidationError as e:
678
753
  print(f"Invalid argument: {e}")
679
754
  except ApiError as e:
680
- print(f"API error: {e.error_code} {e.error_description}")
681
- except CaptchaTimeoutError:
682
- print("Task timed out")
755
+ print(f"API error: {e.error_code} {e.error_description} (task {e.task_id})")
756
+ except CaptchaTimeoutError as e:
757
+ print(f"Task {e.task_id} timed out")
683
758
  except NetworkError as e:
684
759
  print(f"Network error: {e}")
685
760
  ```
686
761
 
762
+ Every SDK error has a `task_id` attribute. It is set when the error happens
763
+ after the task was created (while polling in `solve()` or in `get_task_result()`)
764
+ and is `None` otherwise. A polling timeout does not cancel the task, so you can
765
+ keep checking it:
766
+
767
+ ```python
768
+ try:
769
+ result = client.solve(task)
770
+ except CaptchaTimeoutError as e:
771
+ if e.task_id is not None:
772
+ status = client.get_task_result(e.task_id)
773
+ ```
774
+
687
775
  `TimeoutError` is still exported as a deprecated alias of `CaptchaTimeoutError`.
688
776
  Avoid importing it by name: it shadows Python's built-in `TimeoutError`.
689
777
 
@@ -692,16 +780,17 @@ Avoid importing it by name: it shadows Python's built-in `TimeoutError`.
692
780
  See the dedicated [examples documentation](https://github.com/captcha-solver-api/python-sdk/blob/main/examples/README.md) for the full
693
781
  sync/async example list, setup steps, expected results, and placeholder guidance.
694
782
 
695
- - **Image/click captchas** (`image_to_text.py`, `coordinates.py`) run after installing the dependencies and setting a valid
783
+ - **Image/click captchas** (`image_to_text.py`, `coordinates.py`,
784
+ `yandex_smartcaptcha_image.py`) run after installing the dependencies and setting a valid
696
785
  `CAPTCHA_API_KEY` -- they read sample images bundled in
697
786
  [examples/assets](https://github.com/captcha-solver-api/python-sdk/tree/main/examples/assets), no target page needed.
698
787
  `python-dotenv` is optional: install it only if you want the scripts to load a `.env` file.
699
- - **Token captchas** (`recaptcha_v2.py`, `recaptcha_v2_enterprise.py`, `recaptcha_v3.py`,
700
- `turnstile.py`, `yandex_smartcaptcha.py`, `geetest_v4.py`, `tencent.py`) use
788
+ - **Token captchas** (`recaptcha_v2_*.py`, `recaptcha_v2_enterprise_*.py`, `recaptcha_v3.py`,
789
+ `turnstile_*.py`, `yandex_smartcaptcha_*.py`, `geetest_v4_*.py`, `tencent_*.py`) use
701
790
  placeholder values (`https://example.com/...`, `YOUR_WEBSITE_KEY`, `YOUR_APP_ID`,
702
791
  `YOUR_CAPTCHA_ID`) -- replace these with the real values from your own target
703
792
  page before running.
704
- - **`geetest_v3.py`** additionally needs `challenge` fetched fresh for every
793
+ - **`geetest_v3_*.py`** additionally needs `challenge` fetched fresh for every
705
794
  request -- it's single-use and expires within seconds, so it can't be
706
795
  hardcoded into a static example. `"https://target-site.com/path/to/geetest/init"`
707
796
  is a placeholder; replace it with a request to your own target's equivalent
@@ -717,6 +806,7 @@ export CAPTCHA_API_KEY=your_api_key
717
806
  python examples/sync/balance.py
718
807
  python examples/sync/image_to_text.py
719
808
  python examples/sync/coordinates.py
809
+ python examples/sync/yandex_smartcaptcha_image.py
720
810
  ```
721
811
 
722
812
  Live checks with real parameters have exercised all supported task types.
@@ -741,8 +831,8 @@ Full API reference: https://captcha-solver.com/en/docs/captcha-types
741
831
  - [Selenium Python examples](https://github.com/captcha-solver-api/captcha-solver-selenium-python-examples)
742
832
  - [JavaScript examples](https://github.com/captcha-solver-api/javascript-examples)
743
833
  - [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.
834
+ - [Cloudflare Turnstile Puppeteer Demo](https://github.com/captcha-solver-api/cloudflare-turnstile-puppeteer-demo) - a working browser automation example for Cloudflare Turnstile.
835
+ - [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
836
 
747
837
  ## License
748
838
 
@@ -0,0 +1 @@
1
+ __version__ = "1.1.0"