Skip to content

Commit 9e75fe2

Browse files
Merge pull request #13 from 2captcha/RC-2646
RC-2646 Add Grid method
2 parents 6ea78f5 + e03686c commit 9e75fe2

12 files changed

+226
-34
lines changed

README.md

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ The easiest way to quickly integrate the [2Captcha](https://2captcha.com/) captc
2525
- [MTCaptcha](#mtcaptcha)
2626
- [Friendly Captcha](#friendly-captcha)
2727
- [Bounding Box Method](#bounding-box-method)
28+
- [Grid](#grid)
2829
- [Other methods](#other-methods)
2930
- [goodReport](#goodreport)
3031
- [badReport](#badreport)
@@ -440,7 +441,7 @@ solver.coordinates({
440441
})
441442
```
442443

443-
### Bounding Box Method:
444+
### Bounding Box Method
444445

445446
<sup>[API method description.](https://2captcha.com/2captcha-api#bounding_box)</sup>
446447

@@ -462,6 +463,28 @@ solver.boundingBox({
462463
})
463464
```
464465

466+
### Grid
467+
468+
<sup>[API method description.](https://2captcha.com/2captcha-api#grid)</sup>
469+
470+
This method allows to solve any captcha where image can be divided into equal parts like reCAPTCHA V2 or hCaptcha. A grid is applied above the image. And you receive the numbers clicked boxes.
471+
472+
> [!IMPORTANT]
473+
> You must to send instruction `imginstructions` or `textinstructions`.
474+
475+
```js
476+
solver.grid({
477+
body: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAR4AAACwCAIAAAB...",
478+
textinstructions: "Select cars in the image"
479+
})
480+
.then((res) => {
481+
console.log(res);
482+
})
483+
.catch((err) => {
484+
console.log(err);
485+
})
486+
```
487+
465488
## Other methods
466489

467490
### goodReport

examples/boundingBox.js

Lines changed: 8 additions & 6 deletions
Large diffs are not rendered by default.

examples/grid.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
const TwoCaptcha = require("../dist/index.js");
2+
require('dotenv').config();
3+
const APIKEY = process.env.APIKEY
4+
const solver = new TwoCaptcha.Solver(APIKEY);
5+
const fs = require('fs')
6+
const imageBase64 = fs.readFileSync("./media/recaptchaGrid3x3.jpg", "base64")
7+
8+
solver.grid({
9+
body: imageBase64,
10+
textinstructions: "Select cars in the image"
11+
})
12+
.then((res) => {
13+
console.log(res);
14+
})
15+
.catch((err) => {
16+
console.log(err);
17+
})

examples/grid_options.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
const TwoCaptcha = require("../dist/index.js");
2+
require("dotenv").config();
3+
const APIKEY = process.env.APIKEY;
4+
const solver = new TwoCaptcha.Solver(APIKEY);
5+
const fs = require("fs");
6+
const imageBase64 = fs.readFileSync("./media/recaptchaGrid4x4.jpg", "base64");
7+
const imageInstructionsBase64 = fs.readFileSync("./media/recaptchaGridImginstructions4x4.jpg", "base64");
8+
9+
solver.grid({
10+
body: imageBase64,
11+
textinstructions: "Select all squares with stairs",
12+
imginstructions: imageInstructionsBase64,
13+
cols: 4,
14+
rows: 4,
15+
minClicks: 2,
16+
maxClicks: 6,
17+
lang: "en",
18+
canSkip: 1,
19+
// pingback: '123.123.123.123' /* More info about pingback https://2captcha.com/setting/pingback */
20+
// previousId: '123456789'
21+
})
22+
.then((res) => {
23+
console.log(res);
24+
})
25+
.catch((err) => {
26+
console.log(err);
27+
});

examples/media/boundingBox.jpg

66.4 KB
Loading
16.7 KB
Loading

examples/media/recaptchaGrid3x3.jpg

65.4 KB
Loading

examples/media/recaptchaGrid4x4.jpg

351 KB
Loading
Loading

src/structs/2captcha.ts

Lines changed: 100 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import * as utils from "../utils/generic"
44
import getProviderData from "./providers/providers"
55
import { softId } from "./constants/constants"
66
import checkCaptchaParams from "../utils/checkCaptchaParams"
7+
import renameParams from "../utils/renameParams"
78

89

910
const provider = getProviderData ()
@@ -44,15 +45,15 @@ export interface paramsHCaptcha {
4445

4546
// FixMe:data[key] - how to send this parameter
4647
export interface paramsFunCaptcha {
47-
publickey: string,
48-
pageurl: string,
49-
surl?: string,
50-
header_acao?: boolean,
51-
pingback?: string,
52-
proxy?: string,
53-
proxytype?: string,
54-
userAgent?: string,
55-
data?: string
48+
publickey: string,
49+
pageurl: string,
50+
surl?: string,
51+
header_acao?: boolean,
52+
pingback?: string,
53+
proxy?: string,
54+
proxytype?: string,
55+
userAgent?: string,
56+
data?: string
5657
}
5758

5859
export interface paramsImageCaptcha {
@@ -221,6 +222,21 @@ export interface paramsBoundingBox {
221222
imginstructions?: string,
222223
}
223224

225+
export interface paramsGrid {
226+
body: string,
227+
recaptcha: 1,
228+
rows?: number
229+
cols?: number
230+
minСlicks?: number,
231+
maxСlicks?: number,
232+
previousId?: string,
233+
textinstructions?: string,
234+
imginstructions?: string,
235+
canSkip?: number,
236+
lang?: string,
237+
pingback?: string,
238+
}
239+
224240
/**
225241
* An object containing properties of the captcha solution.
226242
* @typedef {Object} CaptchaAnswer
@@ -398,7 +414,7 @@ export class Solver {
398414
}
399415

400416
/**
401-
* Solves a hCaptcha, returning the result as a string.
417+
* ### Solves a hCaptcha
402418
*
403419
* [Read more about other hCaptcha parameters](https://2captcha.com/2captcha-api#solving_hcaptcha).
404420
*
@@ -452,7 +468,9 @@ export class Solver {
452468
}
453469

454470
/**
455-
* Solves a GeeTest Captcha. [Read more about parameters and solving for Geetest captcha](https://2captcha.com/2captcha-api#solving_geetest).
471+
* ### Solves a GeeTest Captcha.
472+
*
473+
* [Read more about parameters and solving for Geetest captcha](https://2captcha.com/2captcha-api#solving_geetest).
456474
*
457475
* @param {{ gt, challenge, api_server, offline, new_captcha,
458476
* pageurl, pingback, proxy, proxytype, userAgent }} params
@@ -529,7 +547,6 @@ export class Solver {
529547
/**
530548
* ### Solves a GeeTest V4 Captcha.
531549
*
532-
*
533550
* This method accepts an object with the following fields: `pageurl`, `captcha_id`, `pingback`, `proxy`, `proxytype`, `userAgent`.
534551
* The `pageurl` and `captcha_id` fields are required.
535552
*
@@ -581,7 +598,8 @@ export class Solver {
581598
}
582599

583600
/**
584-
* Method for sending Yandex Smart Captcha.
601+
* ### Method for sending Yandex Smart Captcha.
602+
*
585603
* This method accepts an object with the following fields: `pageurl`, `sitekey`, `pingback`, `proxy`, `proxytype`.
586604
* The `pageurl` and `sitekey` fields are required.
587605
*
@@ -633,7 +651,9 @@ export class Solver {
633651
}
634652

635653
/**
636-
* Solves a image-based captcha. [Read more about parameters for image captcha](https://2captcha.com/2captcha-api#solving_normal_captcha).
654+
* ### Solves a image-based captcha.
655+
*
656+
* [Read more about parameters for image captcha](https://2captcha.com/2captcha-api#solving_normal_captcha).
637657
*
638658
* @param {{ body,
639659
* phrase,
@@ -984,17 +1004,6 @@ export class Solver {
9841004
}
9851005
}
9861006

987-
/**
988-
* pageurl: string,
989-
captchakey: string,
990-
api_server?: string,
991-
version?: string,
992-
header_acao?: boolean,
993-
pingback?: string,
994-
proxy?: string,
995-
proxytype?: string,
996-
*/
997-
9981007
/**
9991008
* ### Solves Capy Puzzle captcha
10001009
*
@@ -1342,6 +1351,72 @@ public async boundingBox(params: paramsBoundingBox): Promise<CaptchaAnswer> {
13421351
}
13431352
}
13441353

1354+
1355+
/**
1356+
* ### Grid method
1357+
*
1358+
* The method can be used to bypass tasks where a grid is applied to an image and you need to click on grid tiles, like reCAPTCHA or hCaptcha images.
1359+
*
1360+
* @param {{ body, textinstructions, imginstructions, rows, cols, minСlicks, maxСlicks, previousId, canSkip, lang, pingback}} params Parameters Grid Method as an object.
1361+
* @param {string} params.body `Base64`- encoded captcha image.
1362+
* @param {string} params.textinstructions Text will be shown to worker to help him to select object on the image correctly. For example: "*Select cars in the image*". **Optional parameter**, if the instruction already exists in the form of the `imginstructions`.
1363+
* @param {string} params.imginstructions Image with instruction for worker to help him to select object on the image correctly. The image must be encoded in `Base64` format. **Optional parameter**, if the instruction already exists in the form of the `textinstructions`.
1364+
* @param {number} params.rows Number of rows in grid captcha.
1365+
* @param {number} params.cols Number of columns in grid captcdha.
1366+
* @param {number} params.minСlicks The minimum number of tiles that must be selected. Can't be more than `rows` * `cols`.
1367+
* @param {number} params.maxСlicks The maximum number of tiles that can be selected on the image.
1368+
* @param {string} params.previousId Id of your previous request with the same captcha challenge.
1369+
* @param {number} params.canSkip Set the value to `1` only if it's possible that there's no images matching to the instruction. We'll provide a button "No matching images" to worker and you will receive `No_matching_images` as answer.
1370+
* @param {string} params.lang Language code. [See the list of supported languages](https://2captcha.com/2captcha-api#language).
1371+
* @param {string} params.pingback params.pingback URL for pingback (callback) response that will be sent when captcha is solved. URL should be registered on the server. [More info here](https://2captcha.com/2captcha-api#pingback).
1372+
*
1373+
* @example
1374+
* solver.grid({
1375+
* body: 'iVBORw0KGgoAAAANSUhEUgAAAcIA...',
1376+
* textinstructions: "Select cars in the image",
1377+
* imginstructions: '/9j/4AAQSkZJRgABAQEA...'
1378+
* })
1379+
* .then((res) => {
1380+
* console.log(res);
1381+
* })
1382+
* .catch((err) => {
1383+
* console.log(err);
1384+
* })
1385+
*/
1386+
public async grid(params: paramsGrid): Promise<CaptchaAnswer> {
1387+
checkCaptchaParams(params, "grid")
1388+
1389+
params = await renameParams(params)
1390+
1391+
const payload = {
1392+
...params,
1393+
method: "base64",
1394+
recaptcha: 1,
1395+
...this.defaultPayload,
1396+
}
1397+
1398+
const URL = this.in
1399+
const response = await fetch(URL, {
1400+
body: JSON.stringify( payload ),
1401+
method: "post",
1402+
headers: {'Content-Type': 'application/json'}
1403+
})
1404+
const result = await response.text()
1405+
1406+
let data;
1407+
try {
1408+
data = JSON.parse(result)
1409+
} catch {
1410+
throw new APIError(result)
1411+
}
1412+
1413+
if (data.status == 1) {
1414+
return this.pollResponse(data.request)
1415+
} else {
1416+
throw new APIError(data.request)
1417+
}
1418+
}
1419+
13451420
/**
13461421
* Reports a captcha as correctly solved.
13471422
*

0 commit comments

Comments
 (0)