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/src/solver.js
CHANGED
|
@@ -217,6 +217,90 @@ function applyAltchaSolution(result) {
|
|
|
217
217
|
return result;
|
|
218
218
|
}
|
|
219
219
|
|
|
220
|
+
// A Capy solution is not a token. It is three values that together go into the
|
|
221
|
+
// target form, under the capy_ prefixed names the widget would have filled in.
|
|
222
|
+
const CAPY_FIELDS = ['captchakey', 'challengekey', 'answer', 'respKey'];
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Copy `fields` out of an answer that is an object rather than a token.
|
|
226
|
+
*
|
|
227
|
+
* `code` keeps the raw answer -- an object when polled with json=1, where the
|
|
228
|
+
* server puts it straight into `request`, or the JSON string it sends after
|
|
229
|
+
* `OK|` in plain-text mode -- so callers that forward it verbatim (or that were
|
|
230
|
+
* written against another solver's API) keep working.
|
|
231
|
+
*
|
|
232
|
+
* If the answer does not parse, the result is returned untouched rather than
|
|
233
|
+
* masking the server's reply.
|
|
234
|
+
*/
|
|
235
|
+
function expandObjectAnswer(result, fields) {
|
|
236
|
+
let payload = result.solution;
|
|
237
|
+
delete result.solution;
|
|
238
|
+
|
|
239
|
+
if (payload === null || typeof payload !== 'object') {
|
|
240
|
+
const { code } = result;
|
|
241
|
+
if (code !== null && typeof code === 'object') {
|
|
242
|
+
payload = code;
|
|
243
|
+
} else {
|
|
244
|
+
try {
|
|
245
|
+
payload = JSON.parse(code || '');
|
|
246
|
+
} catch (error) {
|
|
247
|
+
return result;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
if (payload === null || typeof payload !== 'object' || Array.isArray(payload)) {
|
|
253
|
+
return result;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
for (const field of fields) {
|
|
257
|
+
if (Object.prototype.hasOwnProperty.call(payload, field)) {
|
|
258
|
+
result[field] = payload[field];
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
return result;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/** Expand the Capy answer into `captchakey` / `challengekey` / `answer`. */
|
|
266
|
+
function applyCapySolution(result) {
|
|
267
|
+
return expandObjectAnswer(result, CAPY_FIELDS);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// An AWS WAF solution is two values that only work as a pair: the voucher AWS
|
|
271
|
+
// issued for the answered puzzle, and the token it was issued for. The site's
|
|
272
|
+
// own /voucher endpoint trades them for the aws-waf-token cookie.
|
|
273
|
+
const AMAZON_WAF_FIELDS = ['captcha_voucher', 'existing_token'];
|
|
274
|
+
|
|
275
|
+
/** Expand the AWS WAF answer into `captcha_voucher` / `existing_token`. */
|
|
276
|
+
function applyAmazonWafSolution(result) {
|
|
277
|
+
return expandObjectAnswer(result, AMAZON_WAF_FIELDS);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Expose a single-token answer as `token`, named for the form field it fills.
|
|
282
|
+
*
|
|
283
|
+
* `code` keeps the raw answer so callers that forward it verbatim keep working;
|
|
284
|
+
* `token` is the same string. The server's createTask-shaped `solution` object
|
|
285
|
+
* carries that same string, so it is consumed here rather than handed back as a
|
|
286
|
+
* second copy -- but it is read first when `request` came through empty, so a
|
|
287
|
+
* client is never left without the token the poll actually carried.
|
|
288
|
+
*/
|
|
289
|
+
function applyTokenSolution(result) {
|
|
290
|
+
const { solution } = result;
|
|
291
|
+
delete result.solution;
|
|
292
|
+
|
|
293
|
+
let code = result.code;
|
|
294
|
+
|
|
295
|
+
if (!code && solution !== null && typeof solution === 'object') {
|
|
296
|
+
code = solution.token || '';
|
|
297
|
+
result.code = code;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
result.token = code || '';
|
|
301
|
+
return result;
|
|
302
|
+
}
|
|
303
|
+
|
|
220
304
|
// CapSkip's in.php returns OK|<id> by default, or {"status":1,"request":"<id>"}
|
|
221
305
|
// when the submit carried json=1. Accept both so submitting with json=1 works.
|
|
222
306
|
function parseSubmitResponse(response) {
|
|
@@ -240,7 +324,10 @@ function parseSubmitResponse(response) {
|
|
|
240
324
|
throw new ApiException(`cannot recognize response ${response}`);
|
|
241
325
|
}
|
|
242
326
|
|
|
243
|
-
/**
|
|
327
|
+
/**
|
|
328
|
+
* Client for the CapSkip local captcha solver (image, reCAPTCHA, Turnstile,
|
|
329
|
+
* GeeTest v3, ALTCHA, Capy Puzzle, CaptchaFox, Friendly Captcha, AWS WAF).
|
|
330
|
+
*/
|
|
244
331
|
class CapSkip {
|
|
245
332
|
constructor({
|
|
246
333
|
apiKey = 'capskip',
|
|
@@ -359,6 +446,180 @@ class CapSkip {
|
|
|
359
446
|
return applyAltchaSolution(result);
|
|
360
447
|
}
|
|
361
448
|
|
|
449
|
+
/**
|
|
450
|
+
* Solve a Capy Puzzle captcha.
|
|
451
|
+
*
|
|
452
|
+
* `sitekey` is the site's public Capy key, conventionally prefixed `PUZZLE_`;
|
|
453
|
+
* it is sent as the `captchakey` the API documents. Pass `api_server` when the
|
|
454
|
+
* widget script points somewhere other than `https://jp.api.capy.me`.
|
|
455
|
+
*
|
|
456
|
+
* The result is not a token. It carries `captchakey`, `challengekey` and
|
|
457
|
+
* `answer`, which go into the target form's `capy_captchakey`,
|
|
458
|
+
* `capy_challengekey` and `capy_answer` fields, plus the raw answer as `code`.
|
|
459
|
+
* Submit `answer` verbatim -- it is the drag path the widget would have
|
|
460
|
+
* recorded, so trimming or re-encoding it invalidates the solve.
|
|
461
|
+
*
|
|
462
|
+
* The challenge key is single-use and short-lived, so submit promptly rather
|
|
463
|
+
* than caching the three values for a later request.
|
|
464
|
+
*/
|
|
465
|
+
async capy(sitekey, url, options = {}) {
|
|
466
|
+
// An unset optional is dropped rather than sent as undefined, so
|
|
467
|
+
// `capy(key, url, { apiServer: undefined })` behaves as if it were omitted.
|
|
468
|
+
const given = {};
|
|
469
|
+
for (const [key, value] of Object.entries(options)) {
|
|
470
|
+
if (value !== undefined && value !== null) {
|
|
471
|
+
given[key] = value;
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
// A Capy solve is one HTTP fetch plus pixel math, not a browser session, so
|
|
476
|
+
// it keeps the default timeout. It is held back to roughly two seconds
|
|
477
|
+
// before the answer is released -- Capy refuses answers that arrive faster
|
|
478
|
+
// than a human could have produced them -- which the default absorbs.
|
|
479
|
+
const result = await this.solve({
|
|
480
|
+
captchakey: sitekey,
|
|
481
|
+
url,
|
|
482
|
+
...given,
|
|
483
|
+
method: 'capy',
|
|
484
|
+
poll_json: 1,
|
|
485
|
+
});
|
|
486
|
+
return applyCapySolution(result);
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
/**
|
|
490
|
+
* Solve a CaptchaFox challenge.
|
|
491
|
+
*
|
|
492
|
+
* `sitekey` is the public key the widget renders with, conventionally prefixed
|
|
493
|
+
* `sk_`, and `url` has to be the page the widget actually runs on: CaptchaFox
|
|
494
|
+
* checks it against the domains the key is registered for and refuses a
|
|
495
|
+
* mismatch permanently rather than intermittently.
|
|
496
|
+
*
|
|
497
|
+
* Pass `api_server` only when the target page does not load the default
|
|
498
|
+
* widget. A page loading the MAM package expects a `MAM_` prefixed token, and
|
|
499
|
+
* sending the wrong source still succeeds -- it just returns a token in a
|
|
500
|
+
* format the site will not accept, which reads as a silent verification
|
|
501
|
+
* failure rather than an error.
|
|
502
|
+
*
|
|
503
|
+
* The result carries the token as both `code` and `token`, for the form's
|
|
504
|
+
* `cf-captcha-response` field, and `userAgent` when the solve reported one.
|
|
505
|
+
* That User-Agent is the browser's own, not any you sent, so submit the token
|
|
506
|
+
* under it.
|
|
507
|
+
*/
|
|
508
|
+
async captchafox(sitekey, url, options = {}) {
|
|
509
|
+
const given = {};
|
|
510
|
+
for (const [key, value] of Object.entries(options)) {
|
|
511
|
+
if (value !== undefined && value !== null) {
|
|
512
|
+
given[key] = value;
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
// A real browser session, like reCAPTCHA and GeeTest, and longer again when
|
|
517
|
+
// an interactive challenge is drawn -- so it gets the longer of the two
|
|
518
|
+
// timeouts unless the caller asked for a specific one.
|
|
519
|
+
const result = await this.solve({
|
|
520
|
+
timeout: this.recaptchaTimeout,
|
|
521
|
+
sitekey,
|
|
522
|
+
url,
|
|
523
|
+
...given,
|
|
524
|
+
method: 'captchafox',
|
|
525
|
+
poll_json: 1,
|
|
526
|
+
});
|
|
527
|
+
return applyTokenSolution(result);
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
/**
|
|
531
|
+
* Solve a Friendly Captcha proof-of-work challenge.
|
|
532
|
+
*
|
|
533
|
+
* Two different protocols ship under this name and a sitekey does not tell you
|
|
534
|
+
* which one a site uses, so say which: pass `version: 'v1'` or `version: 'v2'`,
|
|
535
|
+
* or pass `moduleScript` with the src of the widget's `type="module"` script
|
|
536
|
+
* tag and let CapSkip read the version off the build the site actually loads.
|
|
537
|
+
* With neither, v1 is assumed. Solving the wrong version returns a well-formed
|
|
538
|
+
* token the target site rejects, with nothing to indicate the version was the
|
|
539
|
+
* problem.
|
|
540
|
+
*
|
|
541
|
+
* Pass `api_server: 'eu'` for a sitekey on the EU data-residency tenant; both
|
|
542
|
+
* tenants mint a token for the same sitekey, so the wrong one is only caught
|
|
543
|
+
* by the site's own verification.
|
|
544
|
+
*
|
|
545
|
+
* The result carries the token as both `code` and `token`. It goes into
|
|
546
|
+
* `frc-captcha-solution` on v1 and `frc-captcha-response` on v2 -- the field
|
|
547
|
+
* names differ, which is what catches an integration moved from one to the
|
|
548
|
+
* other. A v2 token is roughly six kilobytes, so size whatever carries it
|
|
549
|
+
* accordingly.
|
|
550
|
+
*/
|
|
551
|
+
async friendlyCaptcha(sitekey, url, options = {}) {
|
|
552
|
+
const given = {};
|
|
553
|
+
for (const [key, value] of Object.entries(options)) {
|
|
554
|
+
if (value !== undefined && value !== null) {
|
|
555
|
+
given[key] = value;
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
// Proof-of-work, but not the millisecond kind ALTCHA does: the service sets
|
|
560
|
+
// the difficulty per request and raises it for addresses it has seen a lot
|
|
561
|
+
// of, and v2 always solves in a browser. Both make solve time variable
|
|
562
|
+
// enough to want the longer timeout.
|
|
563
|
+
const result = await this.solve({
|
|
564
|
+
timeout: this.recaptchaTimeout,
|
|
565
|
+
sitekey,
|
|
566
|
+
url,
|
|
567
|
+
...given,
|
|
568
|
+
method: 'friendly_captcha',
|
|
569
|
+
poll_json: 1,
|
|
570
|
+
});
|
|
571
|
+
return applyTokenSolution(result);
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
/**
|
|
575
|
+
* Solve an AWS WAF (Amazon WAF) CAPTCHA.
|
|
576
|
+
*
|
|
577
|
+
* Only `sitekey` and `url` are required:
|
|
578
|
+
*
|
|
579
|
+
* - On a challenge page (the HTTP 405 page with `window.gokuProps`), `sitekey`
|
|
580
|
+
* is `gokuProps.key`, and `iv` and `context` are `gokuProps.iv` and
|
|
581
|
+
* `gokuProps.context`. Send both or neither -- left out, CapSkip reads them
|
|
582
|
+
* from `url` at solve time, which is the safer choice when your copy of the
|
|
583
|
+
* page is more than a few minutes old. `challenge_script` and
|
|
584
|
+
* `captcha_script` are the full URLs of the page's challenge.js and
|
|
585
|
+
* captcha.js.
|
|
586
|
+
* - On a widget page (`AwsWafCaptcha.renderCaptcha`), `sitekey` is the
|
|
587
|
+
* widget's `apiKey`; pass `jsapiScript` with the full URL of jsapi.js and no
|
|
588
|
+
* `iv` / `context`.
|
|
589
|
+
*
|
|
590
|
+
* Every script URL must be an https URL on an awswaf.com host; anything else
|
|
591
|
+
* is refused before the request is sent.
|
|
592
|
+
*
|
|
593
|
+
* The result carries `captcha_voucher` and `existing_token`, plus the raw
|
|
594
|
+
* answer as `code`. The two only work as a pair: POST them as JSON to the
|
|
595
|
+
* `voucher` endpoint next to the page's challenge.js and the response's
|
|
596
|
+
* `token` is the aws-waf-token cookie. Exchange them as soon as they arrive
|
|
597
|
+
* rather than storing them for later.
|
|
598
|
+
*/
|
|
599
|
+
async amazonWaf(sitekey, url, options = {}) {
|
|
600
|
+
// An unset optional is dropped rather than sent as undefined; an empty one
|
|
601
|
+
// is dropped during validation, since the server reads '' as "not sent".
|
|
602
|
+
const given = {};
|
|
603
|
+
for (const [key, value] of Object.entries(options)) {
|
|
604
|
+
if (value !== undefined && value !== null) {
|
|
605
|
+
given[key] = value;
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
// A real browser mints the token the voucher is issued for, and the puzzle
|
|
610
|
+
// rounds go through AWS on top of that, so it gets the longer of the two
|
|
611
|
+
// timeouts unless the caller asked for a specific one.
|
|
612
|
+
const result = await this.solve({
|
|
613
|
+
timeout: this.recaptchaTimeout,
|
|
614
|
+
sitekey,
|
|
615
|
+
url,
|
|
616
|
+
...given,
|
|
617
|
+
method: 'amazon_waf',
|
|
618
|
+
poll_json: 1,
|
|
619
|
+
});
|
|
620
|
+
return applyAmazonWafSolution(result);
|
|
621
|
+
}
|
|
622
|
+
|
|
362
623
|
async solve(options = {}) {
|
|
363
624
|
const {
|
|
364
625
|
timeout = 0,
|
|
@@ -450,6 +711,18 @@ class CapSkip {
|
|
|
450
711
|
if (method === 'altcha') {
|
|
451
712
|
return prepareSubmitParams(params, 'altcha');
|
|
452
713
|
}
|
|
714
|
+
if (method === 'capy') {
|
|
715
|
+
return prepareSubmitParams(params, 'capy');
|
|
716
|
+
}
|
|
717
|
+
if (method === 'captchafox') {
|
|
718
|
+
return prepareSubmitParams(params, 'captchafox');
|
|
719
|
+
}
|
|
720
|
+
if (method === 'friendly_captcha') {
|
|
721
|
+
return prepareSubmitParams(params, 'friendly_captcha');
|
|
722
|
+
}
|
|
723
|
+
if (method === 'amazon_waf') {
|
|
724
|
+
return prepareSubmitParams(params, 'amazon_waf');
|
|
725
|
+
}
|
|
453
726
|
return applyProxy(applyParamAliases(params));
|
|
454
727
|
}
|
|
455
728
|
}
|
|
@@ -463,4 +736,8 @@ module.exports = {
|
|
|
463
736
|
applyPollResult,
|
|
464
737
|
applyGeetestSolution,
|
|
465
738
|
applyAltchaSolution,
|
|
739
|
+
applyCapySolution,
|
|
740
|
+
applyAmazonWafSolution,
|
|
741
|
+
expandObjectAnswer,
|
|
742
|
+
applyTokenSolution,
|
|
466
743
|
};
|
package/types/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Type definitions for the CapSkip Node.js SDK.
|
|
2
2
|
|
|
3
|
-
/** Proxy passed to
|
|
3
|
+
/** Proxy passed to any solve except image captcha. */
|
|
4
4
|
export interface Proxy {
|
|
5
5
|
/** Proxy type: `HTTP`, `HTTPS`, `SOCKS5`, or `SOCKS5H`. */
|
|
6
6
|
type: string;
|
|
@@ -18,7 +18,11 @@ export interface CapSkipOptions {
|
|
|
18
18
|
port?: number;
|
|
19
19
|
/** Seconds to poll an image captcha before timing out. Default `120`. */
|
|
20
20
|
defaultTimeout?: number;
|
|
21
|
-
/**
|
|
21
|
+
/**
|
|
22
|
+
* Seconds to poll reCAPTCHA / Turnstile / GeeTest / CaptchaFox / Friendly
|
|
23
|
+
* Captcha / AWS WAF before timing out. Default `300`. ALTCHA and Capy use
|
|
24
|
+
* `defaultTimeout` instead — neither is a browser solve.
|
|
25
|
+
*/
|
|
22
26
|
recaptchaTimeout?: number;
|
|
23
27
|
/** Max seconds between polls; starts at `0.25` and backs off to this. Default `5`. */
|
|
24
28
|
pollingInterval?: number;
|
|
@@ -32,10 +36,15 @@ export interface SolveResult {
|
|
|
32
36
|
* The solution: recognized text for images, a token otherwise. For GeeTest
|
|
33
37
|
* this is the raw JSON string CapSkip returns — prefer the parsed
|
|
34
38
|
* `challenge` / `validate` / `seccode` fields below. For ALTCHA it is the
|
|
35
|
-
* base64 token, also exposed as `token`.
|
|
39
|
+
* base64 token, also exposed as `token`. For Capy and AWS WAF it is the raw
|
|
40
|
+
* answer object, expanded into the fields below.
|
|
41
|
+
*/
|
|
42
|
+
code: string | Record<string, unknown>;
|
|
43
|
+
/**
|
|
44
|
+
* Turnstile and CaptchaFox — the User-Agent to use when submitting the token.
|
|
45
|
+
* For CaptchaFox this is the browser's own, not one you sent, and it is absent
|
|
46
|
+
* when the solve captured none rather than guessed.
|
|
36
47
|
*/
|
|
37
|
-
code: string;
|
|
38
|
-
/** Turnstile only — the User-Agent to use when submitting the token. */
|
|
39
48
|
userAgent?: string;
|
|
40
49
|
/** GeeTest only — the `geetest_challenge` value to post back. */
|
|
41
50
|
challenge?: string;
|
|
@@ -50,6 +59,29 @@ export interface SolveResult {
|
|
|
50
59
|
token?: string;
|
|
51
60
|
/** ALTCHA only — the counter that solved the challenge. */
|
|
52
61
|
number?: number;
|
|
62
|
+
/** Capy only — the value for the target form's `capy_captchakey` field. */
|
|
63
|
+
captchakey?: string;
|
|
64
|
+
/** Capy only — the value for the target form's `capy_challengekey` field. */
|
|
65
|
+
challengekey?: string;
|
|
66
|
+
/**
|
|
67
|
+
* Capy only — the value for the target form's `capy_answer` field. The drag
|
|
68
|
+
* path the widget would have recorded; submit it verbatim.
|
|
69
|
+
*/
|
|
70
|
+
answer?: string;
|
|
71
|
+
/**
|
|
72
|
+
* Capy only — empty for a puzzle solve. Present for shape compatibility with
|
|
73
|
+
* 2Captcha's documented response; it carries nothing.
|
|
74
|
+
*/
|
|
75
|
+
respKey?: string;
|
|
76
|
+
/**
|
|
77
|
+
* AWS WAF only — the voucher AWS issued for the answered puzzle. Only valid
|
|
78
|
+
* together with `existing_token`: POST both as JSON to the `voucher` endpoint
|
|
79
|
+
* beside the page's challenge.js, whose response `token` is the
|
|
80
|
+
* `aws-waf-token` cookie. Exchange immediately.
|
|
81
|
+
*/
|
|
82
|
+
captcha_voucher?: string;
|
|
83
|
+
/** AWS WAF only — the token the voucher was issued for. Pair with `captcha_voucher`. */
|
|
84
|
+
existing_token?: string;
|
|
53
85
|
}
|
|
54
86
|
|
|
55
87
|
/** Extra options for {@link CapSkip.normal}. */
|
|
@@ -141,6 +173,113 @@ export interface AltchaOptions {
|
|
|
141
173
|
[key: string]: unknown;
|
|
142
174
|
}
|
|
143
175
|
|
|
176
|
+
/** Extra options for {@link CapSkip.capy}. */
|
|
177
|
+
export interface CapyOptions {
|
|
178
|
+
/** Root of the Capy API the key lives behind (alias for `api_server`). */
|
|
179
|
+
apiServer?: string;
|
|
180
|
+
/** Root of the Capy API the key lives behind. Default `https://jp.api.capy.me`. */
|
|
181
|
+
api_server?: string;
|
|
182
|
+
/**
|
|
183
|
+
* The challenge family. Only `"puzzle"` (the default) is solved — `"avatar"`
|
|
184
|
+
* is refused before the request is made.
|
|
185
|
+
*/
|
|
186
|
+
version?: string;
|
|
187
|
+
/** User-Agent to send with the puzzle request (alias for `useragent`). */
|
|
188
|
+
userAgent?: string;
|
|
189
|
+
/** User-Agent to send with the puzzle request. */
|
|
190
|
+
useragent?: string;
|
|
191
|
+
/** `1` to request the raw JSON response from CapSkip. */
|
|
192
|
+
json?: number;
|
|
193
|
+
/** Proxy — used for the puzzle-image fetch, the only request a Capy solve makes. */
|
|
194
|
+
proxy?: Proxy | string;
|
|
195
|
+
/** Proxy type when `proxy` is a bare string. */
|
|
196
|
+
proxytype?: string;
|
|
197
|
+
[key: string]: unknown;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/** Extra options for {@link CapSkip.captchafox}. */
|
|
201
|
+
export interface CaptchaFoxOptions {
|
|
202
|
+
/** Widget entry point (alias for `api_server`). */
|
|
203
|
+
apiServer?: string;
|
|
204
|
+
/**
|
|
205
|
+
* Widget entry point. Default `https://cdn.captchafox.com/`. The MAM package
|
|
206
|
+
* path returns a `MAM_` prefixed token instead.
|
|
207
|
+
*/
|
|
208
|
+
api_server?: string;
|
|
209
|
+
/** Accepted for compatibility and not applied (alias for `useragent`). */
|
|
210
|
+
userAgent?: string;
|
|
211
|
+
/** Accepted for compatibility and not applied — CapSkip uses its own browser. */
|
|
212
|
+
useragent?: string;
|
|
213
|
+
/** `1` to request the raw JSON response from CapSkip. */
|
|
214
|
+
json?: number;
|
|
215
|
+
/** Proxy used for solving. */
|
|
216
|
+
proxy?: Proxy | string;
|
|
217
|
+
/** Proxy type when `proxy` is a bare string. */
|
|
218
|
+
proxytype?: string;
|
|
219
|
+
[key: string]: unknown;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/** Extra options for {@link CapSkip.friendlyCaptcha}. */
|
|
223
|
+
export interface FriendlyCaptchaOptions {
|
|
224
|
+
/** Protocol version: `"v1"` (default) or `"v2"`; a bare `1` or `2` works too. */
|
|
225
|
+
version?: string | number;
|
|
226
|
+
/** `src` of the widget script tag carrying `type="module"` (alias). */
|
|
227
|
+
moduleScript?: string;
|
|
228
|
+
/** `src` of the widget script tag carrying `type="module"`. */
|
|
229
|
+
module_script?: string;
|
|
230
|
+
/** `src` of the widget script tag carrying `nomodule` (alias). */
|
|
231
|
+
nomoduleScript?: string;
|
|
232
|
+
/** `src` of the widget script tag carrying `nomodule`. */
|
|
233
|
+
nomodule_script?: string;
|
|
234
|
+
/** Data residency tenant (alias for `api_server`). */
|
|
235
|
+
apiServer?: string;
|
|
236
|
+
/** Data residency tenant: `"global"` (default), `"eu"`, or a full URL. */
|
|
237
|
+
api_server?: string;
|
|
238
|
+
/** User-Agent to send with the request (alias for `useragent`). */
|
|
239
|
+
userAgent?: string;
|
|
240
|
+
/** User-Agent to send with the request. */
|
|
241
|
+
useragent?: string;
|
|
242
|
+
/** `1` to request the raw JSON response from CapSkip. */
|
|
243
|
+
json?: number;
|
|
244
|
+
/** Proxy used for solving. */
|
|
245
|
+
proxy?: Proxy | string;
|
|
246
|
+
/** Proxy type when `proxy` is a bare string. */
|
|
247
|
+
proxytype?: string;
|
|
248
|
+
[key: string]: unknown;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/** Extra options for {@link CapSkip.amazonWaf}. */
|
|
252
|
+
export interface AmazonWafOptions {
|
|
253
|
+
/**
|
|
254
|
+
* Challenge page: `gokuProps.iv`. Send together with `context`, or leave both
|
|
255
|
+
* out and CapSkip reads them from the page at solve time.
|
|
256
|
+
*/
|
|
257
|
+
iv?: string;
|
|
258
|
+
/** Challenge page: `gokuProps.context`. Send together with `iv`. */
|
|
259
|
+
context?: string;
|
|
260
|
+
/** Full https URL of the page's `challenge.js` on an `awswaf.com` host. */
|
|
261
|
+
challenge_script?: string;
|
|
262
|
+
/** Full https URL of the page's `challenge.js` (alias for `challenge_script`). */
|
|
263
|
+
challengeScript?: string;
|
|
264
|
+
/** Full https URL of the page's `captcha.js` on an `awswaf.com` host. */
|
|
265
|
+
captcha_script?: string;
|
|
266
|
+
/** Full https URL of the page's `captcha.js` (alias for `captcha_script`). */
|
|
267
|
+
captchaScript?: string;
|
|
268
|
+
/** Widget page: full https URL of `jsapi.js` on an `awswaf.com` host. */
|
|
269
|
+
jsapiScript?: string;
|
|
270
|
+
/** Widget page: full https URL of `jsapi.js` (alias for `jsapiScript`). */
|
|
271
|
+
jsapi_script?: string;
|
|
272
|
+
/** Poll timeout in seconds. Default: the client's `recaptchaTimeout`. */
|
|
273
|
+
timeout?: number;
|
|
274
|
+
/** `1` to request the raw JSON response from CapSkip. */
|
|
275
|
+
json?: number;
|
|
276
|
+
/** Proxy used for solving. */
|
|
277
|
+
proxy?: Proxy | string;
|
|
278
|
+
/** Proxy type when `proxy` is a bare string. */
|
|
279
|
+
proxytype?: string;
|
|
280
|
+
[key: string]: unknown;
|
|
281
|
+
}
|
|
282
|
+
|
|
144
283
|
/** Options for the {@link CapSkip.solve} manual workflow. */
|
|
145
284
|
export interface SolveOptions {
|
|
146
285
|
/** Poll timeout in seconds (falls back to the configured default). */
|
|
@@ -188,6 +327,55 @@ export class CapSkip {
|
|
|
188
327
|
* wins. Challenges expire fast, so fetch one immediately before calling.
|
|
189
328
|
*/
|
|
190
329
|
altcha(url: string, options?: AltchaOptions): Promise<SolveResult>;
|
|
330
|
+
/**
|
|
331
|
+
* Solve a Capy Puzzle captcha.
|
|
332
|
+
*
|
|
333
|
+
* `sitekey` is the site's public Capy key, conventionally prefixed `PUZZLE_`,
|
|
334
|
+
* and is sent as the `captchakey` the API documents. The result is not a
|
|
335
|
+
* token: it carries `captchakey`, `challengekey` and `answer`, all three of
|
|
336
|
+
* which go into the target form.
|
|
337
|
+
*/
|
|
338
|
+
capy(sitekey: string, url: string, options?: CapyOptions): Promise<SolveResult>;
|
|
339
|
+
/**
|
|
340
|
+
* Solve a CaptchaFox challenge.
|
|
341
|
+
*
|
|
342
|
+
* `url` has to be the page the widget actually runs on — CaptchaFox checks it
|
|
343
|
+
* against the domains the key is registered for. The result carries `token`
|
|
344
|
+
* for the form's `cf-captcha-response` field.
|
|
345
|
+
*/
|
|
346
|
+
captchafox(
|
|
347
|
+
sitekey: string,
|
|
348
|
+
url: string,
|
|
349
|
+
options?: CaptchaFoxOptions,
|
|
350
|
+
): Promise<SolveResult>;
|
|
351
|
+
/**
|
|
352
|
+
* Solve a Friendly Captcha proof-of-work challenge.
|
|
353
|
+
*
|
|
354
|
+
* Two different protocols ship under this name and a sitekey does not say
|
|
355
|
+
* which, so pass `version`, or pass `moduleScript` and let CapSkip read it off
|
|
356
|
+
* the build the site loads. The token goes into `frc-captcha-solution` on v1
|
|
357
|
+
* or `frc-captcha-response` on v2.
|
|
358
|
+
*/
|
|
359
|
+
friendlyCaptcha(
|
|
360
|
+
sitekey: string,
|
|
361
|
+
url: string,
|
|
362
|
+
options?: FriendlyCaptchaOptions,
|
|
363
|
+
): Promise<SolveResult>;
|
|
364
|
+
/**
|
|
365
|
+
* Solve an AWS WAF CAPTCHA.
|
|
366
|
+
*
|
|
367
|
+
* On a challenge page, `sitekey` is `gokuProps.key` and `iv` / `context` are
|
|
368
|
+
* `gokuProps.iv` / `gokuProps.context` (both or neither). On a widget page,
|
|
369
|
+
* `sitekey` is the widget's `apiKey`; pass `jsapiScript`. Script URLs must be
|
|
370
|
+
* https on an `awswaf.com` host. The result carries `captcha_voucher` and
|
|
371
|
+
* `existing_token`, which the site's `voucher` endpoint trades for the
|
|
372
|
+
* `aws-waf-token` cookie.
|
|
373
|
+
*/
|
|
374
|
+
amazonWaf(
|
|
375
|
+
sitekey: string,
|
|
376
|
+
url: string,
|
|
377
|
+
options?: AmazonWafOptions,
|
|
378
|
+
): Promise<SolveResult>;
|
|
191
379
|
/** Submit then poll to completion. Used by the higher-level solve methods. */
|
|
192
380
|
solve(options?: SolveOptions): Promise<SolveResult>;
|
|
193
381
|
/** Submit a captcha without polling; resolves to the captcha id. */
|