Java Client
The EU CAPTCHA Java client is available in three variants published to Maven Central. All three expose the same imports and request/response model — the difference is the underlying HTTP library and the target Spring version.
| Variant | Artifact ID | HTTP library | Java | Spring |
|---|---|---|---|---|
java-resttemplate |
eu-captcha-java-resttemplate |
Spring RestTemplate |
17+ | Spring Framework 6 (WebMVC, synchronous) |
java-webflux-boot2 |
eu-captcha-java-webflux-boot2 |
Spring WebClient |
8+ | Spring Boot 2 / WebFlux (reactive) |
java-webflux-boot3 |
eu-captcha-java-webflux-boot3 |
Spring WebClient |
17+ | Spring Boot 3 / Jakarta EE (reactive) |
Use java-resttemplate for traditional Spring MVC applications, java-webflux-boot2 for Spring Boot 2 reactive applications, and java-webflux-boot3 for Spring Boot 3 applications that use the Jakarta EE namespace.
Installation
All three variants share the same groupId (com.myrasec) and version (1.0.0). Replace ARTIFACT_ID with the variant you need.
Maven:
<dependency>
<groupId>com.myrasec</groupId>
<artifactId>ARTIFACT_ID</artifactId>
<version>1.0.0</version>
</dependency>
Gradle:
implementation "com.myrasec:ARTIFACT_ID:1.0.0"
For example, to use the RestTemplate variant:
<dependency>
<groupId>com.myrasec</groupId>
<artifactId>eu-captcha-java-resttemplate</artifactId>
<version>1.0.0</version>
</dependency>
Usage — java-resttemplate
Synchronous. Returns VerifyResponse directly. Use this variant with Spring MVC / servlet-based applications.
import com.myrasec.client.ApiClient;
import com.myrasec.client.api.EuCaptchaApi;
import com.myrasec.client.model.VerifyRequest;
import com.myrasec.client.model.VerifyResponse;
import org.springframework.web.client.RestClientException;
ApiClient client = new ApiClient(); // thread-safe; create once and share
EuCaptchaApi api = new EuCaptchaApi(client);
VerifyRequest request = new VerifyRequest()
.sitekey(System.getenv("EUCAPTCHA_SITE_KEY"))
.secret(System.getenv("EUCAPTCHA_SECRET_KEY"))
.clientIp(clientIp) // real end-user IP — see below
.clientToken(euCaptchaToken) // value of the "eu-captcha-response" POST field
.clientUserAgent(userAgent); // value of the User-Agent request header
try {
VerifyResponse response = api.verifyClientToken(request);
if (response.isTrainingMode()) {
// Validation was bypassed — sitekey missing, secret wrong, or protection disabled.
// Check your credentials immediately if you see this in production.
denyAccess();
} else if (Boolean.TRUE.equals(response.getSuccess())) {
allowAccess();
} else {
denyAccess();
}
} catch (RestClientException e) {
// Network error or unexpected HTTP status.
// Decide your fallback policy: allow or deny.
log.error("EU CAPTCHA verification failed: {}", e.getMessage());
}
Usage — java-webflux-boot2 and java-webflux-boot3
Reactive. verifyClientToken returns Mono<VerifyResponse>. Compose it into your handler chain rather than calling .block(). The two variants are identical in API — the only difference is the Spring Boot and Jakarta EE version they target.
import com.myrasec.client.ApiClient;
import com.myrasec.client.api.EuCaptchaApi;
import com.myrasec.client.model.VerifyRequest;
import com.myrasec.client.model.VerifyResponse;
import org.springframework.web.reactive.function.client.WebClientResponseException;
import reactor.core.publisher.Mono;
ApiClient client = new ApiClient(); // thread-safe; create once and share
EuCaptchaApi api = new EuCaptchaApi(client);
VerifyRequest request = new VerifyRequest()
.sitekey(System.getenv("EUCAPTCHA_SITE_KEY"))
.secret(System.getenv("EUCAPTCHA_SECRET_KEY"))
.clientIp(clientIp)
.clientToken(euCaptchaToken)
.clientUserAgent(userAgent);
Mono<VerifyResponse> result = api.verifyClientToken(request)
.map(response -> {
if (response.isTrainingMode()) {
denyAccess();
} else if (Boolean.TRUE.equals(response.getSuccess())) {
allowAccess();
} else {
denyAccess();
}
return response;
})
.onErrorResume(WebClientResponseException.class, e -> {
log.error("EU CAPTCHA verification failed: {}", e.getMessage());
return Mono.empty(); // decide your fallback policy
});
// In a WebFlux handler, return the Mono directly:
// return result.then(ServerResponse.ok().build());
Extracting the real client IP
Always pass the real end-user IP address, not the IP of your reverse proxy or CDN.
Spring MVC (HttpServletRequest):
String clientIp = request.getRemoteAddr();
// Behind a reverse proxy or CDN:
String forwarded = request.getHeader("X-Forwarded-For");
if (forwarded != null && !forwarded.isBlank()) {
clientIp = forwarded.split(",")[0].trim();
}
Spring WebFlux (ServerWebExchange):
String clientIp = exchange.getRequest().getRemoteAddress().getAddress().getHostAddress();
// Behind a reverse proxy or CDN:
String forwarded = exchange.getRequest().getHeaders().getFirst("X-Forwarded-For");
if (forwarded != null && !forwarded.isBlank()) {
clientIp = forwarded.split(",")[0].trim();
}
VerifyRequest fields
| Field | Type | Description |
|---|---|---|
sitekey(String) |
required | Your public sitekey |
secret(String) |
required | Your secret key — keep server-side only |
clientIp(String) |
required | Visitor's IPv4 or IPv6 address. Use X-Forwarded-For or X-Client-IP when behind a proxy or CDN. |
clientToken(String) |
required | Value of the eu-captcha-response form field. Pass an empty string if the widget did not complete — always submit it. |
clientUserAgent(String) |
required | Visitor's User-Agent header |
VerifyResponse fields
| Method | Type | Description |
|---|---|---|
getSuccess() |
Boolean |
true if the token passed verification |
isTrainingMode() |
boolean |
true if validation was skipped and success is forced to true. Check your sitekey and secret immediately if you see this in production. See server-side verification for details. |
Security
ApiClientis thread-safe. Create one instance and share it across your application — do not create a new instance per request.- Store credentials in environment variables or a secrets manager — never in source code.
- Do not enable
ApiClient.setDebugging(true)in production. Debug mode logs the full request body; the raw HTTP payload is not redacted even thoughVerifyRequest.toString()masks the secret.
Building from source
If you prefer to build locally rather than pulling from Maven Central:
git clone https://github.com/Myra-Security-GmbH/eu-captcha-java.git
cd eu-captcha-java/java-resttemplate # or java-webflux-boot2 / java-webflux-boot3
mvn clean install
To generate your own client for a different language from the OpenAPI spec, see OpenAPI Generator.