Logo of «2Captcha»To home page
Captcha bypass tutorials

Was this helpful?

How to bypass reCAPTCHA on reportcontent.google.com

Jerry Slimane
Jerry Slimane

Technical engineer

reportcontent.google.com is Google's set of content report forms: through them you ask to remove personal data, right-to-be-forgotten content, copyright-infringing material and so on from Search. A reCAPTCHA sits at the end of such a form.

An important detail: this is not plain reCAPTCHA v2, it is reCAPTCHA v2 Enterprise. On the surface it is the same "I'm not a robot" checkbox, but the captcha loads through a separate Google enterprise script. For the service this means one thing: the task type has to be RecaptchaV2EnterpriseTask, not plain reCAPTCHA v2. Everything else is the same — the token is returned into the g-recaptcha-response field and into a callback function.

There is no captcha on the reportcontent.google.com landing page: the address redirects to Google Help. And the form itself is behind an identity check: until you sign in to a Google account or confirm an email address, the form page shows a sign-in screen and a "Form not found" message, and there is no captcha in the page code at all. After the email is confirmed, the form opens right at its own address, and the captcha appears there.

Task Parameters

The task type is RecaptchaV2EnterpriseTaskProxyless. If you need to solve from your own IP, use RecaptchaV2EnterpriseTask with proxy details.

Parameter Type Required Description
type String Yes RecaptchaV2EnterpriseTaskProxyless or RecaptchaV2EnterpriseTask
websiteURL String Yes Address of the page with the captcha, for example https://reportcontent.google.com/forms/rtbf
websiteKey String Yes reCAPTCHA sitekey. It sits in the widget's data-sitekey attribute and in the k parameter of requests to reCAPTCHA
enterprisePayload Object No Extra parameters for the grecaptcha.enterprise.render call, for example an s value. On the report form the widget has a data-action="form-submit" attribute, but you do not need to pass it in the task: the token comes back the same with or without enterprisePayload
isInvisible Boolean No true for the invisible version. The report form uses a checkbox, so false
userAgent String No User-Agent of the browser the page is opened with
cookies String No Cookies in the format key1=val1; key2=val2. Useful for Google services
apiDomain String No Domain to load the captcha from: google.com or recaptcha.net. Default is google.com

For the RecaptchaV2EnterpriseTask type, add proxyType, proxyAddress, proxyPort, proxyLogin and proxyPassword.

How to find parameters

First you have to open the form itself. Go to the page of the report form you need and pass the identity check: sign in to a Google account or enter an email address and confirm it. Until then the form is not shown and there is no captcha on the page. After confirmation the form opens — its address is what goes into websiteURL.

Then press F12 and, on the Elements tab, find the widget element. Note: you have to look through F12, not through "View page source" — the widget is created by a script after the page loads, and it is not in the source. In the DOM it looks like this: first a service captcha-widget element with the settings, and inside it the ordinary captcha container.

html Copy
<captcha-widget data-sitekey="6LeVK0AhAAAAAAM8ccCAZcaNBQbJQ-iZiZQxyG4h"
                data-callback="onRecaptcha"
                data-action="form-submit"
                data-version="v2">
  <div class="g-recaptcha" data-sitekey="6LeVK0AhAAAAAAM8ccCAZcaNBQbJQ-iZiZQxyG4h"
       data-callback="onRecaptcha"></div>
</captcha-widget>

The sitekey is in the data-sitekey attribute — it is the same on both elements. The same key is visible on the Network tab: filter the requests by recaptcha and look at the k parameter of the requests to the captcha anchor.

This is also where you confirm the version is Enterprise. Look at the path of the captcha requests: for Enterprise they go through /recaptcha/enterprise/anchor and /recaptcha/enterprise/bframe, and the script loads as /recaptcha/enterprise.js. If /recaptcha/api.js and /recaptcha/api2/anchor were loaded instead, it would be plain reCAPTCHA v2.

One subtlety. If you open the page source and search for keys across the whole code, you will find three of them, and it is easy to take the wrong one. Besides the checkbox key, there are recaptcha_enterprise_elevated_key (step-up verification) and recaptcha_enterprise_qr_mobile_key (verification via a QR code on a phone) — these are other flows, and you should not send them in the task. The page only ever puts one key into the markup — the one that matches the active verification mode — and that is the key that goes into both captcha iframes (enterprise/anchor and enterprise/bframe). So the reliable way not to get it wrong is simple: take the value from the widget's data-sitekey attribute rather than searching for keys through the source.

And one more thing: reportcontent.google.com brings together several report forms, and the checkbox key may differ from form to form. So read it from the page you are creating the task for, rather than carrying it over from another form.

Code Examples

Python + requests (API v2)

Sending the task and polling for the result with no extra libraries. Put in the sitekey and address you read from your own form.

python Copy
import time

import requests

API_KEY = "YOUR_API_KEY"
WEBSITE_URL = "https://reportcontent.google.com/forms/rtbf"
WEBSITE_KEY = "6LeVK0AhAAAAAAM8ccCAZcaNBQbJQ-iZiZQxyG4h"

task = {
    "type": "RecaptchaV2EnterpriseTaskProxyless",
    "websiteURL": WEBSITE_URL,
    "websiteKey": WEBSITE_KEY,
    "isInvisible": False,
}

created = requests.post(
    "https://api.2captcha.com/createTask",
    json={"clientKey": API_KEY, "task": task},
    timeout=30,
).json()

if created.get("errorId") != 0:
    raise RuntimeError(f"Task was not created: {created}")

task_id = created["taskId"]
print("Task created, id", task_id)

for _ in range(24):
    time.sleep(5)

    result = requests.post(
        "https://api.2captcha.com/getTaskResult",
        json={"clientKey": API_KEY, "taskId": task_id},
        timeout=30,
    ).json()

    if result.get("errorId") != 0:
        raise RuntimeError(f"Error: {result}")

    if result.get("status") == "ready":
        token = result["solution"]["token"]
        print("Token received:", token[:30], "…")
        break
else:
    raise RuntimeError("No solution arrived within the time limit")

A reCAPTCHA token is a long string, usually starting with 03 or 0c. It has to be passed to the page, as shown below.

Python + Playwright

The example opens the form, reads the sitekey from the page, sends the task and passes the token back: it writes it into the g-recaptcha-response field and calls the callback function the form waits for.

Note: the browser has to have already passed the identity check. On a clean Playwright profile the form will not open, there will be no widget on the page, and waiting for the data-sitekey selector will time out. Use a profile with a saved Google session (launch_persistent_context), or first confirm the email in the same browser.

python Copy
import os
import time

import requests
from playwright.sync_api import sync_playwright

API_KEY = os.getenv("APIKEY_2CAPTCHA", "YOUR_API_KEY")
TARGET_URL = "https://reportcontent.google.com/forms/rtbf"


def solve(task):
    created = requests.post(
        "https://api.2captcha.com/createTask",
        json={"clientKey": API_KEY, "task": task},
        timeout=30,
    ).json()

    if created.get("errorId") != 0:
        raise RuntimeError(f"Task was not created: {created}")

    task_id = created["taskId"]
    print("Task created, id", task_id)

    for _ in range(24):
        time.sleep(5)

        result = requests.post(
            "https://api.2captcha.com/getTaskResult",
            json={"clientKey": API_KEY, "taskId": task_id},
            timeout=30,
        ).json()

        if result.get("errorId") != 0:
            raise RuntimeError(f"Error: {result}")

        if result.get("status") == "ready":
            return result["solution"]["token"]

    raise RuntimeError("No solution arrived within the time limit")


with sync_playwright() as p:
    browser = p.chromium.launch(headless=False)
    page = browser.new_page()

    try:
        page.goto(TARGET_URL)
        page.wait_for_selector("[data-sitekey]", timeout=30000)

        website_key = page.get_attribute("[data-sitekey]", "data-sitekey")
        user_agent = page.evaluate("navigator.userAgent")
        print("Sitekey from the page:", website_key)

        token = solve({
            "type": "RecaptchaV2EnterpriseTaskProxyless",
            "websiteURL": TARGET_URL,
            "websiteKey": website_key,
            "userAgent": user_agent,
            "isInvisible": False,
        })
        print("Token received:", token[:30], "…")

        page.evaluate("""(token) => {
            const field = document.querySelector('textarea[name="g-recaptcha-response"]');
            if (field) {
                field.value = token;
            }
            if (typeof window.onRecaptcha === 'function') {
                window.onRecaptcha(token);
            }
        }""", token)

        print("Token passed to the form, the complaint submission comes next")

    except Exception as e:
        print(f"Error: {e}")
    finally:
        browser.close()

The callback function on the reportcontent.google.com form is named onRecaptcha. Its name is visible in the widget's data-callback attribute. If the name is different on your form, change it in the example.

How to use the received token (Passing via callback)

The service returns the solution in the solution.token field. This is the value that normally lands in g-recaptcha-response when a person ticks the checkbox.

On the report form, writing it into the field alone is not enough. The form is not submitted right after the captcha: it waits for the callback function to fire, and only then unlocks the submit. The function name is given in the widget's data-callback attribute. So the token has to be both written into the field and passed to that function:

javascript Copy
document.querySelector('textarea[name="g-recaptcha-response"]').value = "RECEIVED_TOKEN";
onRecaptcha("RECEIVED_TOKEN");

After that fill in the complaint form and submit it the usual way.

Common Errors and Solutions

Error or problem Cause Solution
The service returns a token, but the form does not accept it The plain reCAPTCHA v2 type was used instead of Enterprise The captcha on this site is Enterprise. Use the RecaptchaV2EnterpriseTaskProxyless type
The token is received, but the form does not submit The token was only written into the field, and the callback function was not called Call the function from the widget's data-callback, here it is onRecaptcha
The form with the captcha does not open, the page says "Form not found" The identity check was not passed, the form and captcha are not loaded yet Sign in to a Google account or confirm an email address — after that the form with the captcha opens
There is no widget and no g-recaptcha-response field in the page code You are looking at the page source, but the widget is created by a script Open DevTools (F12), the Elements tab — the widget is visible there
The token takes long to arrive or is rejected The task is solved on the service's IP, while the form checks for an IP match Use RecaptchaV2EnterpriseTask with your own proxy
The captcha behaves as invisible, there is no checkbox The invisible version is enabled on that particular form Pass isInvisible with the value true in the task

The full list of error codes is on the Error codes page, linked below.