diff --git a/README.md b/README.md
index 37ab0ed..c9ea2ea 100644
--- a/README.md
+++ b/README.md
@@ -55,6 +55,7 @@ Examples of API requests for different captcha types are available on the [JavaS
- [TSPD](#tspd)
- [Basilisk](#basilisk)
- [Hunt](#hunt)
+ - [Drag and Drop](#drag-and-drop)
- [Other methods](#other-methods)
- [goodReport](#goodreport)
- [badReport](#badreport)
@@ -955,6 +956,30 @@ console.log(err);
})
```
+### Drag and Drop
+
+[API method description.](https://2captcha.com/2captcha-api#drag-and-drop-captcha)
+
+A method for solving captcha where one or more images need to be dragged onto specific positions on a background image.
+
+Required parameters: `body`, `images`.
+
+The result (`data`) is a pipe-separated string of coordinates, for example `"120,340|null|210,90"`. The order matches the order of the `images` array you sent. `null` means the corresponding image wasn't moved — it does **not** mean an error or coordinates `(0,0)`.
+
+```js
+solver.dragAndDrop({
+ body: "BASE64_BACKGROUND_IMAGE",
+ images: ["BASE64_IMAGE_1", "BASE64_IMAGE_2"],
+ textinstructions: "Drag the images to proper position"
+})
+.then((res) => {
+console.log(res);
+})
+.catch((err) => {
+console.log(err);
+})
+```
+
## Other methods
### goodReport
diff --git a/examples/dragAndDrop.js b/examples/dragAndDrop.js
new file mode 100644
index 0000000..2240427
--- /dev/null
+++ b/examples/dragAndDrop.js
@@ -0,0 +1,23 @@
+const fs = require('fs');
+const TwoCaptcha = require("../dist/index.js");
+require('dotenv').config();
+const APIKEY = process.env.APIKEY;
+const solver = new TwoCaptcha.Solver(APIKEY);
+
+const backgroundBase64 = fs.readFileSync("./media/drag_drop_main.jpeg", "base64")
+const imagesBase64 = [
+ fs.readFileSync("./media/drag_drop_image1.jpeg", "base64"),
+ fs.readFileSync("./media/drag_drop_image2.jpeg", "base64")
+]
+
+solver.dragAndDrop({
+ body: backgroundBase64,
+ images: imagesBase64,
+ textinstructions: "Drag the images to proper position"
+})
+.then((res) => {
+ console.log(res);
+})
+.catch((err) => {
+ console.log(err);
+})
diff --git a/examples/media/drag_drop_image1.jpeg b/examples/media/drag_drop_image1.jpeg
new file mode 100644
index 0000000..f1bb604
Binary files /dev/null and b/examples/media/drag_drop_image1.jpeg differ
diff --git a/examples/media/drag_drop_image2.jpeg b/examples/media/drag_drop_image2.jpeg
new file mode 100644
index 0000000..86ed7a8
Binary files /dev/null and b/examples/media/drag_drop_image2.jpeg differ
diff --git a/examples/media/drag_drop_main.jpeg b/examples/media/drag_drop_main.jpeg
new file mode 100644
index 0000000..675ba0d
Binary files /dev/null and b/examples/media/drag_drop_main.jpeg differ
diff --git a/package-lock.json b/package-lock.json
index 7900474..5de7324 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "@2captcha/captcha-solver",
- "version": "1.3.5",
+ "version": "1.3.8",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@2captcha/captcha-solver",
- "version": "1.3.5",
+ "version": "1.3.8",
"license": "MIT",
"dependencies": {
"node-fetch": "^2.6.1"
diff --git a/package.json b/package.json
index fba3aa1..530b4f3 100644
--- a/package.json
+++ b/package.json
@@ -60,7 +60,8 @@
"Alibaba Captcha",
"TSPD",
"Basilisk",
- "Hunt"
+ "Hunt",
+ "Drag and Drop"
],
"scripts": {
"build": "tsc && node ./dist/index.js",
diff --git a/src/structs/2captcha.ts b/src/structs/2captcha.ts
index ae89411..e42bccb 100644
--- a/src/structs/2captcha.ts
+++ b/src/structs/2captcha.ts
@@ -379,6 +379,15 @@ export interface paramsHunt {
proxytype?: string,
}
+export interface paramsDragAndDrop {
+ body: string,
+ images: string[],
+ textinstructions?: string,
+ language?: 0 | 1 | 2,
+ lang?: string,
+ pingback?: string,
+}
+
/**
* An object containing properties of the captcha solution.
* @typedef {Object} CaptchaAnswer
@@ -2739,6 +2748,72 @@ public async hunt(params: paramsHunt): Promise {
}
}
+/**
+ * ### Solves Drag & Drop captcha
+ *
+ * A method for solving captcha where one or more images need to be dragged onto specific positions on a background image.
+ * [Read more about Drag & Drop captcha](https://2captcha.com/2captcha-api#drag-and-drop-captcha).
+ *
+ * @param {{ body, images, textinstructions, language, lang, pingback }} params Parameters Drag & Drop Captcha as an object.
+ * @param {string} params.body Background image encoded into Base64 format, without the `data:image/...;base64,` prefix.
+ * @param {string[]} params.images Array of Base64-encoded images to drag. Order matters — the same order is used in the response.
+ * @param {string} params.textinstructions Optional. Text with instruction for solving the captcha, up to 140 characters. For example: "Drag the images to proper position".
+ * @param {number} params.language Optional. `0` - not specified. `1` - Cyrillic captcha. `2` - Latin captcha.
+ * @param {string} params.lang Optional. Language code. [See the list of supported languages](https://2captcha.com/2captcha-api#language).
+ * @param {string} params.pingback Optional. URL for pingback (callback) response that will be sent when captcha is solved. [More info here](https://2captcha.com/2captcha-api#pingback).
+ *
+ * @returns {Promise} The result from the solve. `data` is a pipe-separated string of coordinates, for example `"120,340|null|210,90"`. `null` means the corresponding image wasn't moved.
+ * @throws APIError
+ *
+ * @example
+ * const backgroundBase64 = fs.readFileSync("./media/drag_drop_main.jpeg", "base64")
+ * const imagesBase64 = [
+ * fs.readFileSync("./media/drag_drop_image1.jpeg", "base64"),
+ * fs.readFileSync("./media/drag_drop_image2.jpeg", "base64")
+ * ]
+ *
+ * solver.dragAndDrop({
+ * body: backgroundBase64,
+ * images: imagesBase64,
+ * textinstructions: "Drag the images to proper position"
+ * })
+ * .then((res) => {
+ * console.log(res);
+ * })
+ * .catch((err) => {
+ * console.log(err);
+ * })
+ */
+public async dragAndDrop(params: paramsDragAndDrop): Promise {
+ checkCaptchaParams(params, "drag_drop")
+
+ const payload = {
+ ...this.defaultPayload,
+ ...params,
+ method: "drag_drop",
+ };
+
+ const response = await fetch(this.in, {
+ body: JSON.stringify(payload),
+ method: "post",
+ headers: { "Content-Type": "application/json" }
+ })
+ const result = await response.text()
+
+ let data;
+ try {
+ data = JSON.parse(result)
+ } catch {
+ throw new APIError(result)
+ }
+
+ if (data.status == 1) {
+ return this.pollResponse(data.request)
+ } else {
+ throw new APIError(data.request)
+ }
+}
+
/**
* Reports a captcha as correctly solved.
*
diff --git a/src/utils/checkCaptchaParams.ts b/src/utils/checkCaptchaParams.ts
index df5a407..4d8b3f9 100644
--- a/src/utils/checkCaptchaParams.ts
+++ b/src/utils/checkCaptchaParams.ts
@@ -1,7 +1,7 @@
// Captcha methods for which parameter checking is available
const supportedMethods = ["userrecaptcha", "hcaptcha", "geetest", "geetest_v4","yandex","funcaptcha","lemin","amazon_waf",
"turnstile", "base64", "capy","datadome", "cybersiara", "mt_captcha", "bounding_box", 'friendly_captcha', 'grid',
- 'textcaptcha', 'canvas', 'rotatecaptcha', 'keycaptcha', 'cutcaptcha', 'tencent', 'atb_captcha', 'prosopo', 'captchafox', 'vkimage', 'vkcaptcha', 'temu', 'altcha', 'binance', 'audio', 'yidun', 'alibaba', 'tspd', 'basilisk', 'hunt']
+ 'textcaptcha', 'canvas', 'rotatecaptcha', 'keycaptcha', 'cutcaptcha', 'tencent', 'atb_captcha', 'prosopo', 'captchafox', 'vkimage', 'vkcaptcha', 'temu', 'altcha', 'binance', 'audio', 'yidun', 'alibaba', 'tspd', 'basilisk', 'hunt', 'drag_drop']
// Names of required fields that must be contained in the parameters captcha
const recaptchaRequiredFields = ['pageurl','googlekey']
@@ -42,6 +42,7 @@ const alibabaRequiredFields = ['pageurl', 'scene_id', 'prefix']
const tspdRequiredFields = ['pageurl', 'tspd_cookie', 'html_page_base64', 'proxy', 'proxytype']
const basiliskRequiredFields = ['pageurl', 'sitekey']
const huntRequiredFields = ['pageurl', 'api_get_lib']
+const dragAndDropRequiredFields = ['body', 'images']
/**
* Getting required arguments for a captcha.
@@ -164,6 +165,9 @@ const getRequiredFildsArr = (method: string):Array => {
case "hunt":
requiredFieldsArr = huntRequiredFields
break;
+ case "drag_drop":
+ requiredFieldsArr = dragAndDropRequiredFields
+ break;
}
return requiredFieldsArr
}