Protecting a PHP contact form from spam is no longer just about checking whether a visitor ticked an “I’m not a robot” checkbox. A more robust implementation should validate the reCAPTCHA response on the server, inspect the assessment returned by Google’s reCAPTCHA Enterprise API, and make the final decision based on the risk score.
In this tutorial, we will integrate a Google reCAPTCHA Enterprise Checkbox into a PHP contact form and verify it on the server using a score-based decision model.
The Google reCAPTCHA Checkbox (v2) is a user-friendly way to protect your website from spam and abuse. It requires users to check a box to prove they are human, while also analyzing their behavior to determine the likelihood of them being a bot. By using the reCAPTCHA Enterprise API, we can get a risk score for each submission and make informed decisions about whether to accept or reject it.
In this example, we will create a simple contact form that includes a reCAPTCHA checkbox. When the form is submitted, we will send the reCAPTCHA response to the server for verification. The server will then call the reCAPTCHA Enterprise API to get a risk score and decide whether to accept or reject the submission based on that score.
The Google reCAPTCHA with PHP implementation uses three PHP files:
Before writing the PHP code, it is important to understand the difference between the checkbox and the score.
The checkbox is the user-facing part of the integration. It gives the visitor an explicit reCAPTCHA interaction.
The score is the server-side risk signal returned by the reCAPTCHA Enterprise assessment.
So, these are two different things:
Checkbox → User completes reCAPTCHA → Token generated → Server validates token → Google returns risk assessment → PHP evaluates score
Simply receiving a token is not enough. The backend should create an assessment and verify that the token is valid before trusting the score.
Google specifically recommends creating an assessment from the backend to verify the token and assess the risk associated with the interaction.
The simplest way to create a reCAPTCHA key is through the reCAPTCHA Admin console.

To use Google reCAPTCHA Enterprise, you need to set up a project in the Google Cloud Console and enable the reCAPTCHA Enterprise API.
Since, you already created a reCAPTCHA key in the reCAPTCHA Admin console, you don’t need to create a new project in the Google Cloud Console. You can use the same project that was automatically created for you when you created the reCAPTCHA key.
After completing the above steps, you will have the necessary keys (reCAPTCHA Site Key, API Key, and Project ID) to integrate reCAPTCHA Enterprise into your PHP application.
Create a configuration file (e.g., config.php) in your PHP application to store the reCAPTCHA Site Key, API Key, and Project ID as constants or variables. This will allow you to easily access these keys throughout your application.
<?php
// Define constants for Google reCAPTCHA Enterprise configuration
define('GCP_PROJECT_ID', '_YOUR_GOOGLE_CLOUD_PROJECT_ID_HERE_');
define('GCP_API_KEY', '_GOOGLE_PROJECT_API_KEY_HERE_');
define('RECAPTCHA_SITE_KEY', '_YOUR_RECAPTCHA_SITE_KEY_HERE_');
define('RECAPTCHA_THRESHOLD', 0.5); // Minimum score required for reCAPTCHA validation
// Other configuration constants can be added here as needed,
// such as email settings, database credentials, etc.
?>
Build your HTML form (e.g., index.php) and include the reCAPTCHA checkbox using the Site Key.
First, include the reCAPTCHA Enterprise JavaScript API in the <head> section of your HTML:
<script src="https://www.google.com/recaptcha/enterprise.js" async defer></script>
Create a simple contact form with fields for name, email, subject, and message. Add the reCAPTCHA checkbox to the form, the data-sitekey attribute should be set to your reCAPTCHA Site Key and the data-action attribute should be set to a custom action name (e.g., “submit”).
<form method="POST" action="process_form.php">
<!-- Name Field -->
<div class="form-group">
<label for="name">Your Name <span class="required">*</span></label>
<input type="text" name="name" placeholder="John Doe" required>
</div>
<!-- Email Field -->
<div class="form-group">
<label for="email">Your Email <span class="required">*</span></label>
<input type="email" name="email" placeholder="john@example.com" required>
</div>
<!-- Subject Field -->
<div class="form-group">
<label for="subject">Subject <span class="required">*</span></label>
<input type="text" name="subject" placeholder="How can we help?" required>
</div>
<!-- Message Field -->
<div class="form-group">
<label for="message">Message <span class="required">*</span></label>
<textarea name="message" placeholder="Tell us more about your inquiry..." required></textarea>
</div>
<div class="form-group">
<!-- Google reCAPTCHA Checkbox -->
<div class="g-recaptcha" data-sitekey="YOUR_RECAPTCHA_SITE_KEY" data-action="submit"></div>
</div>
<!-- Submit Button -->
<input type="submit" name="submit" value="Send Message" class="form-submit">
</form>
On form submission, the reCAPTCHA checkbox will generate a response token that will be sent to the server (process_form.php) along with the form data.
In your form submission handler (e.g., process_form.php), you will need to capture the reCAPTCHA response token from the form submission and send it to the reCAPTCHA Enterprise API for verification.
<?php
// Include the configuration file
require_once 'config.php';
// Check if the form was submitted via POST
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// Sanitize input fields
$name = trim($_POST['name'] ?? '');
$email = trim($_POST['email'] ?? '');
$subject = trim($_POST['subject'] ?? '');
$message = trim($_POST['message'] ?? '');
// Validate input fields
$validationErrors = [];
if(empty($name)){
$validationErrors['name'] = 'Name is required.';
}
if(empty($email)){
$validationErrors['email'] = 'Email is required.';
} elseif(!filter_var($email, FILTER_VALIDATE_EMAIL)){
$validationErrors['email'] = 'Invalid email format.';
}
if(empty($subject)){
$validationErrors['subject'] = 'Subject is required.';
}
if(empty($message)){
$validationErrors['message'] = 'Message is required.';
}
if(!empty($validationErrors)){
// Return validation errors if any fields are invalid
$response = [
'success' => false,
'message' => 'Please correct the errors in the form.',
'errors' => $validationErrors
];
}else{
// Verify the reCAPTCHA token
$token = $_POST['g-recaptcha-response'] ?? '';
if(empty($token)){
$response = [
'success' => false,
'message' => 'reCAPTCHA verification failed. Please try again.',
'errors' => ['recaptcha' => 'reCAPTCHA token is missing.']
];
}else{
// Create the reCAPTCHA Enterprise API endpoint URL
$url = 'https://recaptchaenterprise.googleapis.com/v1/projects/' . GCP_PROJECT_ID . '/assessments?key=' . GCP_API_KEY;
// Build the assessment request payload
$assessmentRequest = [
'event' => [
'token' => $token,
'siteKey' => RECAPTCHA_SITE_KEY,
'expectedAction' => 'submit',
'userAgent' => $_SERVER['HTTP_USER_AGENT'] ?? 'Unknown',
'userIpAddress' => $_SERVER['REMOTE_ADDR'] ?? ''
]
];
// Initialize CURL and send the request to the reCAPTCHA Enterprise API
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => $url,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($assessmentRequest),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_SSL_VERIFYHOST => 2,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json; charset=utf-8'
]
]);
$response = curl_exec($curl);
$httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
$curlError = curl_error($curl);
curl_close($curl);
if ($curlError) {
$response = [
'success' => false,
'message' => 'Error communicating with reCAPTCHA API: ' . $curlError,
'errors' => ['recaptcha' => 'CURL error: ' . $curlError]
];
} elseif ($httpCode !== 200) {
$response = [
'success' => false,
'message' => 'reCAPTCHA API returned an unexpected HTTP code: ' . $httpCode,
'errors' => ['recaptcha' => 'HTTP error code: ' . $httpCode]
];
} else {
// Decode the API response and check the assessment result
$assessmentResponse = json_decode($response, true);
if (isset($assessmentResponse['tokenProperties']['valid']) && $assessmentResponse['tokenProperties']['valid'] === true) {
$score = $assessmentResponse['riskAnalysis']['score'] ?? 0.0;
if ($score >= RECAPTCHA_THRESHOLD) {
// Here you would typically send the email or save the form data to a database
// For demonstration, we'll just return a success response
$response = [
'success' => true,
'message' => 'Thank you! Your message has been sent successfully. We will get back to you soon.'
];
// Unset the POST data to prevent resubmission on page refresh
unset($_POST);
} else {
$response = [
'success' => false,
'message' => 'reCAPTCHA verification failed. Your score was too low.',
'errors' => ['recaptcha' => 'Low reCAPTCHA score: ' . $score]
];
}
} else {
$response = [
'success' => false,
'message' => 'Invalid reCAPTCHA token.',
'errors' => ['recaptcha' => 'Token is invalid or expired.']
];
}
}
}
}
}
?>
After processing the form submission and evaluating the risk score, you can display an appropriate message to the user. If the submission is accepted, you might show a success message. If it is rejected due to a low risk score, you can inform the user that their submission could not be processed and suggest trying again later.
If you want to display the status message on the same page as the form, do the following:
index.php file to check for a status message passed from process_form.php.
require_once 'process_form.php';
<?php if (!empty($response['message'])): ?>
<div class="alert alert-<?php echo $response['success'] ? 'success' : 'error'; ?>">
<?php echo htmlspecialchars($response['message']); ?>
</div>
<?php endif; ?>
Note: Ensure that you remove process_form.php from the form’s action attribute and instead submit the form to index.php to handle the status message display.
Integrating Google reCAPTCHA Enterprise into a PHP contact form is more effective when the implementation treats reCAPTCHA as a server-side risk assessment system, rather than merely a checkbox. By validating the reCAPTCHA response on the server and using the risk score to make decisions, you can significantly reduce spam submissions and improve the security of your contact form.
This approach provides a clean separation between the public reCAPTCHA widget and the private server-side verification logic, while giving the PHP application a configurable risk-based decision instead of relying solely on whether the checkbox was completed.
Understanding Checkbox vs. Score-Based reCAPTCHA:
The terminology can be confusing because the implementation can use a checkbox key while the backend still receives a risk score.
If you want to use a score-based key and don’t want to display the checkbox, see our Google reCAPTCHA v3 with PHP tutorial. It uses a score-based key and does not display the checkbox, but still provides risk signals for backend verification.
Looking for expert assistance to implement or extend this script’s functionality? Submit a Service Request
💰 Budget-friendly • 🌍 Global clients • 🚀 Production-ready solutions
Any way to change it so that some fields are not require? Thank you.
Is it possible to use this to send an SMS text message to a specified number as well as sending an email to the admin?
Very helpful.. KUDOS!
Very Helpful
Love you bro, Great Help
Hi
ist this Recaptch V2 or V3 ?
Thanks a lot in advance
Its type is reCAPTCHA v2. If you want to validate requests in the background, use Invisible reCAPTCHA – https://www.codexworld.com/google-invisible-recaptcha-with-php/
thank you so much !
great job sir 🙂
nice 🙂
Thanks for your help ……!!!
Thank you so much.. It helps me a lot 🙂
kindly help how to how to use this ReCaptcha response on to different page( submission.php) where all my PHP code is present and pass ReCaptcha response from HTML page to php page.
You can do it easily by the 2 steps.
1. Put the PHP Code in the
submission.phpfile.2. Specify
submission.phpin the form action attribute.Can you please send code for recaptcha validation when form details are submitted to other page for example my code is in contact.php and details are posted to submit.php i.e, action=”submit.php”
Thanks a lot , worked very well .
Will it work if in the action you source a php file with the validation?
Yes, it will work.
thanks a lot.
Working! Thank you is the best I could find!
thanks a lot
Hey…
Thanks a lot, for the approach to validate captcha.
B.R
Daniel Chaur
Nevermind. I see now. I downloaded the code, and I see you put the PHP code in the HTML itself. I guess I was assuming it was a link to a PHP file in the action=”” section. Thanks.
Oh. Wait. Is it just that you want a donation to get all the code? That’s fine. I just thought it was all here. Can you let me now if that’s why I am having problems? Thanks.
Thanks for your reply. I guess I’m just trying to see exactly how you did that. I don’t even understand how your demo works, with nothing in the action field. I’m not a programmer, so I can’t develop an action by myself. I was hoping to see your PHP code so I can modify it to suit my needs, but it doesn’t work if I just use your example code. That’s why I was hoping to see how it’s actually done. In other words, your separate example code does not work “as is” for me, and there is no form action so I can see how you actually coded the demo. I hope that makes sense. Thanks.
In your demo, the form action is blank. Where/how are you referencing the PHP code? Thanks.
This form data is submitted to the same page for verification.
Hi,
Would you be able to help me to make your great form more secure (build in security checks on each field before the form is submitted) ?
I found several sites with info, but I can’t manage it to implement it on your form.
Or if someone else can make it more secure?
Thx a lot,
John
This is very useful for all fresher’s
nice very helpful for me i just implemented it after reading your post 🙂 Thank you So much
how would you put the php in a separate file rather than it being inline with the html ?
Hi.. i want disable the image verification process in Recaptcha.. is it possible to do it ?
@Arung Google reCAPTCHA image verification widget is appearing due to the following reasons.
awesome work fine, useful to stop js attack
Thank you, very nice script! How can make sending without refreshing page?
Thank you so much! for this nice little script. It was very useful.
This tutorial made the most sense to me out of all my searching for how to do this.
Thanks
thank a lot
Thank you man, I was really searching for this for my site
Thanks for this simplified script. It works well
Thank you for this valuable script 🙂
Hello,
thank you for this nice little script. It was very usefull, because it doesn’t require any extra libs.
Greetings
Thank you very much for providing this!! There’s not many simple examples out there yet for ver. 2, but I found this linked from stackoverflow. I’ve been looking and working on this (off and on) for several days, but after I found your code, I was done in about 20 minutes. Thank you so much!
Hi,
great tutorial, thank you!
I just found a little problem (maybe it’s a feature): The new image captcha reloads automatically if a user did not select all images correctly. So no post is processed and the server-side validation via php is never triggered.
Do you know about this? Is there a way to prevent this reloading and validate the captcha like you described here?
@Robert
Yes, you are right. It is a feature of new Google reCAPTCHA.
Hello, great tutorial unlike most which are out of date. But, i’m having an issue. I get verification failed every time. I even downloaded your demo and just swapped out site and secret key as requested. (also edited out the gmail address to which its sent).
Tried audio and picture verification dozens of times, each time i get: Robot verification failed, please try again.
@Eric
The possible problem could be the registered site domain is not matched with the script hosted domain.
I have found out the you can send an email without filling in the name and email address, after doing the recaptcha and filling in the message box.
Is there a fix for this?
Thanks
Peter
@Peter
The data validation code is not included because our main purpose of this tutorial is to describe the reCAPTCHA validation process. After reCAPTCHA validation success, you can place the data validation code as per your requirement.