Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 5 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
![img.png](images/keyNode.png)
4. Select Task Type:

![img.png](images/selectCaptcha.png)
![selectCaptcha.png](images/selectCaptcha.png)

- Use the Task Type dropdown to choose the kind of captcha you want to solve:
- JSON (Custom Task) – supply any valid CapMonster task JSON.
Expand All @@ -28,15 +28,14 @@
- Cloudflare Turnstile (token, managed challenge, waiting room)
- Complex Image Tasks (click, recognition)
- DataDome, Basilisk, TenDI, Amazon (multiple variants), Binance, Imperva, Prosopo, Temu, Yidun, MTCaptcha, Altcha, FunCaptcha, Castle, TSPD, Hunt
- Some task types support optional proxy settings.
![img_5.png](images/img_5.png)
- Some task types support optional proxy settings.
![selectCaptchaWithProxy.png](images/selectCaptchaWithProxy.png)

5. **Customize Payload**:
- For JSON tasks, supply a full CapMonster JSON object without clientKey.
- For built-in task types, fill the provided fields (e.g., websiteURL, websiteKey, userAgent, metadata).
- If the task supports proxies, enable Use Proxy and fill the proxy details.
-
![img_2.png](images/img_2.png)
- If the task supports proxies, enable Use Proxy and fill the proxy details.![img_2.png](images/img_2.png)

- Find the exact JSON structure in the [Official Task Documentation](https://docs.capmonster.cloud/docs/captchas/).
```json
{
Expand Down
Binary file added images/selectCaptchaWithProxy.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions nodes/CapmonsterCloud/CapmonsterCloud.node.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"nodeVersion": "1.0",
"codexVersion": "1.0",
"categories": ["Development", "Automation"],
"details": "Solve various CAPTCHA types using CapMonster Cloud.\n\nSupported CAPTCHA types:\n\n• reCAPTCHA V2 / V2 Enterprise\n• reCAPTCHA V3 / V3 Enterprise\n• Cloudflare Turnstile\n• GeeTest (V3 / V4)\n• FunCaptcha (Arkose Labs)\n• DataDome\n• Imperva\n• Amazon WAF\n• Binance\n• Basilisk\n• TenDI\n• Altcha\n• Yidun\n• Prosopo\n• MTCaptcha\n• Castle\n• TSPD\n• Hunt\n\nYou can also provide custom JSON tasks for advanced use cases.",
"resources": {
"primaryDocumentation": [
{
Expand Down
18 changes: 8 additions & 10 deletions nodes/CapmonsterCloud/CapmonsterCloud.node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ import {
} from 'n8n-workflow';

import { request, waitForResult } from './transport/request';
import { taskBuilders } from './tasks';
import allFields from './descriptions';
import { TaskType } from './types';
import { softId } from './const';
import { taskBuilders } from './taskBuilder';
import { allFields } from './fields';

type CapmonsterResponse = {
errorId: number;
Expand All @@ -22,14 +22,15 @@ type CreateTaskResponse = CapmonsterResponse & {
taskId: number;
};


export class CapmonsterCloud implements INodeType {
description: INodeTypeDescription = {
displayName: 'CapMonster Cloud',
name: 'capmonsterCloud',
icon: 'file:favicon.svg',
group: ['transform'],
version: 1,
description: 'Solve captchas via CapMonster Cloud',
description: 'Node for solving CAPTCHAs via CapMonsterCloud service.',
defaults: { name: 'CapMonster Cloud' },
inputs: ['main'],
outputs: ['main'],
Expand All @@ -52,12 +53,11 @@ export class CapmonsterCloud implements INodeType {
const credentials = await this.getCredentials('capmonsterCloudApi');
const apiKey = credentials.apiKey as string;

const taskType = this.getNodeParameter('taskType', i) as TaskType;
const operation = this.getNodeParameter('operation', i) as TaskType;

let task: IDataObject;


if (taskType === 'json') {
if (operation === 'json') {
const raw = this.getNodeParameter('taskJson', i) as string;

try {
Expand All @@ -74,19 +74,17 @@ export class CapmonsterCloud implements INodeType {
);
}
} else {

const builder = taskBuilders[taskType];
const builder = taskBuilders[operation];

if (!builder) {
throw new NodeOperationError(this.getNode(), `Unsupported task type: ${taskType}`, {
throw new NodeOperationError(this.getNode(), `Unsupported task type: ${operation}`, {
itemIndex: i,
});
}

task = builder.call(this, i);
}


task = Object.fromEntries(
Object.entries(task).filter(([, v]) => v !== undefined && v !== ''),
);
Expand Down
89 changes: 89 additions & 0 deletions nodes/CapmonsterCloud/captchas/altcha.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import { INodeProperties, IDataObject, IExecuteFunctions } from 'n8n-workflow';
import { userAgent } from '../const';
import { getProxyFields } from '../proxy';

export const altcha: INodeProperties[] = [
{
displayName: 'Website URL',
name: 'websiteURL',
type: 'string',
required: true,
displayOptions: { show: { operation: ['altcha'] } },
default: '',
description: 'The URL of the page with Altcha',
},
{
displayName: 'Website Key',
name: 'websiteKey',
type: 'string',
displayOptions: { show: { operation: ['altcha'] } },
default: '',
description: 'Optional Altcha website key (empty string allowed)',
},
{
displayName: 'User Agent',
name: 'userAgent',
type: 'string',
required: true,
displayOptions: { show: { operation: ['altcha'] } },
default: userAgent,
description: 'Browser User-Agent header',
},
{
displayName: 'Challenge',
name: 'challenge',
type: 'string',
required: true,
displayOptions: { show: { operation: ['altcha'] } },
default: '',
description: 'Unique task identifier obtained from the website',
},
{
displayName: 'Iterations',
name: 'iterations',
type: 'string',
required: true,
displayOptions: { show: { operation: ['altcha'] } },
default: '',
description: 'Number of hashing iterations (maxnumber value)',
},
{
displayName: 'Salt',
name: 'salt',
type: 'string',
required: true,
displayOptions: { show: { operation: ['altcha'] } },
default: '',
description: 'Salt value used for hash generation (send full value including all parameters)',
},
{
displayName: 'Signature',
name: 'signature',
type: 'string',
required: true,
displayOptions: { show: { operation: ['altcha'] } },
default: '',
description: 'Digital signature for validation',
},
];

export const buildAltchaTask = function (this: IExecuteFunctions, i: number): IDataObject {
const task: IDataObject = {
type: 'CustomTask',
class: 'Altcha',
websiteURL: this.getNodeParameter('websiteURL', i),
websiteKey: this.getNodeParameter('websiteKey', i) || undefined,
userAgent: this.getNodeParameter('userAgent', i),
metadata: {
challenge: this.getNodeParameter('challenge', i),
iterations: this.getNodeParameter('iterations', i),
salt: this.getNodeParameter('salt', i),
signature: this.getNodeParameter('signature', i),
},
};

return {
...task,
...getProxyFields.call(this, i),
};
};
79 changes: 79 additions & 0 deletions nodes/CapmonsterCloud/captchas/amazonFullChallenge.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { INodeProperties, IDataObject, IExecuteFunctions } from 'n8n-workflow';
import { getProxyFields } from '../proxy';

export const amazonFullChallenge: INodeProperties[] = [
{
displayName: 'Website URL',
name: 'websiteURL',
type: 'string',
required: true,
displayOptions: { show: { operation: ['amazonFullChallenge'] } },
default: '',
},
{
displayName: 'Challenge Script',
name: 'challengeScript',
type: 'string',
required: true,
displayOptions: { show: { operation: ['amazonFullChallenge'] } },
default: '',
},
{
displayName: 'Website Key',
name: 'websiteKey',
type: 'string',
required: true,
displayOptions: { show: { operation: ['amazonFullChallenge'] } },
default: '',
},
{
displayName: 'Context',
name: 'context',
type: 'string',
required: true,
displayOptions: { show: { operation: ['amazonFullChallenge'] } },
default: '',
},
{
displayName: 'IV',
name: 'iv',
type: 'string',
required: true,
displayOptions: { show: { operation: ['amazonFullChallenge'] } },
default: '',
},
{
displayName: 'Captcha Script',
name: 'captchaScript',
type: 'string',
displayOptions: { show: { operation: ['amazonFullChallenge'] } },
default: '',
},
{
displayName: 'Cookie Solution',
name: 'cookieSolution',
type: 'boolean',
displayOptions: { show: { operation: ['amazonFullChallenge'] } },
default: false,
},
];

export const buildAmazonFullChallenge = function (this: IExecuteFunctions, i: number): IDataObject {
const result: IDataObject = {
type: 'AmazonTask',
websiteURL: this.getNodeParameter('websiteURL', i),
challengeScript: this.getNodeParameter('challengeScript', i),
websiteKey: this.getNodeParameter('websiteKey', i),
context: this.getNodeParameter('context', i),
iv: this.getNodeParameter('iv', i),
...getProxyFields.call(this, i),
};

const captchaScript = this.getNodeParameter('captchaScript', i, '') as string;
if (captchaScript) result.captchaScript = captchaScript;

const cookieSolution = this.getNodeParameter('cookieSolution', i, false) as boolean;
if (cookieSolution) result.cookieSolution = cookieSolution;

return result;
};
85 changes: 85 additions & 0 deletions nodes/CapmonsterCloud/captchas/amazonInvisibleChallenge.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import { INodeProperties, IDataObject, IExecuteFunctions } from 'n8n-workflow';
import { getProxyFields } from '../proxy';

export const amazonInvisibleChallenge: INodeProperties[] = [
{
displayName: 'Website URL',
name: 'websiteURL',
type: 'string',
required: true,
displayOptions: { show: { operation: ['amazonInvisibleChallenge'] } },
default: '',
},
{
displayName: 'Challenge Script',
name: 'challengeScript',
type: 'string',
required: true,
displayOptions: { show: { operation: ['amazonInvisibleChallenge'] } },
default: '',
},
{
displayName: 'Captcha Script',
name: 'captchaScript',
type: 'string',
required: true,
displayOptions: { show: { operation: ['amazonInvisibleChallenge'] } },
default: '',
description: 'Can be any string',
},
{
displayName: 'Website Key',
name: 'websiteKey',
type: 'string',
required: true,
displayOptions: { show: { operation: ['amazonInvisibleChallenge'] } },
default: '',
description: 'Can be any string',
},
{
displayName: 'Context',
name: 'context',
type: 'string',
required: true,
displayOptions: { show: { operation: ['amazonInvisibleChallenge'] } },
default: '',
description: 'Can be any string',
},
{
displayName: 'IV',
name: 'iv',
type: 'string',
required: true,
displayOptions: { show: { operation: ['amazonInvisibleChallenge'] } },
default: '',
description: 'Can be any string',
},
{
displayName: 'Cookie Solution',
name: 'cookieSolution',
type: 'boolean',
displayOptions: { show: { operation: ['amazonInvisibleChallenge'] } },
default: true,
},
];

export const buildAmazonInvisibleChallenge = function (
this: IExecuteFunctions,
i: number,
): IDataObject {
const result: IDataObject = {
type: 'AmazonTask',
websiteURL: this.getNodeParameter('websiteURL', i),
challengeScript: this.getNodeParameter('challengeScript', i),
captchaScript: this.getNodeParameter('captchaScript', i),
websiteKey: this.getNodeParameter('websiteKey', i),
context: this.getNodeParameter('context', i),
iv: this.getNodeParameter('iv', i),
...getProxyFields.call(this, i),
};

const cookieSolution = this.getNodeParameter('cookieSolution', i, true) as boolean;
if (cookieSolution) result.cookieSolution = cookieSolution;

return result;
};
Loading
Loading