ReCaptcha2

Table of contents


Description

Added in version 2.4.0.0.

ReCaptcha2 is a bot protection released by Google. A button "I'm not a robot" appears on the web page, when you click on it, several pictures appear, among which you need to select all the images indicated in the title.

It looks like this:

You can see an example of ReCaptcha2 on the Demo page from Google.


How it works

To send ReCaptcha2 for recognition to CapMonster2, you need to create a request that will include an image from several answer options and a task as an additional parameter. Parameter name: "Task". The meaning is a question of ReCaptcha2 itself, for example "Cars".

CapMonster2 sends a response in the form of a string consisting of numbers - numbers of pictures without separators that you need to click on. The numbers are indicated in descending order of probability that the picture shows the specified item.

For example, we need to select pictures with cars. CapMonster2 sent a reply 456. So you need to click on the 4th, 5th and 6th picture, and then click the "Confirm" button. That is, picture 4 most likely contains a car, then 5 and 6.

If CapMonster2 was unable to recognize a car in more than one picture (2 pictures is the minimum possible number of correct answers), then it sends an empty answer so that you can send this ReCaptcha2 to the manual recognition service.


Usage in ZennoPoster

To send ReCaptcha2 from ZennoPoster, you can use the special Recognize ReCaptcha2 action:

In the action, you can change the recognition parameters that are used in the snippet below.

Also ReCaptcha2 can be recognized through SiteKey specifying SiteKey and page URL.

To send ReCaptcha2 from ZennoPoster version higher than 5.9.0.0, you can use the snippet we have prepared:

// Main settings // wait time var waitTime = 1500; // number of attempts to recognize var tryRecognize = 10; // number of attempts to select changing pictures var dynamicImagesRecognizeAttempts = 20; // number of attempts to load an element var tryLoadElement = 60; // get full response bool fullAnswer = false; // show messages about the progress of recognition var needShowMessages = false; // check the correctness of the recognized response var needToCheck = true; // Auxiliary variables // tab Tab tab = instance.ActiveTab; // congratulations, you are not a robot var success = false; // time is over var timeout = false; // task for recaptcha 2 string task = string.Empty; // image url var src = string.Empty; // image in base64 var imageString = string.Empty; // answer to captcha string answer = string.Empty; // captcha has changed var changed = false; // empty answer bool answerIsEmpty = false; // variable captcha bool dynamicCaptcha = false; // enter captcha several times bool notOneEnter = false; var coincidenceReCaptcha2Index = -1; // Checking the passage of protection Action CheckOK = () => { tab.WaitDownloading (); for (int k = 0; k <tryLoadElement; k ++) { System.Threading.Thread.Sleep (waitTime); // wait for the elements to load var check = tab.FindElementByAttribute ("div", "class", "recaptcha-checkbox-checkmark", "regexp", 0); // check if the form disappears var loadedForm = tab.FindElementByAttribute ("div", "class", "primary-controls", "regexp", 0); if (loadedForm.IsVoid) { success = true; break; } else { int xPrimaryControlsDisplaysment = loadedForm.DisplacementInTabWindow.X; int yPrimaryControlsDisplaysment = loadedForm.DisplacementInTabWindow.Y; if (xPrimaryControlsDisplaysment <0 || yPrimaryControlsDisplaysment <0) // there are no visible recaptcha { success = true; break; } if (check.IsVoid) break; } var more = tab.FindElementByAttribute ("div", "class", "rc-imageselect-error-select-more", "regexp", 0); var wrong = tab.FindElementByAttribute ("div", "class", "rc-imageselect-incorrect-response", "regexp", 0); if (! more.IsVoid &&! wrong.IsVoid) { var isNotVisibleMore = more.GetAttribute ("outerhtml"). Replace ("", ""). Contains ("display: none"); var isNotVisibleWrong = wrong.GetAttribute ("outerhtml"). Replace ("", ""). Contains ("display: none"); if (isNotVisibleMore && isNotVisibleWrong) { if (! check.IsVoid) { if (check.OuterHtml.Contains ("style = \" \ "")) { success = true; break; } else break; } } else break; } if (k == (tryLoadElement - 1)) timeout = true; } }; // Confirm response Action VerifyAnswer = () => { project.SendInfoToLog ("Validation after entering dynamic captcha", needShowMessages); tab.WaitDownloading (); // search for the "Confirm" button HtmlElement apply = tab.FindElementById ("recaptcha-verify-button"); if (! apply.IsVoid) apply.Click (); // check if the answer is correct CheckOK (); }; Action InputNotBotText = () => { tab.WaitDownloading (); var inputField = tab.FindElementByAttribute ("input: text", "id", "default-response", "text", 0); if (! inputField.IsVoid) { inputField.SetValue ("I am not robot", "Full"); VerifyAnswer (); } }; Action UpdateImage = () => { project.SendInfoToLog ("Captcha update", needShowMessages); // Update captcha if necessary if (! changed) { HtmlElement reload = tab.FindElementById ("recaptcha-reload-button"); if (! reload.IsVoid) { reload.Click (); InputNotBotText (); } else timeout = true; } changed = false; for (int k = 0; k <tryLoadElement; k ++) { System.Threading.Thread.Sleep (waitTime); // waiting for element load // searching for the picture var testImage = tab.FindElementByAttribute ("img", "class", "rc-image-tile", "regexp", 0); if (testImage.IsVoid) continue; // get image url var newSrc = testImage.GetAttribute ("src"); // if the image has been changed, go out if (newSrc! = src) break; if (k == (tryLoadElement - 1)) timeout = true; } }; Action VisibleIndexReCaptchaDefinition = () => { tab.WaitDownloading (); var recaptchaElementsGroup = tab.FindElementsByAttribute ("div", "class", "recaptcha-checkbox-checkmark", "regexp"); int length = recaptchaElementsGroup.Elements.Length; if (length == 1) { coincidenceReCaptcha2Index = 0; return; } for (int i = 0; i <length; i ++) { var element = recaptchaElementsGroup.Elements [i]; if (! element.IsVoid) { int x = element.DisplacementInTabWindow.X; int y = element.DisplacementInTabWindow.Y; var suspectVisibleElement = tab.GetElementFromPoint (x, y) .DisplacementInTabWindow; if (x == suspectVisibleElement.X && y == suspectVisibleElement.Y && element.Width! = 0 && element.Height! = 0 && x! = 0 && y! = 0) { coincidenceReCaptcha2Index = i; break; } } } }; // Search for recaptcha 2 Action SearchReCaptcha2 = () => { project.SendInfoToLog ("Search for recaptcha 2", needShowMessages); tab.WaitDownloading (); for (int k = 0; k <tryLoadElement; k ++) { VisibleIndexReCaptchaDefinition (); if (coincidenceReCaptcha2Index <0) coincidenceReCaptcha2Index = 0; // search for the "I'm not a robot" button HtmlElement notRobot = tab.FindElementByAttribute ("div", "class", "recaptcha-checkbox-checkmark", "regexp", coincidenceReCaptcha2Index); // button exists if (! notRobot.IsVoid) { // click on the button notRobot.Click (); System.Threading.Thread.Sleep (waitTime); // pause // if captcha input is not required var check = tab.FindElementByAttribute ("div", "class", "recaptcha-checkbox-checkmark", "regexp", coincidenceReCaptcha2Index); if (! check.IsVoid) { if (check.OuterHtml.Contains ("style = \" \ "")) { success = true; timeout = false; break; } } } // the form exists var loadedForm = tab.FindElementByAttribute ("div", "class", "primary-controls", "regexp", 0); if (! loadedForm.IsVoid) break; // wait for the elements to load System.Threading.Thread.Sleep (waitTime); if (k == (tryLoadElement - 1)) timeout = true; } }; // Search for recaptcha job 2 Action SearchTask = () => { tab.WaitDownloading (); project.SendInfoToLog ("Job Search", needShowMessages); dynamicCaptcha = false; notOneEnter = false; answer = String.Empty; for (int k = 0; k <tryLoadElement; k ++) { HtmlElement taskHe = tab.FindElementByAttribute ("div", "class", "rc-imageselect-desc-wrapper", "regexp", 0); if (! taskHe.IsVoid) { task = taskHe.GetAttribute ("innertext"); // get the task string suspecttask = task.ToLower (); if (suspecttask.Contains ("click verify once there are none left") || suspecttask.Contains ("when images will be end") || suspecttask.Contains ("when the images run out") || suspecttask.Contains ("if the image is no longer overshadowed, press \" confirm \ "") || suspecttask.Contains ("cliquez sur le bouton de validation") || suspecttask.Contains ("klicken sie") || suspecttask.Contains ("fai clic su verifica dopo averle selezionate tutte") || suspecttask.Contains ("gdy wybierzesz wszystkie, kliknij weryfikuj")) dynamicCaptcha = true; if (suspecttask.Contains ("if there are none, click skip") || suspecttask.Contains ("if they do not exist, click \" skip \ "") || suspecttask.Contains ("wenn du keine siehst") || suspecttask.Contains ("s'il n'y en a aucune, cliquez sur \" ignorer \ "") || suspecttask.Contains ("if not, click \" skip \ "") || suspecttask.Contains ("yakscho nichogo nema |") || suspecttask.Contains ("ich nie ma, kliknij") || suspecttask.Contains ("se non ne vedi, fai clic su salta")) notOneEnter = true; timeout = false; break; } System.Threading.Thread.Sleep (waitTime); // wait for the element to load if (k == (tryLoadElement - 1)) timeout = true; } }; // Search for an image Action SearchImage = () => { tab.WaitDownloading (); project.SendInfoToLog ("Image Search", needShowMessages); for (int k = 0; k <tryLoadElement; k ++) { HtmlElement image = null; if (dynamicCaptcha) image = tab.FindElementByAttribute ("table", "class", "rc-imageselect-table", "regexp", 0); else image = tab.FindElementByAttribute ("img", "class", "rc-image-tile", "regexp", 0); // if there are images if (! image.IsVoid) { // get the url of the image if (! dynamicCaptcha) src = image.GetAttribute ("src"); imageString = image.DrawToBitmap (! dynamicCaptcha); timeout = false; break; } System.Threading.Thread.Sleep (waitTime); // wait for the elements to load if (k == (tryLoadElement - 1)) timeout = true; } }; // Recognition Action Recognize = () => { project.SendInfoToLog ("Recognition", needShowMessages); var answerString = ZennoPoster.CaptchaRecognition ("CapMonster2.dll", imageString, String.Format ("Task = {0} & FullAnswer = {1} & CapMonsterModule = ZennoLab.ReCaptcha2", task, fullAnswer)); var split = answerString.Split (new [] {"- | -"}, StringSplitOptions.RemoveEmptyEntries); answer = split [0]; }; // Enter the answer Action InputAnswer = () => { if (! String.IsNullOrEmpty (answer) && answer! = "sorry") { project.SendInfoToLog ("Response input and validation", needShowMessages); int count = 0; string [] answers; if (answer.Contains (",")) answers = answer.Split (new [] {","}, StringSplitOptions.RemoveEmptyEntries); else { answers = new string [answer.Length]; for (int i = 0; i <answer.Length; i ++) answers [i] = answer [i] .ToString (); } foreach (string c in answers) { if (fullAnswer) if (count == 2) break; int index = Convert.ToInt32 (c) - 1; HtmlElement he = tab.FindElementByAttribute ("img", "class", "rc-image-tile", "regexp", index); if (! he.IsVoid) { he.Click (); // click on the picture System.Threading.Thread.Sleep (500); // wait a bit } if (fullAnswer) count ++; } // looking for the "Confirm" button HtmlElement apply = tab.FindElementById ("recaptcha-verify-button"); if (! apply.IsVoid) apply.Click (); // check if the answer is correct CheckOK (); if (success) return; // enter the rest of the answer if (fullAnswer) { for (int i = count; i <answer.Length; i ++) { // look for a picture again var testImage = tab.FindElementByAttribute ("img", "class", "rc-image-tile", "regexp", 0); if (testImage.IsVoid) break; // get the url of the image var newSrc = testImage.GetAttribute ("src"); // if the image has changed, then exit if (newSrc! = src) break; else changed = true; // otherwise continue typing int index = Convert.ToInt32 (answer [i] .ToString ()) - 1; var he = tab.FindElementByAttribute ("img", "class", "rc-image-tile", "regexp", index); if (! he.IsVoid) { he.Click (); System.Threading.Thread.Sleep (500); // wait a bit if (! apply.IsVoid) apply.Click (); CheckOK (); if (success) return; } } } } else answerIsEmpty = true; }; // Enter the answer Action InputDynamicAnswer = () => { project.SendInfoToLog ("Entering dynamic captcha response", needShowMessages); string [] answers; if (answer.Contains (",")) answers = answer.Split (new [] {","}, StringSplitOptions.RemoveEmptyEntries); else { answers = new string [answer.Length]; for (int i = 0; i <answer.Length; i ++) answers [i] = answer [i] .ToString (); } foreach (string number in answers) { int index = Convert.ToInt32 (number) - 1; HtmlElement he = tab.FindElementByAttribute ("img", "class", "rc-image-tile", "regexp", index); if (he.IsVoid) he = tab.FindElementByAttribute ("div", "class", "rc-image-tile-wrapper", "regexp", index); if (! he.IsVoid) { // click on the picture he.Click (); // wait a bit System.Threading.Thread.Sleep (500); } } // wait a little more System.Threading.Thread.Sleep (waitTime * 2); }; // Enter the answer Action InputDynamicAnswer2 = () => { project.SendInfoToLog ("Entering dynamic captcha response", needShowMessages); string [] answers = answer.Split (new [] {","}, StringSplitOptions.RemoveEmptyEntries); foreach (string number in answers) { int index = Convert.ToInt32 (number) - 1; HtmlElement he = tab.FindElementByAttribute ("img", "class", "rc-image-tile", "regexp", index); if (! he.IsVoid) { // click on the picture he.Click (); // wait a bit System.Threading.Thread.Sleep (500); } } // wait a little more System.Threading.Thread.Sleep (waitTime * 2); }; SearchReCaptcha2 (); if (success) return "ok"; if (timeout) throw new Exception ("Element loading timeout"); for (int i = 0; i <tryRecognize; i ++) { project.SendInfoToLog (String.Format ("Attempt #: {0}", i + 1), needShowMessages); InputNotBotText (); SearchTask (); if (timeout) break; // additional verification CheckOK (); if (success) return "ok"; int count = 0; // if captcha is mutable if (dynamicCaptcha) { while (count <dynamicImagesRecognizeAttempts) { if (count> 0) System.Threading.Thread.Sleep (waitTime * 3); // wait for the disappearing images to load SearchImage (); if (timeout) break; Recognize (); if (! String.IsNullOrEmpty (answer) && answer! = "sorry") InputDynamicAnswer (); else { VerifyAnswer (); CheckOK (); if (! success) answerIsEmpty = true; break; } count ++; } } else { if (notOneEnter) { while (notOneEnter &&! dynamicCaptcha && count <dynamicImagesRecognizeAttempts) { SearchImage (); if (timeout) break; Recognize (); if (! String.IsNullOrEmpty (answer) && answer! = "sorry") InputDynamicAnswer2 (); VerifyAnswer (); timeout = false; if (success) break; SearchTask (); if (timeout) break; count ++; } } else { SearchImage (); if (timeout) break; Recognize (); InputAnswer (); } } if (timeout) break; if (! needToCheck) return "ok"; if (answerIsEmpty) { answerIsEmpty = false; UpdateImage (); continue; } if (success) return "ok"; if (i! = (tryRecognize - 1)) UpdateImage (); if (timeout) break; } if (timeout) throw new Exception ("Element loading timeout"); else throw new Exception ("Not recognized. Out of attempts to recognize before the answer was valid");

Note

The snippet can perform any number of attempts to recognize ReCaptcha2. Also, if you use slow proxies, you can increase the waiting time for items to load, the number of load attempts and setting the need to check the correctness of the recognized answer. To do this, you can change the parameters:

// wait time var waitTime = 3000; // number of attempts to recognize var tryRecognize = 10; // number of attempts to select changing pictures var dynamicImagesRecognizeAttempts = 20; // number of attempts to load an element var tryLoadElement = 60; // get full answer bool fullAnswer = false; // get messages about the progress of recognition var needShowMessages = false; // check the correctness of the recognized response var needToCheck = true;

Depending on the IP address from which you perform the above manipulations, ReCaptcha2 may "close its eyes" to the lack of a click on one of the pictures or to a click on the wrong picture. However, with constant errors, ReCaptcha2 may not accept even correct answers, so it is recommended to use good proxies.