Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Deekshith's avatar

Laravel recaptcha v3 integration timeout problem

I have implemented laravel recaptcha v3 like below,

<input type="hidden" name="recaptcha" id="recaptcha">
<script src="https://www.google.com/recaptcha/api.js?render={{ config('services.recaptcha.sitekey') }}"></script>
<script>
         grecaptcha.ready(function() {
             grecaptcha.execute('{{ config('services.recaptcha.sitekey') }}', {action: 'subscribe'}).then(function(token) {
                if(token) {
                    document.getElementById('recaptcha').value = token;
                }
             });
         });
</script>

in controller,

 $url = 'https://www.google.com/recaptcha/api/siteverify';
        $remoteip = $_SERVER['REMOTE_ADDR'];
        $data = [
                'secret' => config('services.recaptcha.secret'),
                'response' => $request->get('recaptcha'),
                'remoteip' => $remoteip
              ];
        $options = [
                'http' => [
                  'header' => "Content-type: application/x-www-form-urlencoded\r\n",
                  'method' => 'POST',
                  'content' => http_build_query($data)
                ]
            ];
        $context = stream_context_create($options);
        $result = file_get_contents($url, false, $context);
        $resultJson = json_decode($result);
        dd($resultJson);

But i am getting timeout-or-duplicate error if i spend 2 or 3 minutes in form how to avoid this or any easy solution?

0 likes
10 replies
Sergiu17's avatar
Sergiu17
Best Answer
Level 60

Because token expires in 2 minutes, you have to run this code

grecaptcha.execute('{{ config('services.recaptcha.sitekey') }}', {action: 'subscribe'}).then(function(token) {
                if(token) {
                    document.getElementById('recaptcha').value = token;
                }
});

when you submit the form

https://developers.google.com/recaptcha/docs/v3

Note: reCAPTCHA tokens expire after two minutes. If you're protecting an action with reCAPTCHA, make sure to call execute when the user takes the action rather than on page load.

<form>
	<input type="hidden" name="recaptcha" id="recaptcha">
	<button>Submit</button>
</form>

<script>
	const btn = document.querySelector('button');
	const form = document.querySelector('form');

	btn.addEventListener('click', () => {
		grecaptcha
            .execute('{{ config('services.recaptcha.sitekey') }}', {action: 'subscribe'})
			.then(function(token) {
                if(token) {
                    document.getElementById('recaptcha').value = token;

					form.submit();
                }
		});
	});
Deekshith's avatar

Thank you for the reply and i am using ajax form submit i should change code in ajax code right?

the code is like below,

 //Subscribe form submit
    $('#user_register').submit(function(e) {
      e.preventDefault();
      var agree = $('#agree_terms_checkbox').val();
      if(agree ==1) {
      var data = $(this).serialize();
      var type = 'post';
      var url = "{{ url('subscribe') }}";

      $('#register').prop("disabled",true);
      $('#register').text("Please wait..");

      // process the form
      $.ajax({
          type : type,
          url  : url,
          data : data,
          dataType : 'json', // what type of data do we expect back from the server
          encode  : true
      })
          // using the done promise callback
          .done(function(data) {
            $('#register').removeAttr('disabled');
            $("#register").text("SUBSCRIBE");

            if(data.status == 500) {

                printErrorMsg(data.info);
                return false;

            } else if(data.status == 600) {
                  swal(data.info);
                  return false;

              } else if(data.status == 200) {

                swal({
                  html :true,
                  title: "Success!",
                  text: "<strong>"+data.info+"</strong>",
                  type: "success",
                  confirmButtonText: "OK"
                },
                function(isConfirm){
                  if (isConfirm) {
                    window.location.href="{{ url('/otp') }}/"+data.otp_token;
                  }
                });

              } else {
                  swal("Some Thing Wrong! Please Try Again");
                  return false;

              }
              // here we will handle errors and validation messages
          }).error(function(jqXHR, textStatus, errorThrown) {
            $('#register').removeAttr('disabled');
            $("#register").text("SUBSCRIBE");
              if(jqXHR.status == 429)
              {
                swal(jqXHR.responseJSON.message);
                return false;
              } else {
                swal(jqXHR.responseJSON.message);
                return false;
              }
          });
        } else {
          swal('To continue, you must agree to  Terms and Conditions.');
        }

    });

Here shall i include after e.preventDefault();?

Sergiu17's avatar
$('#user_register').submit(function(e) {
	e.preventDefault();

	grecaptcha.execute()
		.then(function(token) {
			// your ajax code goes here
	});
});

something like this, and yes, you need e.preventDefault()

Deekshith's avatar

I have altered my code like below. Please confirm,

//Subscribe form submit
    $('#user_register').submit(function(e) {
      e.preventDefault();

    grecaptcha.execute()
		.then(function(token) {
        if(token) {
            document.getElementById('recaptcha').value = token;
      var agree = $('#agree_terms_checkbox').val();
      if(agree ==1) {
      var data = $(this).serialize();
      var type = 'post';
      var url = "{{ url('subscribe') }}";

      $('#register').prop("disabled",true);
      $('#register').text("Please wait..");

      // process the form
      $.ajax({
          type : type,
          url  : url,
          data : data,
          dataType : 'json', // what type of data do we expect back from the server
          encode  : true
      })
          // using the done promise callback
          .done(function(data) {
            $('#register').removeAttr('disabled');
            $("#register").text("SUBSCRIBE");

            if(data.status == 500) {

                printErrorMsg(data.info);
                return false;

            } else if(data.status == 600) {
                  swal(data.info);
                  return false;

              } else if(data.status == 200) {

                swal({
                  html :true,
                  title: "Success!",
                  text: "<strong>"+data.info+"</strong>",
                  type: "success",
                  confirmButtonText: "OK"
                },
                function(isConfirm){
                  if (isConfirm) {
                    window.location.href="{{ url('/otp') }}/"+data.otp_token;
                  }
                });

              } else {
                  swal("Some Thing Wrong! Please Try Again");
                  return false;

              }
              // here we will handle errors and validation messages
          }).error(function(jqXHR, textStatus, errorThrown) {
            $('#register').removeAttr('disabled');
            $("#register").text("SUBSCRIBE");
              if(jqXHR.status == 429)
              {
                swal(jqXHR.responseJSON.message);
                return false;
              } else {
                swal(jqXHR.responseJSON.message);
                return false;
              }
          });
        } else {
          swal('To continue, you must agree to Terms and Conditions.');
        }
            }
        });
    });

And here if user gets some form error like email already exits or you must agree to Terms and Conditions like this then also token will reset right?

Sergiu17's avatar

Looks OK to me

You have an if statement for Terms if(agree ==1) {, but for validation - yes, a new token should be generated

Deekshith's avatar

@sergiu17 and also when i use this inside ajax i get this error,

Uncaught Error: No reCAPTCHA clients exist

i have even included like below,

$('#user_register').submit(function(e) {
      e.preventDefault();
      grecaptcha.ready(function() {
        grecaptcha.execute()
		.then(function(token) {
        if(token) {
            document.getElementById('recaptcha').value = token;
	//code goes here

   }
});
});

});

But getting same error.

Sergiu17's avatar

Make sure you import recaptcha/api.js before your scripts..this should solve, and you don't need grecaptcha.ready(function() {

Deekshith's avatar

@sergiu17 i have a included script like below, before the form submit but still the same problem.

<script src="https://www.google.com/recaptcha/api.js?render={{ config('services.recaptcha.sitekey') }}"></script>
Deekshith's avatar

@sergiu17 Now i have updated my code like below,

$('#user_register').submit(function(e) {
      e.preventDefault();
      grecaptcha.ready(function() {
        grecaptcha.execute('{{ config('services.recaptcha.sitekey') }}', {action: 'subscribe'}).then(function(token) {

        if(token) {
            document.getElementById('recaptcha').value = token;
      var agree = $('#agree_terms_checkbox').val();
      console.log(document.getElementById('recaptcha').value);
      
      if(agree ==1) {
      var data = $('#user_register').serialize();
      var type = 'post';
      var url = "{{ url('subscribe') }}";

      $('#register').prop("disabled",true);
      $('#register').text("Please wait..");

      console.log(data);

      // process the form
      $.ajax({
          type : type,
          url  : url,
          data : data,
          dataType : 'json', // what type of data do we expect back from the server
          encode  : true
      })
          // using the done promise callback
          .done(function(data) {
            $('#register').removeAttr('disabled');
            $("#register").text("SUBSCRIBE");

            if(data.status == 500) {

                printErrorMsg(data.info);
                return false;

            } else if(data.status == 600) {
                  swal(data.info);
                  return false;

              } else if(data.status == 200) {

                swal({
                  html :true,
                  title: "Success!",
                  text: "<strong>"+data.info+"</strong>",
                  type: "success",
                  confirmButtonText: "OK"
                },
                function(isConfirm){
                  if (isConfirm) {
                    window.location.href="{{ url('/otp') }}/"+data.otp_token;
                  }
                });

              } else {
                  swal("Some Thing Wrong! Please Try Again");
                  return false;

              }
              // here we will handle errors and validation messages
          }).error(function(jqXHR, textStatus, errorThrown) {
            $('#register').removeAttr('disabled');
            $("#register").text("SUBSCRIBE");
              if(jqXHR.status == 429)
              {
                swal(jqXHR.responseJSON.message);
                return false;
              } else {
                swal(jqXHR.responseJSON.message);
                return false;
              }
          });
        } else {
          swal('To continue, you must agree to Insights IAS Terms and Conditions.');
        }
     }
        });
      });
    });

grecaptcha.ready(function() { i have included this and it worked and also i was using form data like below,

var data = $(this).serialize();

But it was fetching recaptcha data so i replaced like below,

var data = $('#user_register').serialize();

NOw i am getting data like below,

{#1293
  +"success": true
  +"challenge_ts": "2021-02-05T08:07:29Z"
  +"hostname": "www.website.com"
  +"score": 0.9
  +"action": "subscribe"
}

This is correct right?

Sergiu17's avatar

I think yes, it should also work without grecaptcha.ready(function() {, but never mind

Please or to participate in this conversation.