Skip to content

Repository files navigation

CapSkip PHP SDK

PHP 8.0+ License: MIT Tests

Official PHP client for the CapSkip local captcha solver.

CapSkip runs on your machine and exposes a standard captcha-solver HTTP API (the familiar in.php / res.php endpoints). This SDK wraps that API with clean, familiar method names, so you can solve captchas locally — no per-solve API fees beyond your CapSkip license.


Quick start (5 minutes)

1. Install CapSkip

Download and run the CapSkip desktop app from capskip.com. Leave it running in the background.

In CapSkip settings, note:

  • API port (default: 8080)
  • API key (optional — if validation is disabled, any string works)

2. Install the SDK

composer require capskip/capskip

Or from source:

git clone https://github.com/capskip/capskip-php.git
cd capskip-php
composer install

3. Solve your first captcha

<?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 token

Prerequisite: CapSkip must be running before you call the SDK. If you see a connection error, see Troubleshooting.


Supported captcha types

Type SDK method
Image CAPTCHA (distorted text) $solver->normal($file)
reCAPTCHA v2 (checkbox) $solver->recaptcha($sitekey, $url)
reCAPTCHA v2 Invisible $solver->recaptcha($sitekey, $url, ['invisible' => 1])
reCAPTCHA v2 Enterprise $solver->recaptcha($sitekey, $url, ['enterprise' => 1])
reCAPTCHA v3 $solver->recaptcha($sitekey, $url, ['version' => 'v3'])
reCAPTCHA v3 Enterprise $solver->recaptcha($sitekey, $url, ['version' => 'v3', 'enterprise' => 1])
Cloudflare Turnstile (widget) $solver->turnstile($sitekey, $url)
Cloudflare Turnstile (challenge page) $solver->turnstile($sitekey, $url, ['data' => ..., 'pagedata' => ...])
GeeTest v3 (slide) $solver->geetest($gt, $challenge, $url)

Documentation

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

Configuration

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),
]);

Usage examples

Image captcha

$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 / v3

// reCAPTCHA v2
$v2 = $solver->recaptcha('...', 'https://example.com');

// reCAPTCHA v3
$v3 = $solver->recaptcha('...', 'https://example.com', [
    'version' => 'v3',
    'action' => 'submit',
    'score' => 0.7,
]);

Cloudflare Turnstile

$result = $solver->turnstile('0x4AAAAAAA...', 'https://example.com');

GeeTest v3

$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'];

With a proxy (reCAPTCHA, Turnstile & GeeTest only)

// 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'],
]);

Solving several captchas

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. AsyncCapSkip is exported as an alias of CapSkip for parity with the other CapSkip SDKs — code ported from them keeps working unchanged.

More examples: examples/


Return value

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.


Error handling

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.


Requirements

  • PHP 8.0 or newer
  • The curl and json extensions (bundled with most PHP installs)
  • No other runtime dependencies

Development

git clone https://github.com/capskip/capskip-php.git
cd capskip-php
composer install
composer test

See CONTRIBUTING.md for the full development workflow.


Links


License

MIT — see LICENSE.