From c8d5799bd3aefd22aec0522a0c687a04a1e1e65b Mon Sep 17 00:00:00 2001 From: Kirill Bushmin Date: Wed, 25 Mar 2026 16:05:44 +0300 Subject: [PATCH 1/3] CCL-7545 added new captcha types --- README.md | 3 + package.json | 2 +- src/CapMonsterCloudClient.ts | 69 +++++-- src/CapMonsterCloudClientFactory.i.spec.ts | 170 ++++++++++++++++++ src/GetTaskResult.ts | 8 +- .../BasiliskRequest/BasiliskRequest.ts | 2 + src/Requests/CastleRequest/CastleRequest.ts | 20 +++ .../CastleRequest/CastleRequestBase.ts | 78 ++++++++ src/Requests/CastleRequest/index.ts | 1 + .../DataDomeRequest/DataDomeRequest.ts | 2 + src/Requests/HuntRequest/HuntRequest.ts | 16 ++ src/Requests/HuntRequest/HuntRequestBase.ts | 63 +++++++ src/Requests/HuntRequest/index.ts | 1 + src/Requests/ImpervaRequest/ImpervaRequest.ts | 2 + src/Requests/TSPDRequest/TSPDRequest.ts | 17 ++ src/Requests/TSPDRequest/TSPDRequestBase.ts | 62 +++++++ src/Requests/TSPDRequest/index.ts | 1 + src/Requests/Task.ts | 24 ++- src/Requests/TemuRequest/TemuRequest.ts | 2 + src/Requests/TenDIRequest/TenDIRequest.ts | 2 + src/Responses/CastleResponse.ts | 5 + src/Responses/HuntResponse.ts | 3 + src/Responses/TSPDResponse.ts | 8 + src/index.ts | 12 ++ 24 files changed, 556 insertions(+), 17 deletions(-) create mode 100644 src/Requests/CastleRequest/CastleRequest.ts create mode 100644 src/Requests/CastleRequest/CastleRequestBase.ts create mode 100644 src/Requests/CastleRequest/index.ts create mode 100644 src/Requests/HuntRequest/HuntRequest.ts create mode 100644 src/Requests/HuntRequest/HuntRequestBase.ts create mode 100644 src/Requests/HuntRequest/index.ts create mode 100644 src/Requests/TSPDRequest/TSPDRequest.ts create mode 100644 src/Requests/TSPDRequest/TSPDRequestBase.ts create mode 100644 src/Requests/TSPDRequest/index.ts create mode 100644 src/Responses/CastleResponse.ts create mode 100644 src/Responses/HuntResponse.ts create mode 100644 src/Responses/TSPDResponse.ts diff --git a/README.md b/README.md index 8c0155e..3070f54 100644 --- a/README.md +++ b/README.md @@ -93,3 +93,6 @@ DEBUG=cmc-* node app.js - [TenDIRequest](https://zenno.link/doc-tendi-en) - [TurnstileRequest](https://zenno.link/doc-turnstile-proxy-en) - [Yidun](https://zenno.link/doc-yidun-en) +- [Castle](https://zenno.link/castle-en) +- [TSPD](https://zenno.link/tspd-en) +- [Hunt](https://zenno.link/hunt-en) diff --git a/package.json b/package.json index af8666e..1625b2d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@zennolab_com/capmonstercloud-client", - "version": "2.4.0", + "version": "2.4.1", "description": "Official JS client library for https://capmonster.cloud/ captcha recognition service", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/src/CapMonsterCloudClient.ts b/src/CapMonsterCloudClient.ts index 83ca14e..733311d 100644 --- a/src/CapMonsterCloudClient.ts +++ b/src/CapMonsterCloudClient.ts @@ -53,16 +53,12 @@ import { YidunRequest } from './Requests/YidunRequest'; import { YidunResponse } from './Responses/YidunResponse'; import { MTCaptchaRequest } from './Requests/MTCaptchaRequest'; import { MTCaptchaResponse } from './Responses/MTCaptchaResponse'; - -type CustomTaskUnion = TemuRequest | BasiliskRequest | ImpervaRequest; - -type ResponseForCustomTask = T extends TemuRequest - ? TemuResponse - : T extends BasiliskRequest - ? BasiliskResponse - : T extends ImpervaRequest - ? ImpervaResponse - : never; +import { CastleRequest } from './Requests/CastleRequest'; +import { CastleResponse } from './Responses/CastleResponse'; +import { TSPDRequest } from './Requests/TSPDRequest'; +import { TSPDResponse } from './Responses/TSPDResponse'; +import { HuntRequest } from './Requests/HuntRequest'; +import { HuntResponse } from './Responses/HuntResponse'; /** * Base type for capmonster.cloud Client exceptions @@ -241,6 +237,42 @@ export class CapMonsterCloudClient { resultTimeouts?: GetResultTimeouts, cancellationController?: AbortController, ): Promise>; + /** + * Solve Basilisk task + * You will get response within 10 - 180 secs period depending on service workload. + */ + public async Solve( + task: BasiliskRequest, + resultTimeouts?: GetResultTimeouts, + cancellationController?: AbortController, + ): Promise>; + /** + * Solve Imperva task + * You will get response within 10 - 180 secs period depending on service workload. + */ + public async Solve( + task: ImpervaRequest, + resultTimeouts?: GetResultTimeouts, + cancellationController?: AbortController, + ): Promise>; + /** + * Solve Temu task + * You will get response within 10 - 180 secs period depending on service workload. + */ + public async Solve( + task: TemuRequest, + resultTimeouts?: GetResultTimeouts, + cancellationController?: AbortController, + ): Promise>; + /** + * Solve Castle task + * You will get response within 10 - 180 secs period depending on service workload. + */ + public async Solve( + task: CastleRequest, + resultTimeouts?: GetResultTimeouts, + cancellationController?: AbortController, + ): Promise>; /** * Solve TenDI task * You will get response within 10 - 180 secs period depending on service workload. @@ -251,14 +283,23 @@ export class CapMonsterCloudClient { cancellationController?: AbortController, ): Promise>; /** - * Solve CustomTask task + * Solve Hunt task + * You will get response within 10 - 180 secs period depending on service workload. + */ + public async Solve( + task: HuntRequest, + resultTimeouts?: GetResultTimeouts, + cancellationController?: AbortController, + ): Promise>; + /** + * Solve TSPD task * You will get response within 10 - 180 secs period depending on service workload. */ - public async Solve( - task: T, + public async Solve( + task: TSPDRequest, resultTimeouts?: GetResultTimeouts, cancellationController?: AbortController, - ): Promise>>; + ): Promise>; /** * Solve Binance task * You will get response within 10 - 180 secs period depending on service workload. diff --git a/src/CapMonsterCloudClientFactory.i.spec.ts b/src/CapMonsterCloudClientFactory.i.spec.ts index adbfde3..771bfae 100644 --- a/src/CapMonsterCloudClientFactory.i.spec.ts +++ b/src/CapMonsterCloudClientFactory.i.spec.ts @@ -19,6 +19,9 @@ import { ProsopoRequest } from './Requests/ProsopoRequest'; import { TemuRequest } from './Requests/TemuRequest'; import { YidunRequest } from './Requests/YidunRequest'; import { MTCaptchaRequest } from './Requests/MTCaptchaRequest'; +import { CastleRequest } from './Requests/CastleRequest'; +import { TSPDRequest } from './Requests/TSPDRequest'; +import { HuntRequest } from './Requests/HuntRequest'; const { version } = require('../package.json'); // eslint-disable-line @typescript-eslint/no-var-requires @@ -1170,4 +1173,171 @@ describe('Check integration tests for CapMonsterCloudClientFactory()', () => { expect(await srv.destroy()).toBeUndefined(); }); + + it('should solve Castle Task', async () => { + expect.assertions(5); + + const srv = await createServerMock({ + responses: [ + { responseBody: '{"errorId":0,"taskId":1234567}' }, + { responseBody: '{"errorId":0,"status":"ready","solution":{"token":"castle-token"}}' }, + ], + }); + + const cmcClient = CapMonsterCloudClientFactory.Create( + new ClientOptions({ clientKey: '', serviceUrl: `http://localhost:${srv.address.port}` }), + ); + + const castleRequest = new CastleRequest({ + websiteURL: 'https://example.com/castle', + websiteKey: 'pk_test_123', + metadata: { + wUrl: 'https://s.rsg.sc/auth/js/20251234bgef/build/cw.js', + swUrl: 'https://s.rsg.sc/auth/js/20251213bgef/build/csw.js', + count: 1, + }, + }); + + const task = await cmcClient.Solve(castleRequest); + + expect(srv.caughtRequests[0]).toHaveProperty( + 'body', + '{"clientKey":"","task":{"type":"CustomTask","websiteURL":"https://example.com/castle","websiteKey":"pk_test_123","metadata":{"wUrl":"https://s.rsg.sc/auth/js/20251234bgef/build/cw.js","swUrl":"https://s.rsg.sc/auth/js/20251213bgef/build/csw.js","count":1},"class":"Castle"},"softId":54}', + ); + expect(srv.caughtRequests[1]).toHaveProperty('body', '{"clientKey":"","taskId":1234567}'); + expect(task).toHaveProperty('solution'); + expect(task).toHaveProperty('solution.token', 'castle-token'); + + expect(await srv.destroy()).toBeUndefined(); + }); + + it('should solve Castle Task with Proxy', async () => { + expect.assertions(5); + + const srv = await createServerMock({ + responses: [ + { responseBody: '{"errorId":0,"taskId":1234567}' }, + { responseBody: '{"errorId":0,"status":"ready","solution":{"token":"castle-token"}}' }, + ], + }); + + const cmcClient = CapMonsterCloudClientFactory.Create( + new ClientOptions({ clientKey: '', serviceUrl: `http://localhost:${srv.address.port}` }), + ); + + const castleRequest = new CastleRequest({ + websiteURL: 'https://example.com/castle', + websiteKey: 'pk_test_123', + metadata: { + wUrl: 'https://s.rsg.sc/auth/js/20251234bgef/build/cw.js', + swUrl: 'https://s.rsg.sc/auth/js/20251213bgef/build/csw.js', + count: 1, + }, + proxy: { + proxyType: 'http', + proxyAddress: '8.8.8.8', + proxyPort: 8080, + proxyLogin: 'proxyLoginHere', + proxyPassword: 'proxyPasswordHere', + }, + }); + + const task = await cmcClient.Solve(castleRequest); + + expect(srv.caughtRequests[0]).toHaveProperty( + 'body', + '{"clientKey":"","task":{"type":"CustomTask","websiteURL":"https://example.com/castle","websiteKey":"pk_test_123","metadata":{"wUrl":"https://s.rsg.sc/auth/js/20251234bgef/build/cw.js","swUrl":"https://s.rsg.sc/auth/js/20251213bgef/build/csw.js","count":1},"class":"Castle","proxyType":"http","proxyAddress":"8.8.8.8","proxyPort":8080,"proxyLogin":"proxyLoginHere","proxyPassword":"proxyPasswordHere"},"softId":54}', + ); + expect(srv.caughtRequests[1]).toHaveProperty('body', '{"clientKey":"","taskId":1234567}'); + expect(task).toHaveProperty('solution'); + expect(task).toHaveProperty('solution.token', 'castle-token'); + + expect(await srv.destroy()).toBeUndefined(); + }); + + it('should solve TSPD Task', async () => { + expect.assertions(5); + + const srv = await createServerMock({ + responses: [ + { responseBody: '{"errorId":0,"taskId":1234567}' }, + { responseBody: '{"errorId":0,"status":"ready","solution":{"token":"tspd-token"}}' }, + ], + }); + + const cmcClient = CapMonsterCloudClientFactory.Create( + new ClientOptions({ clientKey: '', serviceUrl: `http://localhost:${srv.address.port}` }), + ); + + const tspdRequest = new TSPDRequest({ + websiteURL: 'https://example.com/tspd', + userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Safari/537.36', + metadata: { + tspdCookie: 'TS386a400d029=example', + htmlPageBase64: 'html-base64', + }, + proxy: { + proxyType: 'http', + proxyAddress: '8.8.8.8', + proxyPort: 8080, + proxyLogin: 'proxyLoginHere', + proxyPassword: 'proxyPasswordHere', + }, + }); + + const task = await cmcClient.Solve(tspdRequest); + + expect(srv.caughtRequests[0]).toHaveProperty( + 'body', + '{"clientKey":"","task":{"type":"CustomTask","websiteURL":"https://example.com/tspd","userAgent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Safari/537.36","metadata":{"tspdCookie":"TS386a400d029=example","htmlPageBase64":"html-base64"},"class":"tspd","proxyType":"http","proxyAddress":"8.8.8.8","proxyPort":8080,"proxyLogin":"proxyLoginHere","proxyPassword":"proxyPasswordHere"},"softId":54}', + ); + expect(srv.caughtRequests[1]).toHaveProperty('body', '{"clientKey":"","taskId":1234567}'); + expect(task).toHaveProperty('solution'); + expect(task).toHaveProperty('solution.token', 'tspd-token'); + + expect(await srv.destroy()).toBeUndefined(); + }); + + it('should solve Hunt Task', async () => { + expect.assertions(5); + + const srv = await createServerMock({ + responses: [ + { responseBody: '{"errorId":0,"taskId":1234567}' }, + { responseBody: '{"errorId":0,"status":"ready","solution":{"token":"hunt-token"}}' }, + ], + }); + + const cmcClient = CapMonsterCloudClientFactory.Create( + new ClientOptions({ clientKey: '', serviceUrl: `http://localhost:${srv.address.port}` }), + ); + + const huntRequest = new HuntRequest({ + websiteURL: 'https://example.com/hunt', + userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Safari/537.36', + metadata: { + apiGetLib: 'https://www.example.com/hd-api/external/apps/a2157wab1045d68672a63557e0n2a77edbfd15ea/api.js', + data: 'some-data', + }, + proxy: { + proxyType: 'http', + proxyAddress: '8.8.8.8', + proxyPort: 8080, + proxyLogin: 'proxyLoginHere', + proxyPassword: 'proxyPasswordHere', + }, + }); + + const task = await cmcClient.Solve(huntRequest); + + expect(srv.caughtRequests[0]).toHaveProperty( + 'body', + '{"clientKey":"","task":{"type":"CustomTask","websiteURL":"https://example.com/hunt","userAgent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Safari/537.36","metadata":{"apiGetLib":"https://www.example.com/hd-api/external/apps/a2157wab1045d68672a63557e0n2a77edbfd15ea/api.js","data":"some-data"},"class":"HUNT","proxyType":"http","proxyAddress":"8.8.8.8","proxyPort":8080,"proxyLogin":"proxyLoginHere","proxyPassword":"proxyPasswordHere"},"softId":54}', + ); + expect(srv.caughtRequests[1]).toHaveProperty('body', '{"clientKey":"","taskId":1234567}'); + expect(task).toHaveProperty('solution'); + expect(task).toHaveProperty('solution.token', 'hunt-token'); + + expect(await srv.destroy()).toBeUndefined(); + }); }); diff --git a/src/GetTaskResult.ts b/src/GetTaskResult.ts index ff9777f..c5de695 100644 --- a/src/GetTaskResult.ts +++ b/src/GetTaskResult.ts @@ -14,6 +14,9 @@ import { BasiliskResponse } from './Responses/BasiliskResponse'; import { ImpervaResponse } from './Responses/ImpervaResponse'; import { BinanceResponse } from './Responses/BinanceResponse'; import { ComplexImageRecognitionResponse } from './Responses/ComplexImageRecognitionResponse'; +import { CastleResponse } from './Responses/CastleResponse'; +import { TSPDResponse } from './Responses/TSPDResponse'; +import { HuntResponse } from './Responses/HuntResponse'; export enum TaskResultType { Failed = 'Failed', @@ -45,7 +48,10 @@ export type TaskCompletedSolution = | BasiliskResponse | ImpervaResponse | BinanceResponse - | ComplexImageRecognitionResponse; + | ComplexImageRecognitionResponse + | CastleResponse + | TSPDResponse + | HuntResponse; export type TaskCompleted = { type: TaskResultType.Completed; diff --git a/src/Requests/BasiliskRequest/BasiliskRequest.ts b/src/Requests/BasiliskRequest/BasiliskRequest.ts index d249295..e96fc3a 100644 --- a/src/Requests/BasiliskRequest/BasiliskRequest.ts +++ b/src/Requests/BasiliskRequest/BasiliskRequest.ts @@ -10,6 +10,8 @@ export type BasiliskRequestIn = Pick> & { proxy?: ProxyInfoIn }; + +/** + * Castle recognition request. + */ +export class CastleRequest extends CastleRequestBase { + public declare class: 'Castle'; + + constructor({ proxy, ...argsObj }: CastleRequestIn) { + super({ type: TaskType.CustomTask, _class: 'Castle', ...argsObj }); + + if (proxy) { + Object.assign(this, new ProxyInfo(proxy)); + } + } +} diff --git a/src/Requests/CastleRequest/CastleRequestBase.ts b/src/Requests/CastleRequest/CastleRequestBase.ts new file mode 100644 index 0000000..a5a5ec2 --- /dev/null +++ b/src/Requests/CastleRequest/CastleRequestBase.ts @@ -0,0 +1,78 @@ +import { CaptchaRequestBase, CaptchaRequestBaseIn } from '../CaptchaRequestBase'; + +export type CastleMetadata = { + /** + * Link to cw.js + * @example "https://s.rsg.sc/auth/js/20251234bgef/build/cw.js" + */ + wUrl: string; + /** + * Link to csw.js + * @example "https://s.rsg.sc/auth/js/20251213bgef/build/csw.js" + */ + swUrl: string; + /** + * Number of tokens (1..49). Default is 1. + */ + count?: number; +}; + +export type CastleRequestBaseIn = { + /** + * The URL of the page where Castle is located. + */ + websiteURL: string; + /** + * Publishable Key, the Castle identifier. + * @example "pk_1Tk5Yzr1WFzxrJCh7WzMZzY1rHpaOtdK" + */ + websiteKey: string; + /** + * Browser User-Agent. Pass only the actual UA from Windows OS + */ + userAgent?: string; + /** + * Additional metadata required to solve Castle. + */ + metadata: CastleMetadata; + _class: string; +} & CaptchaRequestBaseIn; + +/** + * Base Castle recognition request + */ +export abstract class CastleRequestBase extends CaptchaRequestBase { + /** + * Address of a webpage with Castle. + */ + public websiteURL!: string; + + /** + * Castle website key (Publishable Key). + */ + public websiteKey!: string; + + /** + * Browser User-Agent. Pass only the actual UA from Windows OS + */ + public userAgent?: string; + + /** + * The object that contains additional data about the captcha (wUrl, swUrl, count). + */ + public metadata!: CastleMetadata; + + /** + * Class of captcha object + */ + public class: string; + + constructor({ type, nocache, websiteURL, websiteKey, userAgent, metadata, _class }: CastleRequestBaseIn) { + super({ type, nocache }); + this.websiteURL = websiteURL; + this.websiteKey = websiteKey; + this.userAgent = userAgent; + this.metadata = metadata; + this.class = _class; + } +} diff --git a/src/Requests/CastleRequest/index.ts b/src/Requests/CastleRequest/index.ts new file mode 100644 index 0000000..74d28a3 --- /dev/null +++ b/src/Requests/CastleRequest/index.ts @@ -0,0 +1 @@ +export * from './CastleRequest'; diff --git a/src/Requests/DataDomeRequest/DataDomeRequest.ts b/src/Requests/DataDomeRequest/DataDomeRequest.ts index e34b9ee..382b7ee 100644 --- a/src/Requests/DataDomeRequest/DataDomeRequest.ts +++ b/src/Requests/DataDomeRequest/DataDomeRequest.ts @@ -10,6 +10,8 @@ export type DataDomeRequestIn = Pick> & { + proxy: ProxyInfoIn; +}; + +export class HuntRequest extends HuntRequestBase { + public declare class: 'HUNT'; + + constructor({ proxy, ...argsObj }: HuntRequestIn) { + super({ type: TaskType.CustomTask, _class: 'HUNT', ...argsObj }); + Object.assign(this, new ProxyInfo(proxy)); + } +} diff --git a/src/Requests/HuntRequest/HuntRequestBase.ts b/src/Requests/HuntRequest/HuntRequestBase.ts new file mode 100644 index 0000000..2948aea --- /dev/null +++ b/src/Requests/HuntRequest/HuntRequestBase.ts @@ -0,0 +1,63 @@ +import { CaptchaRequestBase, CaptchaRequestBaseIn } from '../CaptchaRequestBase'; + +export type HuntMetadata = { + /** + * The full link to the api.js file. + * Example: + * https://www.example.com/hd-api/external/apps//api.js + */ + apiGetLib: string; + /** + * The `data` parameter (required only in some solving modes). + */ + data?: string; +}; + +export type HuntRequestBaseIn = { + /** + * The URL of the page where the Hunt CAPTCHA is located. + */ + websiteURL: string; + /** + * Browser User-Agent. + */ + userAgent?: string; + /** + * Additional metadata required to solve Hunt. + */ + metadata: HuntMetadata; + _class: string; +} & CaptchaRequestBaseIn; + +/** + * Base Hunt recognition request + */ +export abstract class HuntRequestBase extends CaptchaRequestBase { + /** + * Address of a webpage with Hunt. + */ + public websiteURL!: string; + + /** + * Browser User-Agent. + */ + public userAgent?: string; + + /** + * Additional data about the captcha (apiGetLib, data). + */ + public metadata!: HuntMetadata; + + /** + * Class of captcha object + */ + public class!: string; + + constructor({ type, nocache, websiteURL, userAgent, metadata, _class }: HuntRequestBaseIn) { + super({ type, nocache }); + this.websiteURL = websiteURL; + this.userAgent = userAgent; + this.metadata = metadata; + this.class = _class; + } +} diff --git a/src/Requests/HuntRequest/index.ts b/src/Requests/HuntRequest/index.ts new file mode 100644 index 0000000..c07ec5d --- /dev/null +++ b/src/Requests/HuntRequest/index.ts @@ -0,0 +1 @@ +export * from './HuntRequest'; diff --git a/src/Requests/ImpervaRequest/ImpervaRequest.ts b/src/Requests/ImpervaRequest/ImpervaRequest.ts index 2c2aea0..96daf5b 100644 --- a/src/Requests/ImpervaRequest/ImpervaRequest.ts +++ b/src/Requests/ImpervaRequest/ImpervaRequest.ts @@ -8,6 +8,8 @@ export type ImpervaRequestIn = Pick> & { proxy: ProxyInfoIn }; + +/** + * TSPD recognition request. + */ +export class TSPDRequest extends TSPDRequestBase { + public declare class: 'tspd'; + + constructor({ proxy, ...argsObj }: TSPDRequestIn) { + super({ type: TaskType.CustomTask, _class: 'tspd', ...argsObj }); + Object.assign(this, new ProxyInfo(proxy)); + } +} diff --git a/src/Requests/TSPDRequest/TSPDRequestBase.ts b/src/Requests/TSPDRequest/TSPDRequestBase.ts new file mode 100644 index 0000000..f732941 --- /dev/null +++ b/src/Requests/TSPDRequest/TSPDRequestBase.ts @@ -0,0 +1,62 @@ +import { CaptchaRequestBase, CaptchaRequestBaseIn } from '../CaptchaRequestBase'; + +export type TSPDMetadata = { + /** + * Cookies obtained on the TSPD challenge page. + */ + tspdCookie: string; + /** + * The entire TSPD page encoded in base64. + */ + htmlPageBase64: string; +}; + +export type TSPDRequestBaseIn = { + /** + * The URL of the page where the TSPD challenge is located. + */ + websiteURL: string; + /** + * Browser User-Agent. + * Provide only the current Windows UA. + */ + userAgent: string; + /** + * Additional metadata required to solve TSPD. + */ + metadata: TSPDMetadata; + _class: string; +} & CaptchaRequestBaseIn; + +/** + * Base TSPD recognition request + */ +export abstract class TSPDRequestBase extends CaptchaRequestBase { + /** + * Address of a webpage with TSPD. + */ + public websiteURL!: string; + + /** + * Browser User-Agent. + */ + public userAgent!: string; + + /** + * Additional data about the captcha challenge (tspdCookie, htmlPageBase64). + */ + public metadata!: TSPDMetadata; + + /** + * Class of captcha object + */ + public class!: string; + + constructor({ type, nocache, websiteURL, userAgent, metadata, _class }: TSPDRequestBaseIn) { + super({ type, nocache }); + this.websiteURL = websiteURL; + this.userAgent = userAgent; + this.metadata = metadata; + this.class = _class; + } +} diff --git a/src/Requests/TSPDRequest/index.ts b/src/Requests/TSPDRequest/index.ts new file mode 100644 index 0000000..b4972fc --- /dev/null +++ b/src/Requests/TSPDRequest/index.ts @@ -0,0 +1 @@ +export * from './TSPDRequest'; diff --git a/src/Requests/Task.ts b/src/Requests/Task.ts index f3be41b..0dd47e8 100644 --- a/src/Requests/Task.ts +++ b/src/Requests/Task.ts @@ -9,9 +9,20 @@ import { ComplexImageHCaptchaRequest } from './ComplexImageHCaptchaRequest'; import { ComplexImageRecaptchaRequest } from './ComplexImageRecaptchaRequest'; import { ComplexImageFunCaptchaRequest } from './ComplexImageFunCaptchaRequest'; import { DataDomeRequest } from './DataDomeRequest'; +import { TenDIRequest } from './TenDIRequest'; import { BasiliskRequest } from './BasiliskRequest'; import { ImpervaRequest } from './ImpervaRequest'; import { BinanceRequest } from './BinanceRequest'; +import { ComplexImageTaskRecognitionRequest } from './ComplexImageTaskRecognitionRequest'; +import { AmazonRequest } from './AmazonRequest'; +import { TurnstileRequest } from './TurnstileRequest'; +import { ProsopoRequest } from './ProsopoRequest'; +import { TemuRequest } from './TemuRequest'; +import { YidunRequest } from './YidunRequest'; +import { MTCaptchaRequest } from './MTCaptchaRequest'; +import { CastleRequest } from './CastleRequest'; +import { HuntRequest } from './HuntRequest'; +import { TSPDRequest } from './TSPDRequest'; /** * Universal type for recognition request @@ -27,7 +38,18 @@ export type Task = | ComplexImageHCaptchaRequest | ComplexImageRecaptchaRequest | ComplexImageFunCaptchaRequest + | TurnstileRequest | DataDomeRequest + | TenDIRequest | BasiliskRequest | ImpervaRequest - | BinanceRequest; + | BinanceRequest + | ComplexImageTaskRecognitionRequest + | AmazonRequest + | ProsopoRequest + | TemuRequest + | YidunRequest + | MTCaptchaRequest + | CastleRequest + | TSPDRequest + | HuntRequest; diff --git a/src/Requests/TemuRequest/TemuRequest.ts b/src/Requests/TemuRequest/TemuRequest.ts index 17bedcc..c2440a7 100644 --- a/src/Requests/TemuRequest/TemuRequest.ts +++ b/src/Requests/TemuRequest/TemuRequest.ts @@ -10,6 +10,8 @@ export type TemuRequestIn = Pick; + } + >; +}; diff --git a/src/index.ts b/src/index.ts index 2b77078..75f3adc 100644 --- a/src/index.ts +++ b/src/index.ts @@ -26,6 +26,9 @@ import { ProsopoRequest, ProsopoRequestIn } from './Requests/ProsopoRequest'; import { TemuRequest, TemuRequestIn } from './Requests/TemuRequest'; import { YidunRequest, YidunRequestIn } from './Requests/YidunRequest'; import { MTCaptchaRequest, MTCaptchaRequestIn } from './Requests/MTCaptchaRequest'; +import { CastleRequest, CastleRequestIn } from './Requests/CastleRequest'; +import { TSPDRequest, TSPDRequestIn } from './Requests/TSPDRequest'; +import { HuntRequest, HuntRequestIn } from './Requests/HuntRequest'; export default { CapMonsterCloudClientFactory, @@ -52,6 +55,9 @@ export default { TemuRequest, YidunRequest, MTCaptchaRequest, + CastleRequest, + TSPDRequest, + HuntRequest, }; export { @@ -105,4 +111,10 @@ export { YidunRequestIn, MTCaptchaRequest, MTCaptchaRequestIn, + CastleRequest, + CastleRequestIn, + TSPDRequest, + TSPDRequestIn, + HuntRequest, + HuntRequestIn, }; From 145d7b12652eb81f205841608825fb28e95284d8 Mon Sep 17 00:00:00 2001 From: Kirill Bushmin Date: Wed, 25 Mar 2026 16:33:17 +0300 Subject: [PATCH 2/3] CCL-7545 fixed after merge --- src/GetResultTimeouts.ts | 9 +++++++++ src/Requests/AltchaRequest/AltchaRequest.ts | 2 ++ src/Requests/Task.ts | 2 ++ 3 files changed, 13 insertions(+) diff --git a/src/GetResultTimeouts.ts b/src/GetResultTimeouts.ts index fe170b4..d794736 100644 --- a/src/GetResultTimeouts.ts +++ b/src/GetResultTimeouts.ts @@ -29,6 +29,13 @@ export const RecaptchaV3Timeouts = { timeout: 1000 * 180, } as GetResultTimeouts; +export const RecaptchaV3EnterpriseTimeouts = { + firstRequestDelay: 1000 * 1, + firstRequestNoCacheDelay: 1000 * 10, + requestsInterval: 1000 * 3, + timeout: 1000 * 180, +} as GetResultTimeouts; + export const ImageToTextTimeouts = { firstRequestDelay: 350, requestsInterval: 200, @@ -128,6 +135,8 @@ export function detectResultTimeouts(task: Task): GetResultTimeouts { return RecaptchaV2Timeouts; case TaskType.RecaptchaV3TaskProxyless: return RecaptchaV3Timeouts; + case TaskType.RecaptchaV3EnterpriseTask: + return RecaptchaV3EnterpriseTimeouts; case TaskType.TurnstileTask: return TurnstileTimeouts; case TaskType.ComplexImageTask: diff --git a/src/Requests/AltchaRequest/AltchaRequest.ts b/src/Requests/AltchaRequest/AltchaRequest.ts index 459745b..d3e9d66 100644 --- a/src/Requests/AltchaRequest/AltchaRequest.ts +++ b/src/Requests/AltchaRequest/AltchaRequest.ts @@ -10,6 +10,8 @@ export type AltchaRequestIn = Pick Date: Thu, 26 Mar 2026 16:07:13 +0300 Subject: [PATCH 3/3] CCL-7545 updated version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index cabc1f8..aa662bd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@zennolab_com/capmonstercloud-client", - "version": "2.5.1", + "version": "2.6.1", "description": "Official JS client library for https://capmonster.cloud/ captcha recognition service", "main": "dist/index.js", "types": "dist/index.d.ts",