How to bypass captcha with 2captcha and Selenium using Python
Tags: python, automation, selenium, tooling
Published: 2022-01-28 20:02:54


When you go to any modern website, they ask you to solve a challenge before submitting a form, such as identifying all firehoses, a slider to solve a puzzle or typing out some texts. This is called CAPTCHA(short for Completely Automated Public Turing tests to tell Computers and Humans Apart). They usually add a layer of security to prevent bots and malicious accounts from accessing a website's resources.

The squiggly lines and words of the past are less common nowadays and have been replaced by Google's version 2 of CAPTCHA, known as reCAPTCHA or key puzzles from keyCAPTCHA. However, bots are becoming more advanced and can bypass almost any captcha. In this tutorial, we'll make use of the captcha bypass software, [2captcha](https://2captcha.com/?from=12437369).

![cover image tngeene captcha](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0cxjwqgogblodoijg1fv.jpeg)

## Why are we doing this?

Okay, I know some of you might be wondering, why would we need to bypass captcha? and most importantly; is this even legal? No, it is not illegal to bypass 2captcha.
This article is intended for;

1. Curious about how you can bypass captcha
2. Building web scrapers that would need to bypass a captcha

> *Disclosure: I only recommend products I would use myself and all opinions expressed here are my own. This post may contain affiliate links that at no additional cost to you, I may earn a small commission.

## What is 2captcha?

[2Captcha.com](https://2captcha.com/?from=12437369) is a captcha solving service that automates the captcha solving process. They have an API and several packages that wrap around different programming languages. All you need is to register on their website, get an API key and make requests to their API.

> Note: They charge a small rate for every captcha solved, however, the fee is quite minimal at $0.05 to $ 1.00 for every 1000 captchas solved.

## Signup Process and supported languages

![https://res.cloudinary.com/practicaldev/image/fetch/s--JgfXuOWJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vdobzdwc4thex7mwocho.png](https://res.cloudinary.com/practicaldev/image/fetch/s--JgfXuOWJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vdobzdwc4thex7mwocho.png)

![https://res.cloudinary.com/practicaldev/image/fetch/s--OEXnGqQA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/szwihqwt8xxrtpnz64fn.png](https://res.cloudinary.com/practicaldev/image/fetch/s--OEXnGqQA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/szwihqwt8xxrtpnz64fn.png)

Supported captchas the software solves include;

![https://res.cloudinary.com/practicaldev/image/fetch/s--px3AuiEX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/11ybxotkegschanhgq9i.png](https://res.cloudinary.com/practicaldev/image/fetch/s--px3AuiEX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/11ybxotkegschanhgq9i.png)

## Requirements and Setup

- For this tutorial, we'll utilize the [2captcha API](https://2captcha.com/2captcha-api). You'll need to have a developer account to use. You can head over to [this link and sign up](https://2captcha.com/?from=12437369)
- The source code we'll be using can be found [here](https://github.com/tngeene/2-captcha-solver-python). Setup instructions have been linked in the project README file. Feel free to clone the repository and tinker around.

Let's dive in.

## Automating with Selenium

Before we get carried away by CAPTCHA, we need to understand the process our program will follow. I'm going to use [selenium](https://www.selenium.dev/documentation/) and python. Selenium is a browser automation service that provides extensions that allow programs to emulate browser interactions. It supports an array of browsers; from chrome, firefox, safari, and so forth, by integrating with their web drivers.

## Captcha Solving Pseudocode

Now that we have our account setup, we'll do the actual capture bypassing, which brings us to the next part.

For this tutorial, i'll be bypassing the capture on [this sample form](https://phppot.com/demo/php-contact-form-with-google-recaptcha/)

![https://res.cloudinary.com/practicaldev/image/fetch/s--F4Bz13C_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qkgdk3qldwr178k6rtb0.png](https://res.cloudinary.com/practicaldev/image/fetch/s--F4Bz13C_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qkgdk3qldwr178k6rtb0.png)

In order to achieve our objective, we'll need our program to follow these steps.

1. Launch a browser tab.
2. Fill in the required fields in the form.
3. Solve the captcha.
4. Send the contact message with the solved captcha.
5. Close the browser window.

All this will be achieved automatically!! How cool is that?

For this tutorial, I'll be using chrome driver since chrome is my default browser. To setup selenium, chromedriver, and all project dependencies run the following command

    pip install -r requirements.txt

> Always ensure you've activated a virtual environment to prevent the packages from being installed globally in your machine.


There are several packages that you'll see in the `main.py` file. I'll go over them in brief

1. [2captcha-python](https://pypi.org/project/2captcha-python/) - the 2captcha python SDK. It does most of the heavy lifting of interacting with the 2captcha API
2. [Selenium with python](https://selenium-python.readthedocs.io/) - contains selenium python bindings.
3. [webdriver-manager](https://pypi.org/project/webdriver-manager/) - manages our chromedriver installation rather than manually setting path configurations. It's main idea is to simplify management of binary drivers for different browsers.
4. [python-decouple](https://pypi.org/project/python-decouple/) - enables storing of variables in `.env` or `.ini` files. This comes in handy when we have sensitive information we might not want exposed to the unauthorized parties, such as API keys.

## Project Code

Open an `main.py` file at the root of your project directory and paste the following code. We'll go over the code in-depth in the next section.

```python
from random import randint
from time import sleep

from decouple import config
from selenium import webdriver
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from twocaptcha import TwoCaptcha
from twocaptcha.api import ApiException, NetworkException
from twocaptcha.solver import ValidationException
from webdriver_manager.chrome import ChromeDriverManager

two_captcha_api_key = config('CAPTCHA_API_KEY')
website_url = config('WEBSITE_URL')
site_key = config('GOOGLE_CAPTCHA_KEY')

driver_options = webdriver.ChromeOptions()
driver_options.add_argument('--start_maximized')

# * use 2captcha python client, read docs in https://pypi.org/project/2captcha-python/
solver_config = {
    'apiKey': two_captcha_api_key,
    'defaultTimeout': 120,
    'recaptchaTimeout': 600,
    'pollingInterval': 10,
}

solver = TwoCaptcha(**solver_config)


class SolveCaptcha:

    def launch_selenium(self, response):
        if response:
            print('Captcha Solved! Launching Browser...')
            # initiate chrome webdriver
            # * check webdrivers for firefox and others in https://selenium-python.readthedocs.io/installation.html#drivers
            driver = webdriver.Chrome(service=Service(
                ChromeDriverManager().install()),
                                      options=driver_options)

            # open browser window and navigate to Url
            driver.get(website_url)

            driver.find_element(By.ID, 'name').send_keys('Ted')
            driver.find_element(By.ID, 'phone').send_keys('000000000')
            driver.find_element(By.ID,
                                'email').send_keys('tngeene@captcha.com')
            driver.find_element(By.ID,
                                'comment-content').send_keys('test comment')

            google_captcha_response_input = driver.find_element(
                By.ID, 'g-recaptcha-response')

            # make input visible
            driver.execute_script(
                "arguments[0].setAttribute('style','type: text; visibility:visible;');",
                google_captcha_response_input)
            # input the code received from 2captcha API
            google_captcha_response_input.send_keys(response.get('code'))
            # hide the captch input
            driver.execute_script(
                "arguments[0].setAttribute('style', 'display:none;');",
                google_captcha_response_input)
            # send text
            driver.find_element(By.ID, 'send-message').click()

            sleep(randint(5, 10))

            driver.quit()
            balance = solver.balance()
            # show 2captcha Balance.
            print(f'Your 2captcha balance is ${round(balance, 2)}')
        else:
            print('No response.')

    def initiate_captcha_solver(self):
        try:
            print('Solving captcha...')
            result = solver.recaptcha(sitekey=site_key, url=website_url)
            # launch browser window upon successful
            # completion of captcha solving.
            self.launch_selenium(result)
        except ValidationException as e:
            # invalid parameters passed
            print(e)
            return e
        except NetworkException as e:
            # network error occurred
            print(e)
            return e
        except ApiException as e:
            # api respond with error
            print(e)
            return e
        except TimeoutException as e:
            # captcha is not solved so far
            print(e)
            return e


SolveCaptcha().initiate_captcha_solver()

```

### Importing Packages

```python
from random import randint
from time import sleep

from decouple import config
from selenium import webdriver
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from twocaptcha import TwoCaptcha
from twocaptcha.api import ApiException, NetworkException
from twocaptcha.solver import ValidationException
from webdriver_manager.chrome import ChromeDriverManager
```

These lines are essentially referencing the packages we'll be using. We're telling the program that we'll require to use; decouple, the twocaptcha, and selenium packages.
I've also imported the `randint` and `sleep` modules that come as part of the standard python package.
We'll be using these two as well.
### Interacting with imported packages

```python
two_captcha_api_key = config('CAPTCHA_API_KEY')
website_url = config('WEBSITE_URL')
site_key = config('GOOGLE_CAPTCHA_KEY')
```

The first package we need to use is the `python-decouple` package. Here, we define the environment variables we'll be using for the program. You can obtain the 2captcha api key from the website's dashboard.

### Environment variable.

{% wikipedia [https://en.wikipedia.org/wiki/Environment_variable] (https://en.wikipedia.org/wiki/Environment_variable) %}

It's advisable to use environment variables to store sensitive information that we wouldn't want getting into unauthorized hands, for example, our 2Captcha API key. Create a `env` file at the root of your project folder. Modify it to this.

```
 CAPTCHA_API_KEY=<api_key_from_2_captcha.com>
 WEBSITE_URL=<website_we'll_be_accessing_captcha>
 GOOGLE_CAPTCHA_KEY=<google_captcha_site_key>

```

Paste the api key value from [2captcha](https://2captcha.com/?from=12437369) dashboard on the `CAPTCHA_API_KEY` field.

`GOOGLE_CAPTCHA_KEY` is a special identifier found in all web forms having captcha, we can retrieve it by also opening dev tools, and searching the `data-sitekey` keyword.

![https://res.cloudinary.com/practicaldev/image/fetch/s--EWcZ2FeR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lp1rxds2suvwbtgrktdn.png](https://res.cloudinary.com/practicaldev/image/fetch/s--EWcZ2FeR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lp1rxds2suvwbtgrktdn.png)

Retrieve the value and paste it in the `.env`, GOOGLE_CAPTCHA_KEY value. `python-2captcha` sends this key under the hood to the 2captcha API, which then returns an API response of the solved captcha. We'll be seeing this further ahead.

The `WEBSITE_URL` is the webpage of our captcha form. Fill it in the `.env` file as well.



```python
solver_config = {
    'apiKey': two_captcha_api_key,
    'defaultTimeout': 120,
    'recaptchaTimeout': 600,
    'pollingInterval': 10,
}

solver = TwoCaptcha(**solver_config)
```

Next we initialize the twocaptcha instance using the TwoCaptcha constructor. The constructor takes in a few arguments which we have defined inside the `solver_config` dictionary.
We then pass the configs into the constructor by desctructuring the dictionary.

These arguments are;
- `apikey`: The API key we obtain from 2Captcha.
- `defaultTimeout`: Time (seconds) to wait before giving up on waiting for a captcha solution.
- `recaptchaTimeout`: Polling timeout for ReCaptcha in seconds. Defines how long the module tries to get the answer from `res.php` API endpoint
- `pollingInterval`: Time (seconds) between polls to 2captcha server. 2Captcha documentation suggests this time to be at least 5 seconds, or you might get blocked.

## Retrieving Dom elements

As you can tell from the form, we will need selenium to access the DOM form elements as it automatically fills the inputs. These are; the name, email, phone, comment, and finally there's a hidden google captcha field that takes the solved captcha as an input.

For the visible form fields, all we need to do is open up the dev tools and retrieve the individual ids of the form fields.

This section does just that.

```python
   def launch_selenium(self, response):
        if response:
            print('Captcha Solved! Launching Browser...')
            # initiate chrome webdriver
            # * check webdrivers for firefox and others in https://selenium-python.readthedocs.io/installation.html#drivers
            driver = webdriver.Chrome(service=Service(
                ChromeDriverManager().install()),
                                      options=driver_options)

            # open browser window and navigate to Url
            driver.get(website_url)

            driver.find_element(By.ID, 'name').send_keys('Ted')
            driver.find_element(By.ID, 'phone').send_keys('000000000')
            driver.find_element(By.ID,
                                'email').send_keys('tngeene@captcha.com')
            driver.find_element(By.ID,
                                'comment-content').send_keys('test comment')
```

What we're telling selenium is, to launch chrome browser, and visit the specified url. Once it does so, find the DOM elements that matches the provided ids. Since these are form inputs, auto-populate those field with the data inside the `send_keys` function.

All 2captchas have a hidden text-area that autofills with the solved captcha code once you click the `i'm not a robot` check. Usually, this has the id set as `g-recaptcha-response`

![https://res.cloudinary.com/practicaldev/image/fetch/s--DRV3vb-q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6v3jdf99wtv974jfhffy.png](https://res.cloudinary.com/practicaldev/image/fetch/s--DRV3vb-q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6v3jdf99wtv974jfhffy.png)

Since selenium simulates browser human inputs, it'll be required to make the field visible. We achieve this with this code snippet

```python
  google_captcha_response_input = driver.find_element(
                By.ID, 'g-recaptcha-response')

            # make input visible
            driver.execute_script(
                "arguments[0].setAttribute('style','type: text; visibility:visible;');",
                google_captcha_response_input)
            # input the code received from 2captcha API
            google_captcha_response_input.send_keys(response.get('code'))
            # hide the captcha input
            driver.execute_script(
                "arguments[0].setAttribute('style', 'display:none;');",
                google_captcha_response_input)
            # send text
            driver.find_element(By.ID, 'send-message').click()

```

This section typically makes the field visible, auto-populates the field with the solved captcha, hides the field again, and finally, the button click is simulated to send the comment with the solved captcha.

Finally, we'll close the browser tab a few seconds after the captcha has been solved. We're using the `randint` function to close the browser anytime between 5 and 10 seconds

```python
            sleep(randint(5, 10))

            driver.quit()
            balance = solver.balance()
            # show 2captcha Balance.
            print(f'Your 2captcha balance is ${round(balance, 2)}')

```

The last section queries your 2captcha balance and returns the account balance of your account so as to give you a small report on the cash balance. As mentioned before, each captcha solved attracts a small fee.

All the fore-mentioned functionality resides in the `launch_selenium()` function. We need to tie it all together with the 2captcha service.

From the `main.py` file, you can see we have a `initiate_captcha_solver()` function.

```python

    def initiate_captcha_solver(self):
        try:
            print('Solving captcha...')
            result = solver.recaptcha(sitekey=site_key, url=website_url)
            # launch browser window upon successful
            # completion of captcha solving.
            self.launch_selenium(result)
        except ValidationException as e:
            # invalid parameters passed
            print(e)
            return e
        except NetworkException as e:
            # network error occurred
            print(e)
            return e
        except ApiException as e:
            # api respond with error
            print(e)
            return e
        except TimeoutException as e:
            # captcha is not solved so far
            print(e)
            return e

```

We are calling the `python_two_captcha` sdk we'd initialized before, by
   result = solver.recaptcha(sitekey=site_key, 
          url=website_url)

We're also catching some exceptions that may be returned by the 2Captcha API.

This result will be used as an argument in the `launch_selenium` function as we'll need the output of the response as an input to our form.

Selenium will only be launched upon a successful captcha solve, which usually takes a few seconds. For Recaptcha version 2, the ETA is usually anytime from 15 seconds to 45seconds. Recaptcha version 3 takes a shorter time.If a request timed out, we log the api response.

## Demo
Okay, now your application is set up! It may feel like a lot 😅 but we did a lot of installation. We will now test our application.

![tngeene python 2captcha demo gif](https://i.imgur.com/Ma9Llnc.gif[/img])

### Conclusion

> It’s always a dilemma, should websites have a better experience and have simple to bypass the CAPTCHA or should websites aggressively protect themselves from bots and have a bad user experience. The war between websites and bots is never over. Whatever verification method websites pull out, it’s just a matter of time when someone figures out how to bypass it. ~ Filip Vitas

In this guide, we were introduced to 2captcha API, selenium, and a few concepts in 2captcha using python. By the end of it, I hope you can apply the knowledge gained to build your own captcha bypass service. I mean, if bots can do it, then so should we! A few next steps would be to add a User interface to input our values. You can also look into using the 2captcha API using your preferred programming language and other tools such as [puppeteer](https://pptr.dev/), i've also previously written an article on the same using javascript. You can find this by visiting this [link](https://dev.to/tngeene/how-to-bypass-captcha-with-2captcha-api-and-selenium-4p5m)

Finally, if you liked the content and would like to use 2captcha, [sign up with this link.](https://2captcha.com/?from=12437369)

If you have any questions, you can always leave a comment below, or reach out on these channels;

1. [personal website](https://tngeene.com/)
2. [Twitter](https://twitter.com/Ngeene_kihiu)

Source code of demo project can be accessed [here.](https://github.com/tngeene/2-captcha-solver-python)

Use 2captcha responsibly.

## Sponsors
- [Scraper API](https://www.scraperapi.com?via=teddy44) is a startup specializing in strategies that'll ease the worry of your IP address from being blocked while web scraping. They utilize IP rotation so you can avoid detection. Boasting over 20 million IP addresses and unlimited bandwidth. Using Scraper API and a tool like [2captcha](https://2captcha.com?from=12437369) will give you an edge over other developers. The two can be used together to automate processes. Sign up on Scraper API and use [this link] (https://www.scraperapi.com?via=teddy44) to get a 10% discount on your first purchase.

- Do you need a place to host your website or app, [Digital ocean](DigitalOcean – The developer cloudwww.digitalocean.com)
 is just the solution you need, sign up on digital ocean using this [link](https://m.do.co/c/eaa803fe4d99) and experience the best cloud service provider.

- The journey to becoming a developer can be long and tormentous, luckily [Pluralsight](http://referral.pluralsight.com/mQh0Nxp) makes it easier to learn. They offer a wide range of courses, with top quality trainers, whom I can personally vouch for. Sign up using [this link](http://referral.pluralsight.com/mQh0Nxp) and get a 50% discount on your first course.