Skip to main content

3. Verify the CAPTCHA Solution

βœ… A full working backend example can be found at the bottom of this page.

Switch with ease

Verification of the solution (token) works in the same way as with Google reCAPTCHA & hCaptcha. Only the API response is slightly different with more information. And you can also verify email addresses in the same API call.

Server Side Verification​

Remember the secret key that was automatically generated together with the sitekey. This secret key is needed to verify the CAPTCHA solution with the API endpoint to ensure that it is indeed real and valid.

To verify the CAPTCHA solution, make a POST request to

with the following parameters:

Post ParameterDescription
responseThe solution (zenc-captcha-solution) of the CAPTCHA
secretYour secret key (that matches the sitekey of the widget)
emailOptional: Users email address (disposable/invalid check) - Alternatively, you can simply provide the domain name of the email (for maximum privacy:

Do not use a GET request to call /siteverify (or it will fail)

curl example​

Change CAPTCHA-SOLUTION and YOUR-SECRET-KEY with your values:

-H "Content-Type: application/x-www-form-urlencoded"

To verify the zenc-captcha-solution token sent from your frontend HTML to your backend, the endpoint requires a POST request with two parameters - your secret key and the zenc-captcha-solution token. You can optionally include the users email adress & to check wheter the user uses a disposable or invalid email address. (This option is only available on all paid plans.)

API Response​

The verification response​

The response to the POST request indicates whether the CAPTCHA solution (token) is valid.

  • The response body is a JSON object.

The response will also give you the user's country code (ISO 3166-1 alpha-2 codes), the validity of the user's email address and a fraud score for each user from 0 to 99. Scores between 0 and 55 are acceptable, while scores between 55 and 99 indicate that the user may be fraudulent. Do not rely on the score, it should only help you identify potentially fraudulent users based on their activity on your site.

"success":true|false, //true if validation is successful
"message":"XXX", //"valid" or another error message
"fraudscore":XXX, //number between 0-99
"countrycode":"XXX", //two letter country code ex. "DE", "FR"
"emailvalid":"XXX" //`none`, `valid_email`, `invalid_email`, `disposable_email` or `upgrade_plan`
//"success":true and "message":"valid" This means that the solution is correct. => accept user
Solution validity

Solutions can only be validated once and will then be marked as invalid or duplicated. Solutions are also only valid for up to 5 minutes, after which they will be marked as invalid. If you need a new solution, you should reset the captcha (zencap.reset()) and start it again (zencap.start()).

Summary Of The POST Request Response​

Response KeyDescription
successIf true, then the solution was correct, no need to check the message field. If false, the solution was invalid, duplicate or has timed out more info in "message" .
messageIf "valid", then the solution was correct. If "timeout_or_duplicate", then then the solution has already been validated or has timed out. If "invalid_solution", then the solution is not valid. Other error codes are possible.
fraudscore0-55 is acceptable, 55-99 means that the user could be a spammer based on potential fraudulent activity. However a value of 0-55 does not mean that the user is not a spammer. Use at your own risk.
countrycodeTwo-letter country codes of the users defined in ISO 3166-1 - (ISO 3166-1 alpha-2 codes). For example: Germany "DE", France "FR"
emailvalid"valid_email" is perfect, "invalid_email" or "disposable_email" is not good. "disposable_email" means that the user tried to use a disposable email address (100% sure). "none" means that you may not have submitted an email address. "upgrade_plan" means that you need to update your plan

Full (Simple) Backend Examples​

$email = $_POST['email'];
$password = $_POST['password'];
$captcharesponse = $_POST['zenc-captcha-solution'];

$secret = "YOUR-SECRET-KEY"; //never share your key

$data = array(
"response" => $captcharesponse,
"secret" => $secret,
"email" => $email,

$options = array(
"http" => array(
"header" => "Content-type: application/x-www-form-urlencoded",
"method" => "POST",
"content" => http_build_query($data),

$context = stream_context_create($options);
$verify = file_get_contents("", false, $context);
$captcha_success = json_decode($verify);

if ($captcha_success->success==false) {
//wrong solution - do not continue
//correct solution - continue with your code
//$captcha_success->fraudscore (get the score)
//$captcha_success->countrycode (get users' country code)
//$captcha_success->emailvalid (check users' email address)