How to Handle reCAPTCHA in Automation

Updated June 2026
Handling reCAPTCHA in browser automation requires detecting the challenge, extracting the site key and page parameters, sending them to a solving service, and injecting the returned token into the page before submitting the form. This guide walks through the complete process for both reCAPTCHA v2 and v3, with practical guidance for Playwright, Puppeteer, and Selenium workflows.

Google reCAPTCHA is the most widely deployed CAPTCHA system on the web, protecting millions of websites. Whether you encounter the v2 checkbox, the invisible v2 variant, or the fully background v3 scoring system, the handling process follows the same general pattern: detect, extract, solve, inject, and submit. The specific implementation details vary by reCAPTCHA version and automation framework, but the core workflow remains consistent.

Step 1: Identify the reCAPTCHA Version

Before writing any solving logic, you need to know exactly which reCAPTCHA version the target site uses. This determines the parameters you need to extract and the solving method your service will use.

reCAPTCHA v2 (checkbox). Look for an iframe with a source URL containing google.com/recaptcha. The page will also load the script api.js or recaptcha__en.js from google.com. The visible indicator is the "I'm not a robot" checkbox widget rendered inside a div with the class g-recaptcha.

reCAPTCHA v2 (invisible). The invisible variant loads the same scripts but does not render a visible checkbox. Instead, the reCAPTCHA triggers automatically when the user clicks a button or submits a form. Look for a div with class g-recaptcha that has the attribute data-size="invisible" or a programmatic grecaptcha.execute() call in the page's JavaScript.

reCAPTCHA v3. Version 3 loads the script api.js with a render parameter containing the site key (for example, api.js?render=SITE_KEY). There is no visible widget or checkbox. The script runs in the background and generates a token when grecaptcha.execute() is called, typically tied to a specific action name like "login" or "submit".

The site key is the critical parameter. For v2, find it in the data-sitekey attribute of the g-recaptcha div. For v3, extract it from the render parameter in the script URL or from the grecaptcha.execute() call in the page source.

Step 2: Set Up a Solving Service

Register with a CAPTCHA solving service that supports reCAPTCHA. All major services (2Captcha, Anti-Captcha, CapSolver, CapMonster) support both v2 and v3. Create an account, add funds to your balance, and note your API key.

Install the service's client library for your programming language. For Python, this typically means running a pip install command for the service's package. For JavaScript, use npm. If you prefer to call the API directly, the REST endpoints are straightforward and well-documented by every major service.

Before integrating into your full automation script, test the service with a simple standalone script that submits a known reCAPTCHA challenge and verifies that you receive a valid token. This isolates any account, billing, or connectivity issues from your automation logic.

Step 3: Detect the CAPTCHA in Your Script

Your automation script needs reliable detection logic that identifies when a reCAPTCHA challenge has appeared. There are several approaches, and the best choice depends on the target site's behavior.

DOM element detection. Check for the presence of the reCAPTCHA iframe or the g-recaptcha div after each page navigation. In Playwright, use page.locator() to search for these elements. In Puppeteer, use page.$() or page.waitForSelector(). In Selenium, use driver.find_element() with appropriate selectors.

URL-based detection. Some sites redirect to a CAPTCHA page when they detect suspicious activity. Monitor the current URL after each navigation and check whether it contains patterns like captcha, challenge, or verify.

Response content detection. For non-browser HTTP scraping, check the response body for reCAPTCHA script includes or the g-recaptcha div. If the expected content is missing and reCAPTCHA elements are present instead, a challenge has been triggered.

Build your detection as a reusable function that returns the CAPTCHA type and site key when a challenge is found, or returns null when the page loads normally. This keeps your main scraping loop clean and separates CAPTCHA handling from data extraction logic.

Step 4: Extract Challenge Parameters

Once you have detected a reCAPTCHA, extract the parameters that the solving service needs.

For reCAPTCHA v2 (both checkbox and invisible): You need the site key (from the data-sitekey attribute) and the current page URL. Some sites also include a data-s attribute on the g-recaptcha div, which contains an additional token that must be passed to the solving service for the solution to be valid.

For reCAPTCHA v3: You need the site key (from the script render parameter or the execute call), the page URL, and the action name. The action name is a string like "login", "submit", "homepage", or "register" that the site developer chose when implementing reCAPTCHA v3. You can find it in the grecaptcha.execute() calls in the page's JavaScript. If you cannot determine the action name, many solving services accept a default value, though matching the exact action name improves the likelihood of a valid token.

Additionally, note the minimum score threshold for v3 if you can determine it. Some solving services allow you to request a token with a specific minimum score, increasing the probability that the target site will accept it.

Step 5: Submit to the Solving Service

Send the extracted parameters to your solving service's API. The exact API call varies by service, but the required fields are consistent: CAPTCHA type identifier, site key, page URL, and any additional parameters (action name for v3, data-s for v2 if present).

Using a client library, the call is typically a single function. For example, with a Python 2Captcha library you would call solver.recaptcha(sitekey=site_key, url=page_url) for v2, or solver.recaptcha(sitekey=site_key, url=page_url, version="v3", action=action_name) for v3. The function handles the API call and returns a task ID.

If calling the API directly, send a POST request to the service's task creation endpoint with the parameters as JSON, then use the returned task ID to poll for results.

Step 6: Poll for the Solution

After submitting the challenge, poll the solving service at regular intervals (typically every 3 to 5 seconds) until the solution is ready. Most client libraries handle polling automatically, blocking until the result is available or a timeout is reached.

Typical solve times are 10 to 45 seconds for reCAPTCHA v2 (human solving) or 5 to 15 seconds (AI solving), and 5 to 20 seconds for reCAPTCHA v3. Set a reasonable timeout of 60 to 90 seconds. If the solve takes longer than that, the service may be experiencing capacity issues, and you should consider falling back to an alternative service or retrying.

The solution returned for reCAPTCHA is always a token string, typically 500 to 600 characters long. This is the value that would normally populate the g-recaptcha-response hidden field when a human user completes the challenge.

Step 7: Inject the Token and Submit

With the token in hand, inject it into the page. In browser automation, you need to set the value of the g-recaptcha-response textarea element. This element is often hidden on the page, but it exists in the DOM and its value is what gets sent to the server when the form is submitted.

In Playwright, use page.evaluate() to set the textarea value via JavaScript. In Puppeteer, the approach is identical. In Selenium, use driver.execute_script(). The JavaScript is straightforward: find the textarea element by its ID or name and set its value property to the token string.

For reCAPTCHA v2, you may also need to trigger the callback function that reCAPTCHA registers, which notifies the host page that verification is complete. This callback is typically stored in the ___grecaptcha_cfg object or can be found by inspecting the g-recaptcha div's data-callback attribute. Calling this function with the token as an argument completes the verification flow from the page's perspective.

After injecting the token and triggering the callback, submit the form normally. The server will validate the token with Google's API on the backend. If the token is valid and not expired, the submission will succeed.

Step 8: Handle Errors and Retries

Robust reCAPTCHA handling requires error handling at every stage of the process.

Token expiration. reCAPTCHA tokens expire within approximately 2 minutes of being generated. If your script takes too long between receiving the token and submitting the form, the server will reject the token. Minimize the time between receiving the solution and injecting it. If submission fails with an expired token error, request a new solution immediately.

Invalid tokens. Occasionally, a solving service returns a token that the target site rejects. This can happen if the site key changed, the page URL was incorrect, or the action name (for v3) did not match. Report the invalid solution to your service (most offer a complaint API that refunds the charge) and retry with verified parameters.

Service errors. Solving services can return errors for insufficient balance, rate limiting, capacity overload, or unsupported CAPTCHA parameters. Handle each error type appropriately: top up balance, add delays between requests, switch to a backup service, or verify your parameters.

Retry strategy. Implement a retry loop with a maximum of 2 to 3 attempts per CAPTCHA encounter. If a solve fails, wait a few seconds before retrying. If all attempts fail, log the failure, skip the page, and continue with the rest of your scraping job rather than getting stuck on a single CAPTCHA.

Tips for Production Workflows

In production automation, several practices improve the reliability and efficiency of reCAPTCHA handling. First, always verify that the page actually needs a CAPTCHA before requesting a solve. Unnecessary API calls waste money and slow down your pipeline. Second, use asynchronous solving whenever possible: submit the CAPTCHA to the service, continue processing other tasks, and come back for the result when needed. This prevents your script from sitting idle during the solve period.

Third, combine reCAPTCHA solving with prevention measures. Using residential proxies, realistic browser fingerprints, and reasonable request rates will reduce your CAPTCHA encounter rate significantly, lowering both the cost and latency impact of solving. The fewer CAPTCHAs you trigger, the faster and cheaper your overall operation runs.

Finally, monitor your solving success rate and cost per page over time. If the success rate drops or costs spike, the target site may have updated its reCAPTCHA configuration, changed the site key, or added additional security layers that your current approach does not handle. Regular monitoring catches these changes early before they affect your data collection at scale.

Key Takeaway

Handling reCAPTCHA in automation follows a consistent pattern: detect the challenge, extract the site key and parameters, send them to a solving service, inject the returned token, and submit the form. Build this as a reusable module with proper error handling and retry logic, and combine it with prevention measures to minimize the number of CAPTCHAs your scripts encounter.