Solve reCAPTCHA v2, reCAPTCHA v3, Cloudflare Turnstile, GeeTest and image captchas from PHP.
Official PHP client for CapSkip, a local captcha solver that runs on your own machine. Licensed once, not billed per solve.
composer require capskip/capskipCapSkip is a desktop app. It does the solving on your machine and exposes the standard captcha-solver HTTP API — the same in.php / res.php endpoints every 2captcha-compatible client already speaks — on 127.0.0.1:8080.
This SDK is a thin wrapper over that API, with the method names you would expect: normal(), recaptcha(), turnstile(), geetest(). Nothing leaves your network, and there is no credit balance to keep an eye on.
| Captcha | Method |
|---|---|
| Image captcha solver (distorted text / OCR) | $solver->normal($file) |
| reCAPTCHA v2 solver (checkbox) | $solver->recaptcha($sitekey, $url) |
| reCAPTCHA v2 invisible solver | $solver->recaptcha($sitekey, $url, ['invisible' => 1]) |
| reCAPTCHA Enterprise solver | $solver->recaptcha($sitekey, $url, ['enterprise' => 1]) |
| reCAPTCHA v3 solver | $solver->recaptcha($sitekey, $url, ['version' => 'v3', 'action' => 'submit']) |
| reCAPTCHA v3 Enterprise | $solver->recaptcha($sitekey, $url, ['version' => 'v3', 'enterprise' => 1]) |
| Cloudflare Turnstile solver (widget) | $solver->turnstile($sitekey, $url) |
| Cloudflare Turnstile (challenge page) | $solver->turnstile($sitekey, $url, ['data' => ..., 'pagedata' => ...]) |
| GeeTest v3 solver (slide puzzle) | $solver->geetest($gt, $challenge, $url) |
hCaptcha and FunCaptcha/Arkose are not supported. hCaptcha is the one people misidentify most often, since it also puts a data-sitekey on the widget — check for class="h-captcha" or a js.hcaptcha.com script before reaching for recaptcha().
Point the SDK at the live captcha demo pages to sanity-check your setup against real widgets.
Download and run the CapSkip desktop app — CapSkipInstaller.msi. Leave it running in the background.
In CapSkip settings, note:
- API port (default:
8080) - API key (optional — if validation is disabled, any string works)
composer require capskip/capskipOr from source:
git clone https://github.com/capskip/capskip-php.git
cd capskip-php
composer install<?php
require 'vendor/autoload.php';
use CapSkip\CapSkip;
$solver = new CapSkip(['host' => '127.0.0.1', 'port' => 8080]);
$result = $solver->recaptcha(
'YOUR_SITEKEY',
'https://example.com/page-with-recaptcha'
);
echo $result['code']; // g-recaptcha-response tokenPrerequisite: CapSkip must be running before you call the SDK. If you see a connection error, see Troubleshooting.
Cloud captcha APIs charge per solve, which turns a retry loop into an expense and routes every page URL and sitekey you touch through someone else's queue.
CapSkip flips that around:
- Unlimited solving — one license, no per-captcha charge, no balance to top up
- Runs on
127.0.0.1— the SDK never talks to a third-party server - No per-key rate limit — throughput is whatever your machine can manage
- Fast — image captchas come back in well under a second; a typical reCAPTCHA v2 lands in 30–45 seconds
CapSkip answers on the same in.php / res.php endpoints, so it works as a 2captcha API alternative: an existing integration usually needs nothing more than its host pointed at 127.0.0.1:8080. The migration notes cover the details, if you would rather keep your current client library than switch to this one.
| Guide | Description |
|---|---|
| Tutorial | Complete walkthrough of every captcha type |
| Getting Started | Full setup: CapSkip app, SDK install, first script |
| API Reference | All classes, methods, parameters, and return values |
| Examples | Ready-to-run scripts for every captcha type |
| Troubleshooting | Connection errors, timeouts, proxy issues |
| Contributing | Development setup, tests, pull requests |
| Changelog | Release history |
use CapSkip\CapSkip;
$solver = new CapSkip([
'apiKey' => 'capskip', // your CapSkip API key (or any string if validation is off)
'host' => '127.0.0.1', // CapSkip host
'port' => 8080, // CapSkip port from app settings
'defaultTimeout' => 120, // seconds — image captcha polling timeout
'recaptchaTimeout' => 300, // seconds — reCAPTCHA / Turnstile / GeeTest polling timeout
'pollingInterval' => 5, // max seconds between res.php polls (starts at 0.25s, backs off to this)
]);Use environment variables in production:
# Linux / macOS
export CAPSKIP_API_KEY="your-key"
export CAPSKIP_HOST="127.0.0.1"
export CAPSKIP_PORT="8080"# Windows PowerShell
$env:CAPSKIP_API_KEY = "your-key"
$env:CAPSKIP_HOST = "127.0.0.1"
$env:CAPSKIP_PORT = "8080"use CapSkip\CapSkip;
$solver = new CapSkip([
'apiKey' => getenv('CAPSKIP_API_KEY') ?: 'capskip',
'host' => getenv('CAPSKIP_HOST') ?: '127.0.0.1',
'port' => (int) (getenv('CAPSKIP_PORT') ?: 8080),
]);$result = $solver->normal('captcha.png');
$result = $solver->normal('https://example.com/captcha.jpg');
$result = $solver->normal('data:image/png;base64,iVBORw0KGgo...');
echo $result['code'];// reCAPTCHA v2
$v2 = $solver->recaptcha('...', 'https://example.com');
// reCAPTCHA v3
$v3 = $solver->recaptcha('...', 'https://example.com', [
'version' => 'v3',
'action' => 'submit',
'score' => 0.7,
]);$result = $solver->turnstile('0x4AAAAAAA...', 'https://example.com');$gt is static per site, but $challenge is single-use and expires in about a
minute — fetch a fresh pair right before solving.
$result = $solver->geetest(
'81388ea1fc187e0c335c0a8907ff2625',
'7cf6a8b1a2c34d5e6f7089abcdef0123',
'https://example.com/login'
);
// Post these back exactly as the site's own front-end would
$result['challenge']; $result['validate']; $result['seccode'];// Proxy is not supported for image captcha
$result = $solver->recaptcha('...', 'https://example.com', [
'proxy' => ['type' => 'HTTPS', 'uri' => 'user:pass@1.2.3.4:3128'],
]);
$result = $solver->turnstile('...', 'https://example.com', [
'proxy' => ['type' => 'HTTP', 'uri' => '1.2.3.4:3128'],
]);use CapSkip\CapSkip;
$solver = new CapSkip();
$r1 = $solver->recaptcha('...', 'https://a.com');
$r2 = $solver->turnstile('...', 'https://b.com');
echo $r1['code'], $r2['code'];PHP executes synchronously, so each solve blocks until it finishes.
AsyncCapSkipis exported as an alias ofCapSkipfor parity with the other CapSkip SDKs — code ported from them keeps working unchanged.
More examples: examples/
The SDK hands back a token; the rest of your stack does what it already does.
In a Laravel app, resolve the solver from the container and treat a solve like any other outbound call:
$this->app->singleton(CapSkip::class, fn () => new CapSkip([
'apiKey' => config('services.capskip.key'),
'host' => config('services.capskip.host', '127.0.0.1'),
]));Posting the token with Guzzle — the field name is whatever the target form uses; for reCAPTCHA it is g-recaptcha-response:
$token = $solver->recaptcha($sitekey, $url)['code'];
$client->post($url, ['form_params' => [
'g-recaptcha-response' => $token,
// ... the rest of the form
]]);Driving a real browser with Symfony Panther (or php-webdriver/Selenium), read the sitekey off the page, solve, then write the token back:
$sitekey = $crawler->filter('[data-sitekey]')->attr('data-sitekey');
$token = $solver->recaptcha($sitekey, $client->getCurrentURL())['code'];
$client->executeScript(
'document.getElementById("g-recaptcha-response").value = arguments[0];', [$token]
);Longer walkthroughs: Selenium and the PHP captcha solver guide.
Every solve method returns an associative array:
[
'captchaId' => '12345', // internal ID from CapSkip
'code' => 'TOKEN_OR_TEXT', // solution — text for image, token for reCAPTCHA/Turnstile
'userAgent' => '...', // Turnstile only — use when submitting challenge-page tokens
]GeeTest additionally expands its answer into challenge, validate, and
seccode, while code keeps the raw JSON string.
use CapSkip\CapSkip;
use CapSkip\Exceptions\ValidationException;
use CapSkip\Exceptions\NetworkException;
use CapSkip\Exceptions\ApiException;
use CapSkip\Exceptions\TimeoutException;
try {
$result = $solver->recaptcha('...', '...');
} catch (ValidationException $e) {
// invalid parameters
} catch (NetworkException $e) {
// CapSkip not running, or captcha not ready (manual polling)
} catch (ApiException $e) {
// API returned an error code
} catch (TimeoutException $e) {
// polling timeout exceeded
}All four extend CapSkip\Exceptions\CapSkipError, so you can catch them all at once with the base class.
Install the CapSkip desktop app, composer require capskip/capskip, then call the method that matches the widget — recaptcha(), turnstile(), geetest() or normal(). Each one blocks until CapSkip has an answer, then returns a token, or the recognized text in the case of an image captcha.
The SDK itself is MIT-licensed and free. Solving needs the CapSkip app, which is bought once rather than metered per captcha, so your cost stops scaling with volume.
reCAPTCHA v2 (checkbox and invisible), reCAPTCHA v3, reCAPTCHA Enterprise, Cloudflare Turnstile, GeeTest v3, and image/text captchas. Not hCaptcha, and not FunCaptcha/Arkose.
Yes — see above. The SDK has no framework ties and depends only on ext-curl and ext-json, so it drops into any PHP 8 project.
Google derives v3 scores from IP reputation, cookies and browsing history. A solver returns a valid token, but it cannot change how Google grades that token — score is forwarded as the target you want, not a guarantee. If a site enforces a high threshold, solve through a cleaner IP using the proxy option.
Yes. CapSkip serves the same endpoints, so you can either move to this SDK or repoint an existing 2captcha client at 127.0.0.1:8080.
For widget captchas, yes — CapSkip loads the URL you pass it. Image captchas only need the image, and that can be a local file.
It can. A reCAPTCHA solve takes tens of seconds, which is longer than most max_execution_time settings and longer than a user will wait on a page load. Solve from a queue worker or CLI script rather than inside a web request.
- PHP 8.0 or newer
- The
curlandjsonextensions (bundled with most PHP installs) - No other runtime dependencies
git clone https://github.com/capskip/capskip-php.git
cd capskip-php
composer install
composer testSee CONTRIBUTING.md for the full development workflow.
- CapSkip — local captcha solver · download the app
- Captcha demo pages — live reCAPTCHA, Turnstile, GeeTest and image widgets
- PHP captcha solver guide
- HTTP API docs
- Other clients: Python · Node.js · .NET · MCP server for AI agents
- Packagist package · report an issue
MIT — see LICENSE.