capskip 1.2.0 → 1.4.0
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.
- package/CHANGELOG.md +84 -0
- package/README.md +139 -8
- package/docs/API_REFERENCE.md +386 -3
- package/examples/amazon_waf.js +97 -0
- package/examples/captchafox.js +102 -0
- package/examples/capy.js +101 -0
- package/examples/friendly_captcha.js +115 -0
- package/package.json +4 -2
- package/src/apiParams.js +249 -0
- package/src/index.js +1 -1
- package/src/solver.js +278 -1
- package/types/index.d.ts +193 -5
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,90 @@ All notable changes to this project are documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [1.4.0] - 2026-11-01
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **AWS WAF support** via `amazonWaf(sitekey, url, options)`, sent as
|
|
13
|
+
`method=amazon_waf`. Only `sitekey` and `url` are required.
|
|
14
|
+
On a challenge page (the HTTP 405 page with `window.gokuProps`), `sitekey`,
|
|
15
|
+
`iv` and `context` are `gokuProps.key`, `.iv` and `.context`, and
|
|
16
|
+
`challenge_script` / `captcha_script` are the page's challenge.js and
|
|
17
|
+
captcha.js. On a widget page (`AwsWafCaptcha.renderCaptcha`), `sitekey` is the
|
|
18
|
+
widget's `apiKey` and `jsapiScript` the URL of jsapi.js.
|
|
19
|
+
An AWS WAF answer is **not a token**: the result expands into
|
|
20
|
+
`captcha_voucher` and `existing_token`, which the site's `voucher` endpoint
|
|
21
|
+
(beside challenge.js) trades for the `aws-waf-token` cookie. `code` keeps the
|
|
22
|
+
raw answer.
|
|
23
|
+
- Parameter aliases `challengeScript` for `challenge_script`, `captchaScript`
|
|
24
|
+
for `captcha_script`, and `jsapi_script` for `jsapiScript`.
|
|
25
|
+
- TypeScript definitions for `AmazonWafOptions`, plus the new `SolveResult`
|
|
26
|
+
fields.
|
|
27
|
+
- `examples/amazon_waf.js`.
|
|
28
|
+
|
|
29
|
+
### Changed
|
|
30
|
+
|
|
31
|
+
- The Capy answer expansion is now a shared helper, used by Capy and AWS WAF
|
|
32
|
+
alike. Capy results are unchanged.
|
|
33
|
+
- The exported `version` constant now reports the package version; it had been
|
|
34
|
+
left at `1.1.0`.
|
|
35
|
+
|
|
36
|
+
### Notes
|
|
37
|
+
|
|
38
|
+
- `iv` and `context` are optional but travel together: one without the other is
|
|
39
|
+
refused locally, as the server would refuse it. Left out, CapSkip reads both
|
|
40
|
+
from the page at solve time. An optional passed as `''` is treated as not
|
|
41
|
+
sent, the way the server reads it.
|
|
42
|
+
- Every script URL must be `https` on an `awswaf.com` host, with no credentials,
|
|
43
|
+
no port other than 443, and a path ending in `challenge.js`, `captcha.js` or
|
|
44
|
+
`jsapi.js`. CapSkip posts the solution to the host the script names, so any
|
|
45
|
+
other script is refused before the request is made.
|
|
46
|
+
- AWS WAF uses `recaptchaTimeout`: a real browser mints the token the voucher is
|
|
47
|
+
issued for.
|
|
48
|
+
|
|
49
|
+
## [1.3.0] - 2026-09-22
|
|
50
|
+
|
|
51
|
+
### Added
|
|
52
|
+
|
|
53
|
+
- **Capy Puzzle support** via `capy(sitekey, url, options)`. The site key
|
|
54
|
+
(conventionally prefixed `PUZZLE_`) is sent as the `captchakey` the API
|
|
55
|
+
documents. Optional `api_server` selects the Capy API the key lives behind,
|
|
56
|
+
defaulting to `https://jp.api.capy.me`.
|
|
57
|
+
A Capy answer is **not a token**: the result expands into `captchakey`,
|
|
58
|
+
`challengekey` and `answer`, which go into the target form's `capy_captchakey`,
|
|
59
|
+
`capy_challengekey` and `capy_answer` fields. `code` keeps the raw answer.
|
|
60
|
+
- **CaptchaFox support** via `captchafox(sitekey, url, options)`. The result
|
|
61
|
+
exposes `token` (for the form's `cf-captcha-response` field) and, when the
|
|
62
|
+
solve reported one, `userAgent` — the UA the browser actually minted the token
|
|
63
|
+
under, which is not the one you sent. Optional `api_server` selects the widget
|
|
64
|
+
source; the MAM package returns a `MAM_` prefixed token.
|
|
65
|
+
- **Friendly Captcha support** via `friendlyCaptcha(sitekey, url, options)`.
|
|
66
|
+
Pass `version` (`v1`/`v2`, or a bare `1`/`2`), or `moduleScript` /
|
|
67
|
+
`nomoduleScript` with the widget script URLs and let CapSkip read the version
|
|
68
|
+
off the build the site actually loads. Optional `api_server` accepts `global`
|
|
69
|
+
(the default), `eu`, or a full URL for the data-residency tenant. The result
|
|
70
|
+
exposes `token`, for `frc-captcha-solution` on v1 or `frc-captcha-response` on
|
|
71
|
+
v2.
|
|
72
|
+
- Parameter aliases `userAgent`/`user_agent` for `useragent`, `captchaKey` for
|
|
73
|
+
`captchakey`, and `moduleScript`/`nomoduleScript` for `module_script` /
|
|
74
|
+
`nomodule_script`.
|
|
75
|
+
- TypeScript definitions for `CapyOptions`, `CaptchaFoxOptions` and
|
|
76
|
+
`FriendlyCaptchaOptions`, plus the new `SolveResult` fields.
|
|
77
|
+
|
|
78
|
+
### Notes
|
|
79
|
+
|
|
80
|
+
- `version: 'avatar'` is refused locally for Capy. CapSkip solves the puzzle
|
|
81
|
+
family only, and answering an avatar request with a puzzle answer would bill
|
|
82
|
+
for a solve the target site rejects, indistinguishably from a broken solver.
|
|
83
|
+
- An unknown Friendly Captcha `version` is refused locally too. The two versions
|
|
84
|
+
are different protocols sharing one sitekey namespace, so solving the wrong one
|
|
85
|
+
returns a well-formed token the site rejects with nothing to indicate why.
|
|
86
|
+
- CaptchaFox and Friendly Captcha use `recaptchaTimeout`: the first is a real
|
|
87
|
+
browser solve, and the second has its difficulty set per request by the service
|
|
88
|
+
(and always solves in a browser on v2). Capy uses `defaultTimeout` — it is one
|
|
89
|
+
HTTP fetch plus pixel math, held back to roughly two seconds because Capy
|
|
90
|
+
refuses answers that arrive faster than a human could have produced them.
|
|
91
|
+
|
|
8
92
|
## [1.2.0] - 2026-09-12
|
|
9
93
|
|
|
10
94
|
### Added
|
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
[](LICENSE)
|
|
6
6
|
[](https://github.com/capskip/capskip-node/actions/workflows/ci.yml)
|
|
7
7
|
|
|
8
|
-
**Solve reCAPTCHA v2, reCAPTCHA v3, Cloudflare Turnstile, GeeTest, ALTCHA and image captchas from Node.js.**
|
|
8
|
+
**Solve reCAPTCHA v2, reCAPTCHA v3, Cloudflare Turnstile, GeeTest, ALTCHA, Capy Puzzle, CaptchaFox, Friendly Captcha, AWS WAF and image captchas from Node.js.**
|
|
9
9
|
|
|
10
10
|
Official Node.js client for [CapSkip](https://capskip.com), a **local captcha solver** that runs on your own machine. Licensed once, not billed per solve. TypeScript definitions included.
|
|
11
11
|
|
|
@@ -19,7 +19,7 @@ npm install capskip
|
|
|
19
19
|
|
|
20
20
|
CapSkip is a desktop app. It does the solving on your machine and exposes the standard captcha-solver HTTP API — the same `in.php` / `res.php` endpoints every 2captcha-compatible client already speaks — on `127.0.0.1:8080`.
|
|
21
21
|
|
|
22
|
-
This SDK is a thin wrapper over that API, with the method names you would expect: `normal()`, `recaptcha()`, `turnstile()`, `geetest()`, `altcha()`. Nothing leaves your network, and there is no credit balance to keep an eye on.
|
|
22
|
+
This SDK is a thin wrapper over that API, with the method names you would expect: `normal()`, `recaptcha()`, `turnstile()`, `geetest()`, `altcha()`, `capy()`, `captchafox()`, `friendlyCaptcha()`, `amazonWaf()`. Nothing leaves your network, and there is no credit balance to keep an eye on.
|
|
23
23
|
|
|
24
24
|
## Supported captcha types
|
|
25
25
|
|
|
@@ -35,6 +35,11 @@ This SDK is a thin wrapper over that API, with the method names you would expect
|
|
|
35
35
|
| Cloudflare Turnstile (challenge page) | `solver.turnstile(sitekey, url, { data, pagedata })` |
|
|
36
36
|
| **GeeTest v3 solver** (slide puzzle) | `solver.geetest(gt, challenge, url)` |
|
|
37
37
|
| **ALTCHA solver** (proof-of-work) | `solver.altcha(url, { challengeUrl })` |
|
|
38
|
+
| **Capy Puzzle solver** (slide puzzle) | `solver.capy(sitekey, url)` |
|
|
39
|
+
| **CaptchaFox solver** (widget) | `solver.captchafox(sitekey, url)` |
|
|
40
|
+
| **Friendly Captcha solver** (proof-of-work) | `solver.friendlyCaptcha(sitekey, url, { version })` |
|
|
41
|
+
| **AWS WAF solver** (challenge page) | `solver.amazonWaf(sitekey, url, { iv, context })` |
|
|
42
|
+
| AWS WAF (widget) | `solver.amazonWaf(sitekey, url, { jsapiScript })` |
|
|
38
43
|
|
|
39
44
|
**hCaptcha and FunCaptcha/Arkose are not supported.** hCaptcha is the one people misidentify most often, since it also puts a `data-sitekey` on the widget — check for `class="h-captcha"` or a `js.hcaptcha.com` script before reaching for `recaptcha()`.
|
|
40
45
|
|
|
@@ -131,8 +136,9 @@ const solver = new CapSkip({
|
|
|
131
136
|
host: '127.0.0.1', // CapSkip host
|
|
132
137
|
port: 8080, // CapSkip port from app settings
|
|
133
138
|
defaultTimeout: 120, // seconds — image captcha polling timeout
|
|
134
|
-
recaptchaTimeout: 300, // seconds — reCAPTCHA / Turnstile / GeeTest
|
|
135
|
-
//
|
|
139
|
+
recaptchaTimeout: 300, // seconds — reCAPTCHA / Turnstile / GeeTest / CaptchaFox /
|
|
140
|
+
// Friendly Captcha / AWS WAF polling timeout
|
|
141
|
+
// (ALTCHA and Capy use defaultTimeout — neither is a browser solve)
|
|
136
142
|
pollingInterval: 5, // max seconds between res.php polls (starts at 0.25s, backs off to this)
|
|
137
143
|
});
|
|
138
144
|
```
|
|
@@ -230,7 +236,128 @@ result.token;
|
|
|
230
236
|
Challenges expire fast — some sites inside two minutes — so fetch one
|
|
231
237
|
immediately before solving and submit the token promptly.
|
|
232
238
|
|
|
233
|
-
###
|
|
239
|
+
### Capy Puzzle
|
|
240
|
+
|
|
241
|
+
A Capy solution is not a token. It is three values that together go into the
|
|
242
|
+
target form, so post all three back exactly as returned.
|
|
243
|
+
|
|
244
|
+
```js
|
|
245
|
+
const result = await solver.capy(
|
|
246
|
+
'PUZZLE_Abc1dEFghIJKLM2no34P56q7rStu8v',
|
|
247
|
+
'https://example.com/login',
|
|
248
|
+
);
|
|
249
|
+
|
|
250
|
+
// capy_captchakey, capy_challengekey and capy_answer respectively
|
|
251
|
+
result.captchakey, result.challengekey, result.answer;
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
`answer` is the drag path the widget would have recorded — submit it verbatim,
|
|
255
|
+
without trimming or re-encoding it. The challenge key is single-use and
|
|
256
|
+
short-lived, so submit promptly rather than caching the three values.
|
|
257
|
+
|
|
258
|
+
Pass `api_server` when the widget script points somewhere other than
|
|
259
|
+
`https://jp.api.capy.me`. Only the `puzzle` family is solved; `version: 'avatar'`
|
|
260
|
+
is refused rather than answered with a puzzle answer the site would reject.
|
|
261
|
+
|
|
262
|
+
### CaptchaFox
|
|
263
|
+
|
|
264
|
+
```js
|
|
265
|
+
const result = await solver.captchafox(
|
|
266
|
+
'sk_xtNxpk6fCdFbxh1_xJeGflSdCE9tn99G',
|
|
267
|
+
'https://example.com/signup',
|
|
268
|
+
);
|
|
269
|
+
|
|
270
|
+
// Post this back in the form field the widget uses, named `cf-captcha-response`
|
|
271
|
+
result.token;
|
|
272
|
+
|
|
273
|
+
// The UA the token was minted under — submit under this one, not your own
|
|
274
|
+
result.userAgent;
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
`url` has to be the page the widget actually runs on: CaptchaFox checks it
|
|
278
|
+
against the domains the key is registered for and refuses a mismatch
|
|
279
|
+
permanently, not intermittently.
|
|
280
|
+
|
|
281
|
+
Pass `api_server` only when the page does not load the default widget. A page
|
|
282
|
+
loading the MAM package expects a `MAM_` prefixed token, and sending the wrong
|
|
283
|
+
source still succeeds — it just returns a token the site will not accept, which
|
|
284
|
+
reads as a silent verification failure rather than an error.
|
|
285
|
+
|
|
286
|
+
### Friendly Captcha
|
|
287
|
+
|
|
288
|
+
Two different protocols ship under this name and a sitekey does not tell you
|
|
289
|
+
which one a site uses, so say which — or send the widget script and let CapSkip
|
|
290
|
+
read it off the build the site actually loads.
|
|
291
|
+
|
|
292
|
+
```js
|
|
293
|
+
const result = await solver.friendlyCaptcha(
|
|
294
|
+
'FCMGEMUD2M567T8G',
|
|
295
|
+
'https://example.com/signup',
|
|
296
|
+
{ version: 'v2' },
|
|
297
|
+
);
|
|
298
|
+
|
|
299
|
+
// v1 → frc-captcha-solution, v2 → frc-captcha-response
|
|
300
|
+
result.token;
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
```js
|
|
304
|
+
// Or let the script URL decide the version
|
|
305
|
+
const result = await solver.friendlyCaptcha(
|
|
306
|
+
'FCMGEMUD2M567T8G',
|
|
307
|
+
'https://example.com/signup',
|
|
308
|
+
{ moduleScript: 'https://cdn.example.com/@friendlycaptcha/sdk@0.1.6/site.min.js' },
|
|
309
|
+
);
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
Solving the wrong version returns a well-formed token the target site rejects,
|
|
313
|
+
with nothing to indicate the version was the problem. With neither `version` nor
|
|
314
|
+
a script URL, v1 is assumed. Pass `api_server: 'eu'` for a sitekey on the EU
|
|
315
|
+
data-residency tenant. A v2 token is roughly six kilobytes, so size whatever
|
|
316
|
+
carries it accordingly.
|
|
317
|
+
|
|
318
|
+
### AWS WAF
|
|
319
|
+
|
|
320
|
+
AWS WAF puts its CAPTCHA either on a **challenge page** — the HTTP 405
|
|
321
|
+
interstitial that sets `window.gokuProps` — or in a **widget** an ordinary page
|
|
322
|
+
renders with `AwsWafCaptcha.renderCaptcha`. Only `sitekey` and `url` are required.
|
|
323
|
+
|
|
324
|
+
```js
|
|
325
|
+
// Challenge page: sitekey, iv and context are gokuProps.key, .iv and .context
|
|
326
|
+
const result = await solver.amazonWaf(
|
|
327
|
+
'AQIDAHjcYuEXAMPLEghicBgQ/7bFaQZ+m5FKCMDnO+vTbNg96AHDh0IR5vgzHNceHYqZR+GOAAAAfjB8',
|
|
328
|
+
'https://example.com/protected',
|
|
329
|
+
{
|
|
330
|
+
iv: 'CgAFRDIjfgAAA5yY',
|
|
331
|
+
context: 'Rbp3r8fvbuhmrCqpUe8Mh1TLvs8OSKJZiSs2vCF4dt9rxVZI7xYJa2n5k/9r+XaXe7KUIu2I8nXTDHHkDvIOTDc2',
|
|
332
|
+
challenge_script: 'https://3f2a9c7d41b0.edge.sdk.awswaf.com/3f2a9c7d41b0/8e51d0c7a2f4/challenge.js',
|
|
333
|
+
},
|
|
334
|
+
);
|
|
335
|
+
|
|
336
|
+
// Widget page: sitekey is the widget's apiKey, plus the jsapi.js it loads
|
|
337
|
+
const result = await solver.amazonWaf(
|
|
338
|
+
'Xr9kEXAMPLE2bWQx1vTq8LmZ0aYc4dHs7nFp3gJt6uKw5eRi9AbCdEfGh=_0_1',
|
|
339
|
+
'https://example.com/protected',
|
|
340
|
+
{ jsapiScript: 'https://5b7e0a19c3d8.us-east-1.captcha-sdk.awswaf.com/5b7e0a19c3d8/jsapi.js' },
|
|
341
|
+
);
|
|
342
|
+
|
|
343
|
+
result.captcha_voucher, result.existing_token;
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
`iv` and `context` are optional and travel together: send both or neither. Left
|
|
347
|
+
out, CapSkip reads them from the page at solve time, which is the safer choice
|
|
348
|
+
when your copy of the page is more than a few minutes old.
|
|
349
|
+
|
|
350
|
+
The answer is not a token. POST `captcha_voucher` and `existing_token` as JSON
|
|
351
|
+
to the `voucher` endpoint beside the page's `challenge.js`; the response's
|
|
352
|
+
`token` is the `aws-waf-token` cookie. The pair is short-lived, so exchange it
|
|
353
|
+
immediately rather than storing it.
|
|
354
|
+
|
|
355
|
+
Every script URL (`challenge_script`, `captcha_script`, `jsapiScript`) must be an
|
|
356
|
+
https URL on an `awswaf.com` host. CapSkip posts the solution to the host the
|
|
357
|
+
script names, so anything else is refused before the request is made. See the
|
|
358
|
+
[AWS WAF API docs](https://capskip.com/api-docs/#aws-waf).
|
|
359
|
+
|
|
360
|
+
### With a proxy (every method except image captcha)
|
|
234
361
|
|
|
235
362
|
```js
|
|
236
363
|
// Proxy is not supported for image captcha
|
|
@@ -325,7 +452,11 @@ Every solve method resolves to:
|
|
|
325
452
|
```
|
|
326
453
|
|
|
327
454
|
GeeTest additionally expands its answer into `challenge`, `validate`, and
|
|
328
|
-
`seccode`, while `code` keeps the raw JSON string.
|
|
455
|
+
`seccode`, while `code` keeps the raw JSON string. CaptchaFox and Friendly
|
|
456
|
+
Captcha add `token`, the same string as `code`. Capy expands its answer into
|
|
457
|
+
`captchakey`, `challengekey` and `answer` — it returns an object rather than a
|
|
458
|
+
token, and `code` keeps the raw answer. AWS WAF likewise returns an object,
|
|
459
|
+
expanded into `captcha_voucher` and `existing_token`. ALTCHA adds `token` (the same
|
|
329
460
|
string as `code`) and `number`, the counter that solved it.
|
|
330
461
|
|
|
331
462
|
---
|
|
@@ -371,7 +502,7 @@ const result: SolveResult = await solver.recaptcha('...', 'https://example.com')
|
|
|
371
502
|
|
|
372
503
|
### How do I solve a captcha in Node.js?
|
|
373
504
|
|
|
374
|
-
Install the CapSkip desktop app, `npm install capskip`, then call the method that matches the widget — `recaptcha()`, `turnstile()`, `geetest()`, `altcha()` or `normal()`. Each returns a Promise that resolves once CapSkip has an answer, giving you a token, or the recognized text in the case of an image captcha.
|
|
505
|
+
Install the CapSkip desktop app, `npm install capskip`, then call the method that matches the widget — `recaptcha()`, `turnstile()`, `geetest()`, `altcha()`, `capy()`, `captchafox()`, `friendlyCaptcha()`, `amazonWaf()` or `normal()`. Each returns a Promise that resolves once CapSkip has an answer, giving you a token, or the recognized text in the case of an image captcha.
|
|
375
506
|
|
|
376
507
|
### Is this a free captcha solver?
|
|
377
508
|
|
|
@@ -379,7 +510,7 @@ The SDK itself is MIT-licensed and free. Solving needs the CapSkip app, which is
|
|
|
379
510
|
|
|
380
511
|
### Which captchas can it solve?
|
|
381
512
|
|
|
382
|
-
reCAPTCHA v2 (checkbox and invisible), reCAPTCHA v3, reCAPTCHA Enterprise, Cloudflare Turnstile, GeeTest v3, ALTCHA, and image/text captchas. Not hCaptcha, and not FunCaptcha/Arkose.
|
|
513
|
+
reCAPTCHA v2 (checkbox and invisible), reCAPTCHA v3, reCAPTCHA Enterprise, Cloudflare Turnstile, GeeTest v3, ALTCHA, Capy Puzzle, CaptchaFox, Friendly Captcha, AWS WAF, and image/text captchas. Not hCaptcha, and not FunCaptcha/Arkose.
|
|
383
514
|
|
|
384
515
|
### Does it work with Puppeteer and Playwright?
|
|
385
516
|
|