60

I'm using Google reCAPTCHA and have been able to add the CAPTCHA component to my page inside a form. But when I submit the form there's no validation taking place to check if the CAPTCHA has been solved.

How do I validate that the CAPTCHA component has been solved when submitting my form? Or, in other words, how do I make my CAPTCHA component required?

3
  • 1
    Sorry gpullen but i want to do reCAPTCHA as required field in the form. Dec 30, 2014 at 14:02
  • 2
    Try this link - How to Ask. Dec 31, 2014 at 20:55
  • Posting your code along with a link to the relevant Google product page would be far more useful to everyone than posting an animated gif. Thanks.
    – Sparky
    Dec 31, 2014 at 21:05

8 Answers 8

103

if you want to use the native html5 popups, than here is the solution

JavaScript:

window.addEventListener('load', () => {
  const $recaptcha = document.querySelector('#g-recaptcha-response');
  if ($recaptcha) {
    $recaptcha.setAttribute('required', 'required');
  }
})

CSS:

#g-recaptcha-response {
  display: block !important;
  position: absolute;
  margin: -78px 0 0 0 !important;
  width: 302px !important;
  height: 76px !important;
  z-index: -999999;
  opacity: 0;
}
10
  • 1
    I like this approach but get an error "An invalid form control with name='g-recaptcha-response' is not focusable."
    – timkado
    Aug 17, 2018 at 13:52
  • @timkado Do you have a Codepen for me?
    – Fred
    Aug 19, 2018 at 13:03
  • 1
    Hi Fred - this is very strange. I copied your code and I am still getting the same error: An invalid form control with name='g-recaptcha-response' is not focusable.
    – timkado
    Aug 20, 2018 at 15:34
  • 4
    It worked well for me. There happened the same error @timkado met but was removed after adding the given CSS style. It's because the target Textarea has "display: none;" by default. Thanks, @Fred!
    – iconique
    Oct 3, 2020 at 6:03
  • 3
    So close, but if the captcha expires, this doesn't catch it. Feb 9, 2021 at 2:13
21

I had the same problem as yours and solved it this way:

First declare a variable that stores 1 or 0 depending or whether the user filled the capcha correctly.

var allowSubmit = false;

Then you need a function which gets executed when the user fills the reCapcha correctly:

function capcha_filled () {
    allowSubmit = true;
}

... and a function that gets executed when the reCapcha session expires:

function capcha_expired () {
    allowSubmit = false;
}

To tell reCapcha about your functions (callbacks), set those data-attributes in your html:

<div class="g-recaptcha"
   data-callback="capcha_filled"
   data-expired-callback="capcha_expired"
   data-sitekey="your site key"></div>

Or if you use explicit load:

  var onloadCallback = function() {
    grecaptcha.render('your_div_id', {
      'sitekey' : 'your_site_key',
      'callback': capcha_filled,
      'expired-callback': capcha_expired,
    });
  };

You need also a callback for the form submission:

function check_if_capcha_is_filled (e) {
    if(allowSubmit) return true;
    e.preventDefault();
    alert('Fill in the capcha!');
}

Finally add in the form the onsubmit attribute:

<form action="..." onsubmit="check_if_capcha_is_filled">

Note: as mentioned in the comments, a server validation is still needed. The code prevents accidentally submitting the form unless the capcha is filled and is only for user's convenience.

3
  • What's to stop me from entering a javascript console and just setting submit = true myself? May 19, 2016 at 13:11
  • 1
    @IanMacDonald Absolutely nothing. It's (my answer) just for user's convenience. The idea is to prevent them from accidentally submitting the form (e.g. pressing enter on an <input>) without having filled the capcha. Just saving a page reload for better user experience.
    – Al.G.
    May 19, 2016 at 18:54
  • Oh, I got your point now. I should have explicitly mentioned that a server check is still required. Thanks for the note.
    – Al.G.
    May 19, 2016 at 18:55
17

I found this to be a quick & easy way to do it. Add this to your headers:

<script>
window.onload = function() {
  var recaptcha = document.forms["myForm"]["g-recaptcha-response"];
  recaptcha.required = true;
  recaptcha.oninvalid = function(e) {
    // do something
    alert("Please complete the captcha");
  }
}
</script>

This only works in HTML5, and is (or should be) supported by these browsers: http://caniuse.com/#feat=form-validation

(The JS console in Chrome shows this error message: "Invalid form control" only in Google Chrome , and I haven't been able to work around this. Hopefully someone else will improve this response.)

1
  • This works when you test manually. But will this work if the form will be submitted by a bot? :D It might not.
    – Larstton
    Aug 5, 2023 at 13:12
12

I checked for existance of #g-recaptcha-response:

function checkRecaptcha() {
    res = $('#g-recaptcha-response').val();

    if (res == "" || res == undefined || res.length == 0)
        return false;
    else
        return true;
}

//...

$('#frm-signup').submit(function(e) {

    if(!checkRecaptcha()) {
        $( "#frm-result" ).text("Please validate your reCAPTCHA.");
        return false;
    }
    //...
});

This really should be part of the docs...

5

Working solution in 2022

Personally, I was not able to get any of the above solutions to work with my captcha. So I figured I would share my current working solution for those facing the same issue.

The accepted answer doesn't have a validation technique for when the captcha expires, the below solution addresses that.

My notes in the .js should explain the solution thoroughly.

JavaScript

// By default do not allow form submission.
var allow_submit = false

function captcha_filled () {
    /*
     * This is called when Google get's the recaptcha response and approves it.
     * Setting allow_submit = true will let the form POST as normal.
     * */

    allow_submit = true
}

function captcha_expired () {
    /*
     * This is called when Google determines too much time has passed and expires the approval.
     * Setting allow_submit = false will prevent the form from being submitted.
     * */

    allow_submit = false
}


function check_captcha_filled (e) {
    console.log('captcha-verified')
    /*
     * This will be called when the form is submitted.
     * If Google determines the captcha is OK, it will have
     * called captcha_filled which sets allow_submit = true
     * If the captcha has not been filled out, allow_submit
     * will still be false.
     * We check allow_submit and prevent the form from being submitted
     * if the value of allow_submit is false.
     * */

    // If captcha_filled has not been called, allow_submit will be false.
    // In this case, we want to prevent the form from being submitted.
    if (!allow_submit) {
        // This call prevents the form submission.
        // e.preventDefault()

        // This alert is temporary - you should replace it with whatever you want
        // to do if the captcha has not been filled out.
        alert('ERROR: Please verify you are human by filling out the captcha')

        return false
    }
    captcha_expired()
    return true
}

HTML

<form action="post" onsubmit="return check_captcha_filled()">
<!-- form items -->
<div class="g-recaptcha"
   data-callback="captcha_filled"
   data-expired-callback="captcha_expired"
   data-sitekey="your site key">
</div>
</form>
2
  • That may be the case, becuase this question was little old, as Captcha library changes we may need to update the jQuery according that. Apr 28, 2022 at 18:13
  • @BaikareSandip I'm unsure if I follow. There is no jQuery in the solution.
    – Kameron
    Apr 28, 2022 at 18:22
2

If you want a more friendly and descriptive message, you can add a required checkbox. This will ensure the html5 popup shows something like: "Please check this box if you want to proceed"

<div class="captcha">
   <div class="g-recaptcha" data-sitekey="Your Site Key" data-callback="removeFakeCaptcha"></div>
   <input type="checkbox" class="captcha-fake-field" tabindex="-1" required>
</div>

Add the code to remove the fake captcha once completed

window.removeFakeCaptcha = function() {
   document.querySelector('.captcha-fake-field').remove();
}

Then on the css you hide the checkbox and position it to the captcha box:

.captcha {
  position: relative;
}
.captcha-fake-field {
  background: transparent;
  bottom: 0;
  border: none;
  display: block;
  height: 1px;
  left: 12px;
  width: 1px;
  position: absolute;
  z-index: -1;
}
1
  • it's not working properly. Can you help me
    – Anny
    May 12, 2023 at 8:56
0

Not sure if you already solved this, but you could use an addon to validate the Google recaptcha: http://formvalidation.io/addons/recaptcha2/

1
  • page not found. Please try to put answer instead of links
    – Anny
    May 12, 2023 at 8:16
0

I find this very helpful:

<div class="g-recaptcha myPopover" data-sitekey="Your Key" 
        data-callback="recaptchaCallback">

You add a function to data-callback="recaptchaCallback" with this code:

var recaptchachecked=false; 
function recaptchaCallback() {
    recaptchachecked = true;
}

and a function were you return the value to use it in a other html-tag like this:

<form method="post" onsubmit="return isreCaptchaChecked()">
function isreCaptchaChecked()
{
    return recaptchachecked;
}

I hope this helps you.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.