capskip 1.0.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.
- capskip-1.0.0/CHANGELOG.md +31 -0
- capskip-1.0.0/LICENSE +21 -0
- capskip-1.0.0/MANIFEST.in +10 -0
- capskip-1.0.0/PKG-INFO +301 -0
- capskip-1.0.0/README.md +268 -0
- capskip-1.0.0/SECURITY.md +35 -0
- capskip-1.0.0/capskip/__init__.py +29 -0
- capskip-1.0.0/capskip/_api_params.py +118 -0
- capskip-1.0.0/capskip/api.py +56 -0
- capskip-1.0.0/capskip/async_api.py +63 -0
- capskip-1.0.0/capskip/async_solver.py +123 -0
- capskip-1.0.0/capskip/exceptions.py +21 -0
- capskip-1.0.0/capskip/solver.py +163 -0
- capskip-1.0.0/capskip.egg-info/PKG-INFO +301 -0
- capskip-1.0.0/capskip.egg-info/SOURCES.txt +39 -0
- capskip-1.0.0/capskip.egg-info/dependency_links.txt +1 -0
- capskip-1.0.0/capskip.egg-info/requires.txt +8 -0
- capskip-1.0.0/capskip.egg-info/top_level.txt +1 -0
- capskip-1.0.0/docs/API_REFERENCE.md +306 -0
- capskip-1.0.0/docs/GETTING_STARTED.md +181 -0
- capskip-1.0.0/docs/TROUBLESHOOTING.md +203 -0
- capskip-1.0.0/docs/TUTORIAL.md +487 -0
- capskip-1.0.0/examples/async_example.py +32 -0
- capskip-1.0.0/examples/captcha.png +0 -0
- capskip-1.0.0/examples/image_captcha.py +18 -0
- capskip-1.0.0/examples/recaptcha.py +18 -0
- capskip-1.0.0/examples/turnstile.py +19 -0
- capskip-1.0.0/examples/verify_connection.py +41 -0
- capskip-1.0.0/pyproject.toml +63 -0
- capskip-1.0.0/setup.cfg +4 -0
- capskip-1.0.0/setup.py +9 -0
- capskip-1.0.0/tests/abstract.py +63 -0
- capskip-1.0.0/tests/abstract_async.py +47 -0
- capskip-1.0.0/tests/conftest.py +113 -0
- capskip-1.0.0/tests/test_async_normal.py +35 -0
- capskip-1.0.0/tests/test_async_recaptcha.py +76 -0
- capskip-1.0.0/tests/test_async_turnstile.py +62 -0
- capskip-1.0.0/tests/test_integration.py +185 -0
- capskip-1.0.0/tests/test_normal.py +55 -0
- capskip-1.0.0/tests/test_recaptcha.py +95 -0
- capskip-1.0.0/tests/test_turnstile.py +72 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [1.0.0] - 2026-07-14
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- Initial release of the CapSkip Python SDK
|
|
13
|
+
- `CapSkip` synchronous client for the local CapSkip API
|
|
14
|
+
- `AsyncCapSkip` asynchronous client (`httpx` + `aiofiles`)
|
|
15
|
+
- Image CAPTCHA solving via `normal()` (file, URL, base64, or data-URI)
|
|
16
|
+
- reCAPTCHA v2 / v3 solving via `recaptcha()` (invisible, enterprise, proxy)
|
|
17
|
+
- Cloudflare Turnstile solving via `turnstile()` (widget and challenge page)
|
|
18
|
+
- Turnstile automatically polls with `json=1` and returns `userAgent` when provided
|
|
19
|
+
- Manual workflow: `send()`, `get_result()`, `solve()`
|
|
20
|
+
- Adaptive result polling — starts at 0.25s and backs off (doubling) up to the
|
|
21
|
+
configured `pollingInterval`, so fast solves (e.g. image captchas) return in a
|
|
22
|
+
fraction of a second; `pollingInterval` also accepts sub-second (float) values
|
|
23
|
+
- Familiar parameter aliases (`url`→`pageurl`, `score`→`min_score`, etc.)
|
|
24
|
+
- Proxy support via dict format `{'type': '...', 'uri': '...'}`
|
|
25
|
+
- Strict per-captcha parameter validation — only documented parameters are accepted
|
|
26
|
+
- Exception hierarchy: `ValidationException`, `NetworkException`, `ApiException`, `TimeoutException`
|
|
27
|
+
- Example scripts for every supported captcha type
|
|
28
|
+
- Unit tests (sync + async) with a mocked API client
|
|
29
|
+
- Documentation: Tutorial, Getting Started, API Reference, Troubleshooting
|
|
30
|
+
|
|
31
|
+
[1.0.0]: https://github.com/capskip/capskip-python/releases/tag/v1.0.0
|
capskip-1.0.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 CapSkip
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
include LICENSE
|
|
2
|
+
include README.md
|
|
3
|
+
include CHANGELOG.md
|
|
4
|
+
include SECURITY.md
|
|
5
|
+
recursive-include docs *.md
|
|
6
|
+
recursive-include examples *.py
|
|
7
|
+
recursive-include examples *.png
|
|
8
|
+
recursive-include tests *.py
|
|
9
|
+
global-exclude __pycache__
|
|
10
|
+
global-exclude *.py[cod]
|
capskip-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: capskip
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Python SDK for the CapSkip local captcha solver
|
|
5
|
+
Author-email: CapSkip <support@capskip.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://capskip.com
|
|
8
|
+
Project-URL: Documentation, https://github.com/capskip/capskip-python/blob/main/docs/GETTING_STARTED.md
|
|
9
|
+
Project-URL: Repository, https://github.com/capskip/capskip-python
|
|
10
|
+
Project-URL: Bug Tracker, https://github.com/capskip/capskip-python/issues
|
|
11
|
+
Project-URL: Changelog, https://github.com/capskip/capskip-python/blob/main/CHANGELOG.md
|
|
12
|
+
Keywords: captcha,captcha-solver,recaptcha,cloudflare,turnstile,capskip,automation
|
|
13
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
21
|
+
Classifier: Topic :: Internet :: WWW/HTTP
|
|
22
|
+
Requires-Python: >=3.10
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
License-File: LICENSE
|
|
25
|
+
Requires-Dist: requests>=2.28
|
|
26
|
+
Requires-Dist: httpx>=0.24
|
|
27
|
+
Requires-Dist: aiofiles>=23.0
|
|
28
|
+
Provides-Extra: dev
|
|
29
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
30
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == "dev"
|
|
31
|
+
Requires-Dist: pytest-cov>=5.0; extra == "dev"
|
|
32
|
+
Dynamic: license-file
|
|
33
|
+
|
|
34
|
+
# CapSkip Python SDK
|
|
35
|
+
|
|
36
|
+
[](https://www.python.org/downloads/)
|
|
37
|
+
[](LICENSE)
|
|
38
|
+
[](https://github.com/capskip/capskip-python/actions/workflows/ci.yml)
|
|
39
|
+
|
|
40
|
+
Official Python client for the [CapSkip](https://capskip.com) **local** captcha solver.
|
|
41
|
+
|
|
42
|
+
CapSkip runs on your machine and exposes a standard captcha-solver HTTP API (the familiar `in.php` / `res.php` endpoints). This SDK wraps that API with clean, familiar method names, so you can solve captchas locally — no cloud service and no per-solve API fees beyond your CapSkip license.
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Quick start (5 minutes)
|
|
47
|
+
|
|
48
|
+
### 1. Install CapSkip
|
|
49
|
+
|
|
50
|
+
Download and run the CapSkip desktop app from [capskip.com](https://capskip.com). Leave it running in the background.
|
|
51
|
+
|
|
52
|
+
In CapSkip settings, note:
|
|
53
|
+
|
|
54
|
+
- **API port** (default: `8080`)
|
|
55
|
+
- **API key** (optional — if validation is disabled, any string works)
|
|
56
|
+
|
|
57
|
+
### 2. Install the SDK
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
pip install capskip
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Or from source:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
git clone https://github.com/capskip/capskip-python.git
|
|
67
|
+
cd capskip-python
|
|
68
|
+
pip install -e .
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### 3. Solve your first captcha
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
from capskip import CapSkip
|
|
75
|
+
|
|
76
|
+
solver = CapSkip(host="127.0.0.1", port=8080)
|
|
77
|
+
|
|
78
|
+
result = solver.recaptcha(
|
|
79
|
+
sitekey="YOUR_SITEKEY",
|
|
80
|
+
url="https://example.com/page-with-recaptcha",
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
print(result["code"]) # g-recaptcha-response token
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
> **Prerequisite:** CapSkip must be running before you call the SDK. If you see a connection error, see [Troubleshooting](docs/TROUBLESHOOTING.md).
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## Supported captcha types
|
|
91
|
+
|
|
92
|
+
| Type | SDK method |
|
|
93
|
+
|---|---|
|
|
94
|
+
| Image CAPTCHA (distorted text) | `solver.normal(file)` |
|
|
95
|
+
| reCAPTCHA v2 (checkbox) | `solver.recaptcha(sitekey, url)` |
|
|
96
|
+
| reCAPTCHA v2 Invisible | `solver.recaptcha(..., invisible=1)` |
|
|
97
|
+
| reCAPTCHA v2 Enterprise | `solver.recaptcha(..., enterprise=1)` |
|
|
98
|
+
| reCAPTCHA v3 | `solver.recaptcha(..., version="v3")` |
|
|
99
|
+
| reCAPTCHA v3 Enterprise | `solver.recaptcha(..., version="v3", enterprise=1)` |
|
|
100
|
+
| Cloudflare Turnstile (widget) | `solver.turnstile(sitekey, url)` |
|
|
101
|
+
| Cloudflare Turnstile (challenge page) | `solver.turnstile(..., data=..., pagedata=...)` |
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## Documentation
|
|
106
|
+
|
|
107
|
+
| Guide | Description |
|
|
108
|
+
|---|---|
|
|
109
|
+
| [Tutorial](docs/TUTORIAL.md) | Complete walkthrough of every captcha type, sync and async |
|
|
110
|
+
| [Getting Started](docs/GETTING_STARTED.md) | Full setup: CapSkip app, SDK install, first script |
|
|
111
|
+
| [API Reference](docs/API_REFERENCE.md) | All classes, methods, parameters, and return values |
|
|
112
|
+
| [Examples](examples/) | Ready-to-run scripts for every captcha type |
|
|
113
|
+
| [Troubleshooting](docs/TROUBLESHOOTING.md) | Connection errors, timeouts, proxy issues |
|
|
114
|
+
| [Contributing](CONTRIBUTING.md) | Development setup, tests, pull requests |
|
|
115
|
+
| [Changelog](CHANGELOG.md) | Release history |
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## Configuration
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
from capskip import CapSkip
|
|
123
|
+
|
|
124
|
+
solver = CapSkip(
|
|
125
|
+
apiKey="capskip", # your CapSkip API key (or any string if validation is off)
|
|
126
|
+
host="127.0.0.1", # CapSkip host
|
|
127
|
+
port=8080, # CapSkip port from app settings
|
|
128
|
+
defaultTimeout=120, # seconds — image captcha polling timeout
|
|
129
|
+
recaptchaTimeout=300, # seconds — reCAPTCHA / Turnstile polling timeout
|
|
130
|
+
pollingInterval=5, # max seconds between res.php polls (starts at 0.25s, backs off to this)
|
|
131
|
+
)
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Use environment variables in production:
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
# Linux / macOS
|
|
138
|
+
export CAPSKIP_API_KEY="your-key"
|
|
139
|
+
export CAPSKIP_HOST="127.0.0.1"
|
|
140
|
+
export CAPSKIP_PORT="8080"
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
```powershell
|
|
144
|
+
# Windows PowerShell
|
|
145
|
+
$env:CAPSKIP_API_KEY = "your-key"
|
|
146
|
+
$env:CAPSKIP_HOST = "127.0.0.1"
|
|
147
|
+
$env:CAPSKIP_PORT = "8080"
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
```python
|
|
151
|
+
import os
|
|
152
|
+
from capskip import CapSkip
|
|
153
|
+
|
|
154
|
+
solver = CapSkip(
|
|
155
|
+
apiKey=os.getenv("CAPSKIP_API_KEY", "capskip"),
|
|
156
|
+
host=os.getenv("CAPSKIP_HOST", "127.0.0.1"),
|
|
157
|
+
port=int(os.getenv("CAPSKIP_PORT", "8080")),
|
|
158
|
+
)
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## Usage examples
|
|
164
|
+
|
|
165
|
+
### Image captcha
|
|
166
|
+
|
|
167
|
+
```python
|
|
168
|
+
result = solver.normal("captcha.png")
|
|
169
|
+
result = solver.normal("https://example.com/captcha.jpg")
|
|
170
|
+
result = solver.normal("data:image/png;base64,iVBORw0KGgo...")
|
|
171
|
+
print(result["code"])
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### reCAPTCHA v2 / v3
|
|
175
|
+
|
|
176
|
+
```python
|
|
177
|
+
# reCAPTCHA v2
|
|
178
|
+
result = solver.recaptcha(sitekey="...", url="https://example.com")
|
|
179
|
+
|
|
180
|
+
# reCAPTCHA v3
|
|
181
|
+
result = solver.recaptcha(
|
|
182
|
+
sitekey="...",
|
|
183
|
+
url="https://example.com",
|
|
184
|
+
version="v3",
|
|
185
|
+
action="submit",
|
|
186
|
+
score=0.7,
|
|
187
|
+
)
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### Cloudflare Turnstile
|
|
191
|
+
|
|
192
|
+
```python
|
|
193
|
+
result = solver.turnstile(
|
|
194
|
+
sitekey="0x4AAAAAAA...",
|
|
195
|
+
url="https://example.com",
|
|
196
|
+
)
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
### With a proxy (reCAPTCHA & Turnstile only)
|
|
200
|
+
|
|
201
|
+
```python
|
|
202
|
+
# Proxy is not supported for image captcha
|
|
203
|
+
result = solver.recaptcha(
|
|
204
|
+
sitekey="...",
|
|
205
|
+
url="https://example.com",
|
|
206
|
+
proxy={"type": "HTTPS", "uri": "user:pass@1.2.3.4:3128"},
|
|
207
|
+
)
|
|
208
|
+
result = solver.turnstile(
|
|
209
|
+
sitekey="...",
|
|
210
|
+
url="https://example.com",
|
|
211
|
+
proxy={"type": "HTTP", "uri": "1.2.3.4:3128"},
|
|
212
|
+
)
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### Async (parallel solving)
|
|
216
|
+
|
|
217
|
+
```python
|
|
218
|
+
import asyncio
|
|
219
|
+
from capskip import AsyncCapSkip
|
|
220
|
+
|
|
221
|
+
async def main():
|
|
222
|
+
solver = AsyncCapSkip()
|
|
223
|
+
r1, r2 = await asyncio.gather(
|
|
224
|
+
solver.recaptcha(sitekey="...", url="https://a.com"),
|
|
225
|
+
solver.turnstile(sitekey="...", url="https://b.com"),
|
|
226
|
+
)
|
|
227
|
+
print(r1["code"], r2["code"])
|
|
228
|
+
|
|
229
|
+
asyncio.run(main())
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
More examples: [`examples/`](examples/)
|
|
233
|
+
|
|
234
|
+
---
|
|
235
|
+
|
|
236
|
+
## Return value
|
|
237
|
+
|
|
238
|
+
Every solve method returns:
|
|
239
|
+
|
|
240
|
+
```python
|
|
241
|
+
{
|
|
242
|
+
"captchaId": "12345", # internal ID from CapSkip
|
|
243
|
+
"code": "TOKEN_OR_TEXT" # solution — text for image, token for reCAPTCHA/Turnstile
|
|
244
|
+
"userAgent": "..." # Turnstile only — use when submitting challenge-page tokens
|
|
245
|
+
}
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
---
|
|
249
|
+
|
|
250
|
+
## Error handling
|
|
251
|
+
|
|
252
|
+
```python
|
|
253
|
+
from capskip import CapSkip, ValidationException, NetworkException, ApiException, TimeoutException
|
|
254
|
+
|
|
255
|
+
try:
|
|
256
|
+
result = solver.recaptcha(sitekey="...", url="...")
|
|
257
|
+
except ValidationException:
|
|
258
|
+
pass # invalid parameters
|
|
259
|
+
except NetworkException:
|
|
260
|
+
pass # CapSkip not running, or captcha not ready (manual polling)
|
|
261
|
+
except ApiException:
|
|
262
|
+
pass # API returned an error code
|
|
263
|
+
except TimeoutException:
|
|
264
|
+
pass # polling timeout exceeded
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
---
|
|
268
|
+
|
|
269
|
+
## Development
|
|
270
|
+
|
|
271
|
+
```bash
|
|
272
|
+
git clone https://github.com/capskip/capskip-python.git
|
|
273
|
+
cd capskip-python
|
|
274
|
+
python -m venv .venv
|
|
275
|
+
|
|
276
|
+
# Windows
|
|
277
|
+
.venv\Scripts\activate
|
|
278
|
+
|
|
279
|
+
# Linux / macOS
|
|
280
|
+
source .venv/bin/activate
|
|
281
|
+
|
|
282
|
+
pip install -e ".[dev]"
|
|
283
|
+
pytest
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for the full development workflow.
|
|
287
|
+
|
|
288
|
+
---
|
|
289
|
+
|
|
290
|
+
## Links
|
|
291
|
+
|
|
292
|
+
- [CapSkip website](https://capskip.com)
|
|
293
|
+
- [CapSkip API docs](https://capskip.com/api-docs/)
|
|
294
|
+
- [Report an issue](https://github.com/capskip/capskip-python/issues)
|
|
295
|
+
- [PyPI package](https://pypi.org/project/capskip/) *(when published)*
|
|
296
|
+
|
|
297
|
+
---
|
|
298
|
+
|
|
299
|
+
## License
|
|
300
|
+
|
|
301
|
+
MIT — see [LICENSE](LICENSE).
|
capskip-1.0.0/README.md
ADDED
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
# CapSkip Python SDK
|
|
2
|
+
|
|
3
|
+
[](https://www.python.org/downloads/)
|
|
4
|
+
[](LICENSE)
|
|
5
|
+
[](https://github.com/capskip/capskip-python/actions/workflows/ci.yml)
|
|
6
|
+
|
|
7
|
+
Official Python client for the [CapSkip](https://capskip.com) **local** captcha solver.
|
|
8
|
+
|
|
9
|
+
CapSkip runs on your machine and exposes a standard captcha-solver HTTP API (the familiar `in.php` / `res.php` endpoints). This SDK wraps that API with clean, familiar method names, so you can solve captchas locally — no cloud service and no per-solve API fees beyond your CapSkip license.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Quick start (5 minutes)
|
|
14
|
+
|
|
15
|
+
### 1. Install CapSkip
|
|
16
|
+
|
|
17
|
+
Download and run the CapSkip desktop app from [capskip.com](https://capskip.com). Leave it running in the background.
|
|
18
|
+
|
|
19
|
+
In CapSkip settings, note:
|
|
20
|
+
|
|
21
|
+
- **API port** (default: `8080`)
|
|
22
|
+
- **API key** (optional — if validation is disabled, any string works)
|
|
23
|
+
|
|
24
|
+
### 2. Install the SDK
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
pip install capskip
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Or from source:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
git clone https://github.com/capskip/capskip-python.git
|
|
34
|
+
cd capskip-python
|
|
35
|
+
pip install -e .
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### 3. Solve your first captcha
|
|
39
|
+
|
|
40
|
+
```python
|
|
41
|
+
from capskip import CapSkip
|
|
42
|
+
|
|
43
|
+
solver = CapSkip(host="127.0.0.1", port=8080)
|
|
44
|
+
|
|
45
|
+
result = solver.recaptcha(
|
|
46
|
+
sitekey="YOUR_SITEKEY",
|
|
47
|
+
url="https://example.com/page-with-recaptcha",
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
print(result["code"]) # g-recaptcha-response token
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
> **Prerequisite:** CapSkip must be running before you call the SDK. If you see a connection error, see [Troubleshooting](docs/TROUBLESHOOTING.md).
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## Supported captcha types
|
|
58
|
+
|
|
59
|
+
| Type | SDK method |
|
|
60
|
+
|---|---|
|
|
61
|
+
| Image CAPTCHA (distorted text) | `solver.normal(file)` |
|
|
62
|
+
| reCAPTCHA v2 (checkbox) | `solver.recaptcha(sitekey, url)` |
|
|
63
|
+
| reCAPTCHA v2 Invisible | `solver.recaptcha(..., invisible=1)` |
|
|
64
|
+
| reCAPTCHA v2 Enterprise | `solver.recaptcha(..., enterprise=1)` |
|
|
65
|
+
| reCAPTCHA v3 | `solver.recaptcha(..., version="v3")` |
|
|
66
|
+
| reCAPTCHA v3 Enterprise | `solver.recaptcha(..., version="v3", enterprise=1)` |
|
|
67
|
+
| Cloudflare Turnstile (widget) | `solver.turnstile(sitekey, url)` |
|
|
68
|
+
| Cloudflare Turnstile (challenge page) | `solver.turnstile(..., data=..., pagedata=...)` |
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## Documentation
|
|
73
|
+
|
|
74
|
+
| Guide | Description |
|
|
75
|
+
|---|---|
|
|
76
|
+
| [Tutorial](docs/TUTORIAL.md) | Complete walkthrough of every captcha type, sync and async |
|
|
77
|
+
| [Getting Started](docs/GETTING_STARTED.md) | Full setup: CapSkip app, SDK install, first script |
|
|
78
|
+
| [API Reference](docs/API_REFERENCE.md) | All classes, methods, parameters, and return values |
|
|
79
|
+
| [Examples](examples/) | Ready-to-run scripts for every captcha type |
|
|
80
|
+
| [Troubleshooting](docs/TROUBLESHOOTING.md) | Connection errors, timeouts, proxy issues |
|
|
81
|
+
| [Contributing](CONTRIBUTING.md) | Development setup, tests, pull requests |
|
|
82
|
+
| [Changelog](CHANGELOG.md) | Release history |
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Configuration
|
|
87
|
+
|
|
88
|
+
```python
|
|
89
|
+
from capskip import CapSkip
|
|
90
|
+
|
|
91
|
+
solver = CapSkip(
|
|
92
|
+
apiKey="capskip", # your CapSkip API key (or any string if validation is off)
|
|
93
|
+
host="127.0.0.1", # CapSkip host
|
|
94
|
+
port=8080, # CapSkip port from app settings
|
|
95
|
+
defaultTimeout=120, # seconds — image captcha polling timeout
|
|
96
|
+
recaptchaTimeout=300, # seconds — reCAPTCHA / Turnstile polling timeout
|
|
97
|
+
pollingInterval=5, # max seconds between res.php polls (starts at 0.25s, backs off to this)
|
|
98
|
+
)
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Use environment variables in production:
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
# Linux / macOS
|
|
105
|
+
export CAPSKIP_API_KEY="your-key"
|
|
106
|
+
export CAPSKIP_HOST="127.0.0.1"
|
|
107
|
+
export CAPSKIP_PORT="8080"
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
```powershell
|
|
111
|
+
# Windows PowerShell
|
|
112
|
+
$env:CAPSKIP_API_KEY = "your-key"
|
|
113
|
+
$env:CAPSKIP_HOST = "127.0.0.1"
|
|
114
|
+
$env:CAPSKIP_PORT = "8080"
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
```python
|
|
118
|
+
import os
|
|
119
|
+
from capskip import CapSkip
|
|
120
|
+
|
|
121
|
+
solver = CapSkip(
|
|
122
|
+
apiKey=os.getenv("CAPSKIP_API_KEY", "capskip"),
|
|
123
|
+
host=os.getenv("CAPSKIP_HOST", "127.0.0.1"),
|
|
124
|
+
port=int(os.getenv("CAPSKIP_PORT", "8080")),
|
|
125
|
+
)
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## Usage examples
|
|
131
|
+
|
|
132
|
+
### Image captcha
|
|
133
|
+
|
|
134
|
+
```python
|
|
135
|
+
result = solver.normal("captcha.png")
|
|
136
|
+
result = solver.normal("https://example.com/captcha.jpg")
|
|
137
|
+
result = solver.normal("data:image/png;base64,iVBORw0KGgo...")
|
|
138
|
+
print(result["code"])
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### reCAPTCHA v2 / v3
|
|
142
|
+
|
|
143
|
+
```python
|
|
144
|
+
# reCAPTCHA v2
|
|
145
|
+
result = solver.recaptcha(sitekey="...", url="https://example.com")
|
|
146
|
+
|
|
147
|
+
# reCAPTCHA v3
|
|
148
|
+
result = solver.recaptcha(
|
|
149
|
+
sitekey="...",
|
|
150
|
+
url="https://example.com",
|
|
151
|
+
version="v3",
|
|
152
|
+
action="submit",
|
|
153
|
+
score=0.7,
|
|
154
|
+
)
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Cloudflare Turnstile
|
|
158
|
+
|
|
159
|
+
```python
|
|
160
|
+
result = solver.turnstile(
|
|
161
|
+
sitekey="0x4AAAAAAA...",
|
|
162
|
+
url="https://example.com",
|
|
163
|
+
)
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### With a proxy (reCAPTCHA & Turnstile only)
|
|
167
|
+
|
|
168
|
+
```python
|
|
169
|
+
# Proxy is not supported for image captcha
|
|
170
|
+
result = solver.recaptcha(
|
|
171
|
+
sitekey="...",
|
|
172
|
+
url="https://example.com",
|
|
173
|
+
proxy={"type": "HTTPS", "uri": "user:pass@1.2.3.4:3128"},
|
|
174
|
+
)
|
|
175
|
+
result = solver.turnstile(
|
|
176
|
+
sitekey="...",
|
|
177
|
+
url="https://example.com",
|
|
178
|
+
proxy={"type": "HTTP", "uri": "1.2.3.4:3128"},
|
|
179
|
+
)
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### Async (parallel solving)
|
|
183
|
+
|
|
184
|
+
```python
|
|
185
|
+
import asyncio
|
|
186
|
+
from capskip import AsyncCapSkip
|
|
187
|
+
|
|
188
|
+
async def main():
|
|
189
|
+
solver = AsyncCapSkip()
|
|
190
|
+
r1, r2 = await asyncio.gather(
|
|
191
|
+
solver.recaptcha(sitekey="...", url="https://a.com"),
|
|
192
|
+
solver.turnstile(sitekey="...", url="https://b.com"),
|
|
193
|
+
)
|
|
194
|
+
print(r1["code"], r2["code"])
|
|
195
|
+
|
|
196
|
+
asyncio.run(main())
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
More examples: [`examples/`](examples/)
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
## Return value
|
|
204
|
+
|
|
205
|
+
Every solve method returns:
|
|
206
|
+
|
|
207
|
+
```python
|
|
208
|
+
{
|
|
209
|
+
"captchaId": "12345", # internal ID from CapSkip
|
|
210
|
+
"code": "TOKEN_OR_TEXT" # solution — text for image, token for reCAPTCHA/Turnstile
|
|
211
|
+
"userAgent": "..." # Turnstile only — use when submitting challenge-page tokens
|
|
212
|
+
}
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
## Error handling
|
|
218
|
+
|
|
219
|
+
```python
|
|
220
|
+
from capskip import CapSkip, ValidationException, NetworkException, ApiException, TimeoutException
|
|
221
|
+
|
|
222
|
+
try:
|
|
223
|
+
result = solver.recaptcha(sitekey="...", url="...")
|
|
224
|
+
except ValidationException:
|
|
225
|
+
pass # invalid parameters
|
|
226
|
+
except NetworkException:
|
|
227
|
+
pass # CapSkip not running, or captcha not ready (manual polling)
|
|
228
|
+
except ApiException:
|
|
229
|
+
pass # API returned an error code
|
|
230
|
+
except TimeoutException:
|
|
231
|
+
pass # polling timeout exceeded
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
---
|
|
235
|
+
|
|
236
|
+
## Development
|
|
237
|
+
|
|
238
|
+
```bash
|
|
239
|
+
git clone https://github.com/capskip/capskip-python.git
|
|
240
|
+
cd capskip-python
|
|
241
|
+
python -m venv .venv
|
|
242
|
+
|
|
243
|
+
# Windows
|
|
244
|
+
.venv\Scripts\activate
|
|
245
|
+
|
|
246
|
+
# Linux / macOS
|
|
247
|
+
source .venv/bin/activate
|
|
248
|
+
|
|
249
|
+
pip install -e ".[dev]"
|
|
250
|
+
pytest
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for the full development workflow.
|
|
254
|
+
|
|
255
|
+
---
|
|
256
|
+
|
|
257
|
+
## Links
|
|
258
|
+
|
|
259
|
+
- [CapSkip website](https://capskip.com)
|
|
260
|
+
- [CapSkip API docs](https://capskip.com/api-docs/)
|
|
261
|
+
- [Report an issue](https://github.com/capskip/capskip-python/issues)
|
|
262
|
+
- [PyPI package](https://pypi.org/project/capskip/) *(when published)*
|
|
263
|
+
|
|
264
|
+
---
|
|
265
|
+
|
|
266
|
+
## License
|
|
267
|
+
|
|
268
|
+
MIT — see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
## Supported versions
|
|
4
|
+
|
|
5
|
+
| Version | Supported |
|
|
6
|
+
|---|---|
|
|
7
|
+
| 1.0.x | Yes |
|
|
8
|
+
|
|
9
|
+
## Reporting a vulnerability
|
|
10
|
+
|
|
11
|
+
If you discover a security vulnerability in the CapSkip Python SDK, please report it responsibly.
|
|
12
|
+
|
|
13
|
+
**Do not** open a public GitHub issue for security vulnerabilities.
|
|
14
|
+
|
|
15
|
+
Instead, email **support@capskip.com** with:
|
|
16
|
+
|
|
17
|
+
- Description of the vulnerability
|
|
18
|
+
- Steps to reproduce
|
|
19
|
+
- Potential impact
|
|
20
|
+
- Suggested fix (if any)
|
|
21
|
+
|
|
22
|
+
We aim to acknowledge reports within 48 hours and provide a status update within 7 days.
|
|
23
|
+
|
|
24
|
+
## Scope
|
|
25
|
+
|
|
26
|
+
This policy covers the `capskip` Python package in this repository.
|
|
27
|
+
|
|
28
|
+
The CapSkip desktop application itself is maintained separately — report app-level issues to CapSkip support.
|
|
29
|
+
|
|
30
|
+
## Best practices for SDK users
|
|
31
|
+
|
|
32
|
+
- Do not commit API keys or captcha tokens to version control
|
|
33
|
+
- Use environment variables for `CAPSKIP_API_KEY`
|
|
34
|
+
- CapSkip runs locally — ensure your firewall rules match your security requirements
|
|
35
|
+
- When using proxies, avoid logging credentials in application logs
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"""CapSkip Python SDK — local captcha solver client."""
|
|
2
|
+
|
|
3
|
+
from .api import ApiClient
|
|
4
|
+
from .async_api import AsyncApiClient
|
|
5
|
+
from .async_solver import AsyncCapSkip
|
|
6
|
+
from .exceptions import (
|
|
7
|
+
ApiException,
|
|
8
|
+
CapSkipError,
|
|
9
|
+
NetworkException,
|
|
10
|
+
SolverExceptions,
|
|
11
|
+
TimeoutException,
|
|
12
|
+
ValidationException,
|
|
13
|
+
)
|
|
14
|
+
from .solver import CapSkip
|
|
15
|
+
|
|
16
|
+
__all__ = [
|
|
17
|
+
'CapSkip',
|
|
18
|
+
'AsyncCapSkip',
|
|
19
|
+
'ApiClient',
|
|
20
|
+
'AsyncApiClient',
|
|
21
|
+
'CapSkipError',
|
|
22
|
+
'SolverExceptions',
|
|
23
|
+
'ValidationException',
|
|
24
|
+
'NetworkException',
|
|
25
|
+
'ApiException',
|
|
26
|
+
'TimeoutException',
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
__version__ = '1.0.0'
|