Skip to content

Instantly share code, notes, and snippets.

@dk731
Last active September 6, 2024 16:45
Show Gist options
  • Save dk731/44944320d4a7d74f40c7229248d5ca98 to your computer and use it in GitHub Desktop.
Save dk731/44944320d4a7d74f40c7229248d5ca98 to your computer and use it in GitHub Desktop.
reCAPTCHA Analyzer Script

reCAPTCHA Analyzer Script

This JavaScript script analyzes web pages to retrieve detailed information about reCAPTCHA clients present on the page. It's designed to work with various versions of reCAPTCHA, including v2 and v3, as well as invisible and enterprise implementations.

Features:

  • Detects and analyzes multiple reCAPTCHA instances on a single page
  • Identifies reCAPTCHA version (v2, v2 invisible, v3)
  • Extracts key information such as sitekey, action, widget ID, and container ID
  • Detects enterprise reCAPTCHA implementations
  • Identifies binded elements for invisible reCAPTCHA

Usage:

  1. Add this script to your web page or run it in the browser console.
  2. Call the getReCaptchaSiteKeys() function to retrieve an array of reCAPTCHA client data objects.

Output:

The script returns an array of objects, each containing detailed information about a reCAPTCHA instance, including:

  • captchaType: Always "recaptcha"
  • widgetId: The reCAPTCHA widget ID
  • version: The reCAPTCHA version ("v2", "v2_invisible", or "v3")
  • sitekey: The reCAPTCHA sitekey
  • action: The action parameter (for v3)
  • s: The 's' parameter (if present)
  • callback: The callback function (if defined)
  • enterprise: Boolean indicating if it's an enterprise implementation
  • containerId: The ID of the container element
  • bindedButtonId: The ID of the binded button (for invisible reCAPTCHA)

Note:

This implementation is based on the 2captcha Chrome extension's approach to reCAPTCHA detection and analysis. It's designed to work with the current structure of reCAPTCHA as of the script's creation date. Future updates to reCAPTCHA may require adjustments to this script.

Disclaimer:

This script is for educational and debugging purposes only. Ensure you comply with Google's terms of service and respect the intended use of reCAPTCHA when using this script.

function verifyClientVersion(client) {
for (const clientObjectFieldKey in client) {
const clientObjectField = client[clientObjectFieldKey];
if (typeof clientObjectField !== "object") continue;
for (const objectFieldKey in clientObjectField) {
const objectField = clientObjectField[objectFieldKey];
if (typeof objectField !== "string") continue;
if (objectField == "fullscreen") return "v2_invisible";
}
}
return "v3";
}
function getClientVersion(client) {
for (const clientObjectFieldKey in client) {
const clientObjectField = client[clientObjectFieldKey];
if (typeof clientObjectField !== "object") continue;
for (const objectFieldKey in clientObjectField) {
const objectField = clientObjectField[objectFieldKey];
if (
objectField &&
objectField.classList &&
objectField.classList.contains("grecaptcha-badge")
)
return verifyClientVersion(client);
}
}
return "v2";
}
function getClientContainerId(client) {
let containerId = null;
let forLoopHelper;
for (const clientObjectFieldKey in client) {
const clientObjectField = client[clientObjectFieldKey];
if (!clientObjectField || !clientObjectField.nodeType) continue;
if (clientObjectField.id) {
containerId = clientObjectField.id;
continue;
}
if (clientObjectField.dataset.sitekey) {
clientObjectField.id = "recaptcha-container-" + Date.now();
containerId = clientObjectField.id;
continue;
}
if (!forLoopHelper) {
forLoopHelper = clientObjectField;
continue;
}
if (clientObjectField.isSameNode(forLoopHelper)) {
clientObjectField.id = "recaptcha-container-" + Date.now();
containerId = clientObjectField.id;
break;
}
}
return containerId;
}
function getClientData(client) {
const result = {
captchaType: "recaptcha",
widgetId: client.id,
version: getClientVersion(client),
sitekey: null,
action: null,
s: null,
callback: null,
enterprise: !!(grecaptcha && grecaptcha.enterprise),
containerId: getClientContainerId(client),
bindedButtonId: null,
};
for (const clientObjectFieldKey in client) {
const clientObjectField = client[clientObjectFieldKey];
if (typeof clientObjectField !== "object") continue;
for (const objectFieldKey in clientObjectField) {
const objectField = clientObjectField[objectFieldKey];
if (objectField === null) continue;
if (typeof objectField !== "object") continue;
if (objectField.sitekey === undefined) continue;
if (objectField.action === undefined) continue;
for (const objectObjectFieldKey in objectField) {
const objectObjectField = objectField[objectObjectFieldKey];
if (objectObjectFieldKey === "sitekey")
result.sitekey = objectObjectField;
if (objectObjectFieldKey === "action")
result.action = objectObjectField;
if (objectObjectFieldKey === "s") result.s = objectObjectField;
if (objectObjectFieldKey === "callback")
result.callback = objectObjectField;
if (objectObjectFieldKey !== "bind") continue;
if (!objectObjectField) {
const queryResult = document.querySelector(
'form[method="post"] button'
);
if (!queryResult) continue;
if (!queryResult.id)
queryResult.id = "recaptchaBindedElement" + client.id;
result.bindedButtonId = queryResult.id;
continue;
}
if (typeof objectObjectField === "string") {
result.bindedButtonId = objectObjectField;
continue;
}
if (objectObjectField.id === undefined)
objectObjectField.id = "recaptchaBindedElement" + client.id;
result.bindedButtonId = objectObjectField.id;
}
}
}
return result;
}
function getReCaptchaSiteKeys() {
// Verify that reCAPTCHA loaded
if ("___grecaptcha_cfg" in window == false)
throw new Error("reCAPTCHA not found");
const recaptchaBase = window["___grecaptcha_cfg"];
// Verify that reCAPTCHA has clients
if ("clients" in recaptchaBase == false)
throw new Error("reCAPTCHA does not have any clients");
const clients = Object.values(recaptchaBase.clients);
// Obtain reCAPTCHA clients data
const clientsData = clients.map(getClientData);
return clientsData;
}
getReCaptchaSiteKeys();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment