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

Was this helpful?

How to bypass captcha using PHP

Gregory Fisher
Gregory Fisher

Technical engineer

Introduction

When developing web scrapers, automating tests, or building bots in PHP, developers often face the challenge of bypassing CAPTCHAs. Writing custom cURL requests, implementing polling loops, and handling timeouts complicate the code and distract from core business logic.

In this guide, we will explore how to use the official PHP library to integrate with the 2Captcha API. We'll walk through the installation process, client initialization, solving Capy Puzzle and other popular CAPTCHA types, and provide a complete list of all protection types supported by the service.

Installation and Setup

The library is distributed via Composer and integrates seamlessly into any PHP project, from simple scripts to large-scale applications built on frameworks like Laravel or Symfony.

You can install the package using the following terminal command:

bash Copy
composer require 2captcha/2captcha

Once installed, include the Composer autoloader in your script and import the main class:

php Copy
require __DIR__ . '/vendor/autoload.php';
use TwoCaptcha\TwoCaptcha;

Client Initialization

To get started, create an instance of the TwoCaptcha class and pass your API key to it. For security reasons, it is highly recommended to store the key in environment variables or configuration files rather than hardcoding it in your source code.

php Copy
$apiKey = getenv('CAPTCHA_API_KEY');
$solver = new TwoCaptcha($apiKey);

Solving Capy Puzzle

Capy Puzzle is an interactive CAPTCHA where the user needs to assemble a puzzle or move an element to a specific position. To solve it via the API, you need to pass the websiteKey (the unique CAPTCHA key) and the page URL.

php Copy
try {
    $result = $solver->capy([
        'sitekey' => 'PUZLE_abcdef1234567890',
        'url'     => 'https://example.com/login'
    ]);
    echo "Answer: " . $result['answer'];
    echo "Challenge Key: " . $result['challenge_key'];
} catch (\Exception $e) {
    echo "Error: " . $e->getMessage();
}

The response contains two values: answer and challenge_key. Both need to be submitted to the target website, typically in hidden form fields.

reCAPTCHA v2 and Invisible

To bypass reCAPTCHA, you need to pass the sitekey and page URL. If you are using the invisible version, add the invisible parameter with a value of 1.

php Copy
try {
    $result = $solver->recaptcha([
        'sitekey' => '6LeTxvsqAAAAAK...',
        'url'     => 'https://example.com/login',
        'invisible' => 1
    ]);
    echo "g-recaptcha-response token: " . $result->code;
} catch (\Exception $e) {
    echo "Error: " . $e->getMessage();
}

Cloudflare Turnstile

Cloudflare's modern protection requires passing the sitekey and page URL. To increase the chances of a successful solve, it is recommended to pass a valid User-Agent.

php Copy
try {
    $result = $solver->turnstile([
        'sitekey' => '0x4AAAAAA...',
        'url'     => 'https://example.com/protected',
        'userAgent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/120.0.0.0 Safari/537.36'
    ]);
    echo "cf-turnstile-response token: " . $result->code;
} catch (\Exception $e) {
    echo "Error: " . $e->getMessage();
}

Text or Image CAPTCHA (Normal)

To solve standard image CAPTCHAs, use the normal method. The image can be passed as a path to a local file.

php Copy
try {
    $result = $solver->normal('/path/to/captcha.jpg');
    echo "Recognized text: " . $result->code;
} catch (\Exception $e) {
    echo "Error: " . $e->getMessage();
}

Complete List of Supported CAPTCHA Types

Currently, the 2Captcha service supports the following main CAPTCHA types: Normal (ImageToTextTask), reCAPTCHA v2, reCAPTCHA v3, Cloudflare Turnstile, GeeTest v3 and v4, FunCaptcha (Arkose Labs), KeyCaptcha, Capy Puzzle, Lemin, Yidun (NECaptcha), Amazon WAF, MTCaptcha, CutCaptcha, Tencent, DataDome, CyberSiARA, Coordinates, Rotate, and Canvas.

The API provides a unique method and a specific set of configuration options for each of these types.

Advanced Settings

Working via Proxy

If the target website strictly checks IP addresses and binds the CAPTCHA to a specific proxy, you can pass the proxy parameters directly into the method's configuration array.

php Copy
try {
    $result = $solver->recaptcha([
        'sitekey'     => '6LeTxvsqAAAAAK...',
        'url'         => 'https://example.com/login',
        'proxy'       => 'login:password@198.51.100.10:8080',
        'proxytype'   => 'HTTP'
    ]);
    echo "Token: " . $result->code;
} catch (\Exception $e) {
    echo "Error: " . $e->getMessage();
}

Timeout Configuration

By default, the library waits for a CAPTCHA solution for 120 seconds, and the status polling interval is 10 seconds. These parameters can be overridden via the object's properties.

php Copy
$solver->defaultTimeout = 300;  // Maximum wait time in seconds
$solver->pollingInterval = 15;  // Status polling interval in seconds

Error Handling

When errors occur, the library throws standard PHP exceptions (\Exception), with messages containing the error code and description from the API. This makes it easy to catch and log issues.

php Copy
try {
    $result = $solver->recaptcha([
        'sitekey' => '6LeTxvsqAAAAAK...',
        'url'     => 'https://example.com/login'
    ]);
    echo "CAPTCHA solved successfully: " . $result->code;
} catch (\Exception $e) {
    // Log the error or send a notification
    error_log("CAPTCHA solving error: " . $e->getMessage());
    
    // You can check for specific error codes
    if ($e->getMessage() === 'ERROR_ZERO_BALANCE') {
        // Actions to take on zero balance
    }
}

Common Error Codes

When exceptions are thrown, the library translates API error codes into human-readable messages. The most common ones are listed in the table below:

Error Code Description Recommendation
ERROR_WRONG_USER_KEY Invalid format or value of the API key Check the key in your configuration
ERROR_ZERO_BALANCE Insufficient funds in your account Top up your balance in your 2Captcha dashboard
ERROR_NO_SLOT_AVAILABLE No free workers available Retry in 10–15 seconds
ERROR_BAD_PARAMETERS Required parameters are missing Verify parameters against the documentation
ERROR_PROXY_CONNECT_REFUSED Failed to connect to the proxy Check proxy availability and string format
ERROR_CAPTCHA_UNSOLVABLE The CAPTCHA could not be solved Funds are refunded; try refreshing the CAPTCHA

Reporting Solution Accuracy

To maintain high recognition quality and ensure refunds for incorrect solutions, use the reporting methods.

php Copy
// If the website accepted the token and the form was submitted successfully
$solver->reportCorrect($result->taskId);

// If the website rejected the token with a validation error
$solver->reportIncorrect($result->taskId);

Conclusion

The PHP library for 2Captcha handles all the routine work of interacting with the API: it abstracts away polling loops, validates input parameters, and returns ready-to-use tokens or recognized text. Thanks to its clean, object-oriented syntax, it integrates seamlessly into both CLI utilities and web applications built on popular frameworks.

The service supports over 20 different CAPTCHA types, ranging from simple text-based ones to complex behavioral systems like DataDome and Amazon WAF. This means that no matter what kind of protection you encounter, you will always have a reliable tool to bypass it.

To get started, simply install the package via Composer, initialize the client with your API key, and call the required method. If needed, you can easily add proxy support or adjust timeouts to fit the specifics of your project.