Official Java SDK for the CaptchaSonic CAPTCHA solving API.
Uses native gRPC via grpc-netty-shaded. Images are sent as raw binary — no base64 overhead.
implementation 'com.captchasonic:captchasonic:1.0.0'<dependency>
<groupId>com.captchasonic</groupId>
<artifactId>captchasonic</artifactId>
<version>1.0.0</version>
</dependency>import com.captchasonic.CaptchaSonicClient;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
try (var client = new CaptchaSonicClient("sonic_your_api_key")) {
double balance = client.getBalance();
System.out.println("Balance: $" + balance);
byte[] tile = Files.readAllBytes(Path.of("tile.png"));
var result = client.solvePopularCaptcha(
List.of(tile), "Select all traffic lights", "objectClassify"
);
System.out.println(result.getTypedSolution().getGrid().getObjectsList());
}CaptchaSonicClient client = CaptchaSonicClient.builder()
.apiKey("sonic_xxx")
.host("api.captchasonic.com")
.port(443)
.timeout(Duration.ofSeconds(120))
.build();var client = new CaptchaSonicClient("sonic_xxx", "api.captchasonic.com", 443, true);The client is thread-safe — create one instance and reuse it.
client.solvePopularCaptcha(images, question, questionType);
// Full options
client.solvePopularCaptcha(
images, // List<byte[]>
"Select all traffic lights", // question
"objectClassify", // questionType
exampleImages, // List<byte[]>, nullable
false, // screenshot
"https://example.com", // websiteUrl, nullable
"sitekey123" // websiteKey, nullable
);client.solveRecaptchaV2(images, "traffic lights");
// With questionType + options
client.solveRecaptchaV2(
images, // List<byte[]>
"traffic lights", // question
"split_33", // questionType: "split_33" | "33" | "44"
"https://example.com", // websiteUrl, nullable
null // websiteKey, nullable
);client.solveGeetest("geetest_nine:Select the bear", images);
// Full options
client.solveGeetest(question, images, examples, bgImage, gtv, websiteUrl);client.solveOcr(images);
// With options
client.solveOcr(images, "mtcaptcha", false, false, 3, 4, "https://example.com");// Type-based routing (alias expansion built-in)
client.solveTikTok("whirl", "Rotate to match", images);
client.solveTikTok("click", "Select the shape", images, examples, websiteUrl);
// Accepted types: "click", "whirl", "slide", "tiktok_click", etc.client.solveBinance("grid", "Select the bicycle", images);
client.solveBinance("slide", "", images, examples, websiteUrl);
// Accepted types: "grid", "slide", "binance_grid", "binance_slide"client.solveAwsWaf(images, "grid:vehicles:cars");
client.solveAwsWaf(images, question, websiteUrl, websiteKey);client.solveSlideImage(List.of(background, piece));
// Returns: result.getTypedSolution().getSlide().getX()These submit a task and poll until a token is returned (up to 120s).
client.solveTurnstile(websiteUrl, websiteKey);
client.solveTurnstile(websiteUrl, websiteKey, proxy);
client.solvePopularCaptchaToken(websiteUrl, websiteKey, proxy);
client.solveRecaptchaV2Token(websiteUrl, websiteKey, proxy);
client.solveRecaptchaV3Token(websiteUrl, websiteKey, proxy);
client.solveCloudflare(websiteUrl, websiteKey, proxy); // proxy requiredEvery blocking method has an Async variant returning CompletableFuture<CreateTaskResponse>.
double balance = client.getBalance();
HealthCheckResponse health = client.healthCheck();
GetTaskResultResponse result = client.getTaskResult(taskId);import com.captchasonic.*;
try {
client.solvePopularCaptcha(images, question, questionType);
} catch (InvalidApiKeyException e) { /* errorId=1 */ }
catch (InsufficientBalanceException e) { /* errorId=2 */ }
catch (DailyLimitExceededException e) { /* errorId=3 */ }
catch (MinuteLimitExceededException e) { /* errorId=4 */ }
catch (QuotaExceededException e) { /* errorId=5 */ }
catch (PlanExpiredException e) { /* errorId=6 */ }
catch (CaptchaSonicException e) { /* other errors */ }Retries on UNAVAILABLE, RESOURCE_EXHAUSTED, DEADLINE_EXCEEDED with exponential backoff.
# Build
./gradlew build
# Publish (requires SONATYPE_USERNAME, SONATYPE_PASSWORD, SIGNING_KEY, SIGNING_PASSWORD)
./gradlew publishToSonatype closeAndReleaseSonatypeStagingRepositorySee the full Maven Central Publish Guide for detailed steps.