reCAPTCHA Recognition: bypass using grid method
Our team regularly enhances the service. 2Captcha provides a service for automatic solving and bypassing reCAPTCHA. According to the CaptchaTheCat rating service 2Captcha is the best reCAPTCHA solver.
We are pleased to announce the latest updates in the Grid method for solving captcha using our captcha recognition service. In this article, we will look in details at how to use the updated API to bypass the reCAPTCHA. This is useful if the reCAPTCHA challenge can not be solved using token method.
The changes in the Grid method are made to provide a captcha-type targeted recognition approach with higher accuracy and reduced recognition time achieved by combining human power with computer vision.
What is reCAPTCHA v2?
reCAPTCHA v2 is a CAPTCHA protection service developed by Google to differentiate between humans and bots. It presents various challenges to users, such as identifying specific objects within a set of 9 images or simply clicking a checkbox labeled "I'm not a robot."
The goal of reCAPTCHA v2 is to ensure that the user interacting with the website is indeed a human and not an automated bot, thereby enhancing security and preventing spam or fraudulent activities.
What's new in the API?
In the article we will consider two types of reCAPTCHA and how to solve them using api and grid method
Now the Grid method accepts an additional parameter imgType
that is used to target the request to a proper recognition pipeline according to the CAPTCHA type. For reCAPTCHA you must set it's value to recaptcha
.
How to solve the reCAPTCHA using the Grid method?
We can divide the process into following steps:
- Clicking the checkbox
- Collecting the task data
- Interacting with the API
- Clicking the grid tiles
To click the checkbox and tiles you can use the corresponding methods of your favorite browser automation framework.
In the article we focus on the steps 2 and 3.
Collecting the data
reCAPTCHA grid challenge consists of:
- task text
- image with 3x3 or 4x4 grid applied
Task text
We can get the text from innerText
property of the element returned by selector .rc-imageselect-desc-wrapper
, and we also need to remove the new line symbols to get the whole text as a one line string
const comment = document.querySelector('.rc-imageselect-desc-wrapper').innerText.replaceAll('\n', ' ')
Image with 4x4 grid
This case is pretty simple, we just need to use the image from an element returned by selector img.rc-image-tile-44
.
const img4x4 = document.querySelector('img.rc-image-tile-44')
Image with 3x3 grid
Initially all the tiles for 3x3 grid are loaded as a single image, but when you click on images, the tiles can be updated with a new small image, so we need to paste these updated images over the initial one.
To get the initial 3x3 image we can use the selector: img.rc-image-tile-33
and to get the updated tiles: img.rc-image-tile-11
.
const initial3x3img = table3x3.querySelector('img.rc-image-tile-33')
const updatedTiles = document.querySelectorAll('img.rc-image-tile-11')
Use the Canvas API
to place the images and tiles properly and to get the base64 encoded version of the images.
Below we provide a JavaScript function that can help you extract the data properly. You can inject this code into the captcha iframe after you click the captcha checkbox. Then, call the getCaptchaData
function once the captcha task is visible. The function returns a Promise
that is resolved with the Object containing the following properties:
Helper function call example:
type
- the API task type:GridTask
body
- the extracted image as base64 stringcomment
- the task text
try {
let data = await getCaptchaData()
console.log(JSON.stringify(data))
} catch (e) {
console.error(e)
}
Helper function code
const getCaptchaData = () => {
return new Promise((resolve, reject)=>{
let canvas = document.createElement('canvas')
let ctx = canvas.getContext('2d')
let comment = document.querySelector('.rc-imageselect-desc-wrapper').innerText.replaceAll('\n', ' ')
let img4x4 = document.querySelector('img.rc-image-tile-44')
if (!img4x4) {
let table3x3 = document.querySelector('table.rc-imageselect-table-33 > tbody')
if (!table3x3) {
reject('Can not find reCAPTCHA elements')
}
initial3x3img = table3x3.querySelector('img.rc-image-tile-33')
canvas.width = initial3x3img.naturalWidth
canvas.height = initial3x3img.naturalHeight
ctx.drawImage(initial3x3img, 0, 0)
let updatedTiles = document.querySelectorAll('img.rc-image-tile-11')
if (updatedTiles.length > 0) {
const pos = [
{ x: 0, y: 0 }, { x: ctx.canvas.width / 3, y: 0 }, { x: ctx.canvas.width / 3 * 2, y: 0 },
{ x: 0, y: ctx.canvas.height / 3 }, { x: ctx.canvas.width / 3, y: ctx.canvas.height / 3 }, { x: ctx.canvas.width / 3 * 2, y: ctx.canvas.height / 3 },
{ x: 0, y: ctx.canvas.height / 3 * 2 }, { x: ctx.canvas.width / 3, y: ctx.canvas.height / 3 * 2 }, { x: ctx.canvas.width / 3 * 2, y: ctx.canvas.height / 3 * 2 }
]
updatedTiles.forEach((t) => {
const ind = t.parentElement.parentElement.parentElement.tabIndex - 3
ctx.drawImage(t, pos[ind - 1].x, pos[ind - 1].y)
})
}
resolve({
rows: 3,
columns: 3,
type: 'GridTask',
comment,
body: canvas.toDataURL().replace(/^data:image\/?[A-z]*;base64,/, '')
})
} else {
canvas.width = img4x4.clientWidth
canvas.height = img4x4.clientHeight
ctx.drawImage(img4x4, 0, 0)
resolve({
rows: 4,
columns: 4,
comment,
body: canvas.toDataURL().replace(/^data:image\/?[A-z]*;base64,/, ''),
type: 'GridTask'
})
}
})
}
Result example
{
"type": "GridTask",
"body": "/9j/4AAQSkZJRgABAQEAYABgAAD/4QBoRXhpZg...",
"imgType": "recaptcha",
"rows": 3,
"columns": 3,
"comment": "Select all images that have cars in them"
}
Interacting with the API
Once we have all the required data, we can make a request to the API to solve our captcha task. Use the data extracted on previous step, add the imgType
parameter set to recaptcha
and indicate the number of columns
and rows
.
Method: POST
API endpoint: https://api.2captcha.com/createTask
Task parameters
Parameter | Type | Required | Description |
---|---|---|---|
type | String | Yes | The task type must be set to GridTask |
imgType | String | Yes | Must be set to recaptcha |
body | String | Yes | Image in base64 format with the task tiles glued together |
comment | String | Yes | The task text in English |
rows | Number | Yes | The number of rows, will be 3 or 4 |
columns | Number | Yes | The number of columns, will be 3 or 4 |
imgInstructions | String | No | Additional task image (when provided) in base64 format |
Request body example
{
"clientKey":"YOUR_API_KEY",
"task": {
"type": "GridTask",
"imgType": "recaptcha",
"body": "iVBORw0KGgoAAAA...",
"comment": "Click on the images that best match the theme of the sample image.",
"rows": 3, // 4
"columns": 3, // 4
"imgInstructions": "iVBORw0KGgoAAA..."
}
}
Result example
{
"errorId": 0,
"status": "ready",
"solution": {
"click": [
3,
4,
7
]
},
"cost": "0.0012",
"ip": "1.2.3.4",
"createTime": 1692863536,
"endTime": 1692863556,
"solveCount": 1
}
Use the click
method of your browser automation framework to click on the corresponding tiles. The selector for tiles is 'div.task'
. Please note that the array of nodes is numerated from 0 and in our API answer the tiles are numerated from 1 to 9. In our example we click in the tiles using pure JavaScript:
document.querySelectorAll('div.task')[3-1].click()
document.querySelectorAll('div.task')[4-1].click()
document.querySelectorAll('div.task')[7-1].click()
You can also use our libraries to quickly implement the method into your code.
Code examples for libraries
Ruby
result = client.grid({
method: 'base64',
key: 'your_api_key',
recaptcha: 1,
json: 1,
recaptchacols: 3,
recaptcharows: 3,
img_type: 'recaptcha',
textinstructions: 'lease click on all entities similar to the following silhouette',
imginstructions: Base64.encode64(File.read('path/to/hint.jpg')),
body: Base64.encode64(File.read('path/to/captcha.jpg')),
previous_id: 0
})
Python
result = solver.grid( method='base64',
body = 'base64',
key='your_api_key',
recaptcha=1,
json=1,
recaptchacols=3,
recaptcharows=3,
img_type='recaptcha',
textinstructions='Please click on all entities similar to the following silhouette',
imginstructions=base64.b64encode(open('path/to/hint.jpg', 'rb').read()).decode('utf-8'),
previous_id=0)
Code example using browser automation
- Puppeteer (javascript): https://github.com/2captcha/puppeteer-recaptcha-solver-using-clicks
- Selenium (Python): https://github.com/2captcha/selenium-recaptcha-solver-using-grid