Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Verify Google reCAPTCHA with PHP
#
# Verify captcha
$post_data = http_build_query(
array(
'secret' => CAPTCHA_SECRET,
'response' => $_POST['g-recaptcha-response'],
'remoteip' => $_SERVER['REMOTE_ADDR']
)
);
$opts = array('http' =>
array(
'method' => 'POST',
'header' => 'Content-type: application/x-www-form-urlencoded',
'content' => $post_data
)
);
$context = stream_context_create($opts);
$response = file_get_contents('https://www.google.com/recaptcha/api/siteverify', false, $context);
$result = json_decode($response);
if (!$result->success) {
throw new Exception('Gah! CAPTCHA verification failed. Please email me directly at: jstark at jonathanstark dot com', 1);
}
@Slavezax

This comment has been minimized.

Copy link

commented Aug 30, 2017

Thank you!

Cloudflare users should add this.

if (isset($_SERVER["HTTP_CF_CONNECTING_IP"])) {
  $_SERVER['REMOTE_ADDR'] = $_SERVER["HTTP_CF_CONNECTING_IP"];
}
@puetzrene

This comment has been minimized.

Copy link

commented Sep 14, 2017

Thanks, exactly what i needed! Runs perfectly.

@sourovroy

This comment has been minimized.

Copy link

commented Nov 4, 2017

Thank you very much

@Filnor

This comment has been minimized.

Copy link

commented Nov 13, 2017

Works like a charm! Thank you very much!

@ozzi-

This comment has been minimized.

Copy link

commented Jan 4, 2018

This has a serious problem:

if (!$result->success) {

does not suffices, as success may be returned but as false.

if (!$result->success || $result !== true)

is a fix.

Steps to reproduce:
Replay request containing the captcha -> it will yield success = false & error code.

@Mecanik

This comment has been minimized.

Copy link

commented Jan 12, 2018

Useful in some situations, thank you!

@KazeZlat

This comment has been minimized.

Copy link

commented Jan 18, 2018

@ozzi- reCAPTCHA response always has success property, and it is true when user succeeded and false if doesn't.
So !$result->success means "'success' property of '$result' not equals true", which is sufficent to know if user failed to pass test.

However, you might want to replace that with empty($result->success) so it won't throw you E_NOTICE when request failed and json_decode returned false.

@vic3256

This comment has been minimized.

Copy link

commented Feb 9, 2018

Thanks!

@kinetic-henza

This comment has been minimized.

Copy link

commented Mar 5, 2018

Thanks a lot!!

@RickAQ-Dev

This comment has been minimized.

Copy link

commented Mar 12, 2018

Thanks!

@diversen

This comment has been minimized.

Copy link

commented May 9, 2018

Nice one!

This one will work if 'allow_url_fopen' is disabled on your server:

https://gist.github.com/diversen/8184ecfe8b796dc809c3cb2c514003a0

@parsa25eng

This comment has been minimized.

Copy link

commented Jun 27, 2018

Thanks

@Mecanik

This comment has been minimized.

Copy link

commented Aug 9, 2018

The correct method of checking result should be:

if (!$result->success || empty($result->success)) {

}
@samsonasik

This comment has been minimized.

Copy link

commented Aug 21, 2018

Thank you, actually, empty check should be enough:

if (empty($result->success)) {

}
@iamlatin

This comment has been minimized.

Copy link

commented Sep 9, 2018

i can do codes i did it for a college for fun y got a good. reposición

@iamlatin

This comment has been minimized.

Copy link

commented Sep 9, 2018

response

@CreativForm

This comment has been minimized.

Copy link

commented Oct 16, 2018

This is great solution, thanks for this. I made an more spicy solution:

function validate_rechapcha($response){
	// Verifying the user's response (https://developers.google.com/recaptcha/docs/verify)
	$verifyURL = 'https://www.google.com/recaptcha/api/siteverify';
	
	// Collect and build POST data
	$post_data = http_build_query(
		array(
			'secret' => 'YOUR_SECRET_KEY',
			'response' => $response,
			'remoteip' => (isset($_SERVER["HTTP_CF_CONNECTING_IP"]) ? $_SERVER["HTTP_CF_CONNECTING_IP"] : $_SERVER['REMOTE_ADDR'])
		)
	);
	
	// Send data on the best possible way
	if(function_exists('curl_init') && function_exists('curl_setopt') && function_exists('curl_exec')) {
		// Use cURL to get data 10x faster than using file_get_contents or other methods
		$ch =  curl_init($verifyURL);
			curl_setopt($ch, CURLOPT_POST, 1);
			curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
			curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
			curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
			curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
			curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
			curl_setopt($ch, CURLOPT_TIMEOUT, 5);
			curl_setopt($ch, CURLOPT_HTTPHEADER, array('Accept: application/json', 'Content-type: application/x-www-form-urlencoded'));
			$response = curl_exec($ch);
		curl_close($ch);
	} else {
		// If server not have active cURL module, use file_get_contents
		$opts = array('http' =>
			array(
				'method'  => 'POST',
				'header'  => 'Content-type: application/x-www-form-urlencoded',
				'content' => $post_data
			)
		);
		$context  = stream_context_create($opts);
		$response = file_get_contents($verifyURL, false, $context);
	}

	// Verify all reponses and avoid PHP errors
	if($response) {
		$result = json_decode($response);
		if ($result->success===true) {
			return true;
		} else {
			return $result;
		}
	}

	// Dead end
	return false; 
}

This is a much faster, universal and more flexible solution.

@mmxcrono

This comment has been minimized.

Copy link

commented Nov 12, 2018

This is great solution, thanks for this. I made an more spicy solution:

function validate_rechapcha($response){
	// Verifying the user's response (https://developers.google.com/recaptcha/docs/verify)
	$verifyURL = 'https://www.google.com/recaptcha/api/siteverify';
	
	// Collect and build POST data
	$post_data = http_build_query(
		array(
			'secret' => 'YOUR_SECRET_KEY',
			'response' => $response,
			'remoteip' => (isset($_SERVER["HTTP_CF_CONNECTING_IP"]) ? $_SERVER["HTTP_CF_CONNECTING_IP"] : $_SERVER['REMOTE_ADDR'])
		)
	);
	
	// Send data on the best possible way
	if(function_exists('curl_init') && function_exists('curl_setopt') && function_exists('curl_exec')) {
		// Use cURL to get data 10x faster than using file_get_contents or other methods
		$ch =  curl_init($verifyURL);
			curl_setopt($ch, CURLOPT_POST, 1);
			curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
			curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
			curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
			curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
			curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
			curl_setopt($ch, CURLOPT_TIMEOUT, 5);
			curl_setopt($ch, CURLOPT_HTTPHEADER, array('Accept: application/json', 'Content-type: application/x-www-form-urlencoded'));
			$response = curl_exec($ch);
		curl_close($ch);
	} else {
		// If server not have active cURL module, use file_get_contents
		$opts = array('http' =>
			array(
				'method'  => 'POST',
				'header'  => 'Content-type: application/x-www-form-urlencoded',
				'content' => $post_data
			)
		);
		$context  = stream_context_create($opts);
		$response = file_get_contents($verifyURL, false, $context);
	}

	// Verify all reponses and avoid PHP errors
	if($response) {
		$result = json_decode($response);
		if ($result->success===true) {
			return true;
		} else {
			return $result;
		}
	}

	// Dead end
	return false; 
}

This is a much faster, universal and more flexible solution.

This worked well for me. I had issues with using file_get_contents on a certain server, possibly due to permissions and access, so good ol' curl did the trick.

@martinm79

This comment has been minimized.

Copy link

commented Dec 12, 2018

This is great solution, thanks for this. I made an more spicy solution:

function validate_rechapcha($response)
{
	// Verifying the user's response (https://developers.google.com/recaptcha/docs/verify)
	$verifyURL = 'https://www.google.com/recaptcha/api/siteverify';

	$query_data = [
		'secret' => 'Key',
		'response' => $response,
		'remoteip' => (isset($_SERVER["HTTP_CF_CONNECTING_IP"]) ? $_SERVER["HTTP_CF_CONNECTING_IP"] : $_SERVER['REMOTE_ADDR'])
	];

	// Collect and build POST data
	$post_data = http_build_query($query_data, '', '&');

	// Send data on the best possible way
	if (function_exists('curl_init') && function_exists('curl_setopt') && function_exists('curl_exec'))
	{
		// Use cURL to get data 10x faster than using file_get_contents or other methods
		$ch = curl_init($verifyURL);
		curl_setopt($ch, CURLOPT_POST, 1);
		curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
		curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
		curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
		curl_setopt($ch, CURLOPT_TIMEOUT, 5);
		curl_setopt($ch, CURLOPT_HTTPHEADER, array('Accept: application/json', 'Content-type: application/x-www-form-urlencoded'));
		$response = curl_exec($ch);
		curl_close($ch);
	}
	else
	{
		// If server not have active cURL module, use file_get_contents
		$opts = array('http' =>
			array(
				'method' => 'POST',
				'header' => 'Content-type: application/x-www-form-urlencoded',
				'content' => $post_data
			)
		);
		$context = stream_context_create($opts);
		$response = file_get_contents($verifyURL, false, $context);
	}

	// Verify all reponses and avoid PHP errors
	if ($response)
	{
		$result = json_decode($response);
		if ($result->success === true)
		{
			return true;
		}
		else
		{
			return $result;
		}
	}

	// Dead end
	return false;
}

Change http_build_query($query_data, '', '&');

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.