Was this helpful?
How to bypass captcha using PHP
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
composer require 2captcha/2captcha
Once installed, include the Composer autoloader in your script and import the main class:
php
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
$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
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.
Solving Other Popular CAPTCHA Types
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
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
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
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
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
$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
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
// 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);
Useful Links
- Library source code and documentation: https://github.com/2captcha/2captcha-php
- Usage examples: https://github.com/2captcha/2captcha-php/tree/main/examples
- Full 2Captcha API documentation: https://2captcha.com/api-docs
- Support center: https://2captcha.com/support/tickets/new
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.