19

From the documentation I understood that in order to change the language of the recaptcha I have to render it explicitly.

The problem is, however, that it's not really showing up, and the onload is not even called.
When I try to render it automatically it does work.

Here's the code:
In the HTML head: (I have also tried putting this at the end of the body tag)

<script src="https://www.google.com/recaptcha/api.js?onload=recaptchaCallback&render=explicit&hl=iw" async defer></script>

In the HTML form:

<div id="recaptcha"></div>

Javascript:

var recaptchaCallback = function() {
  console.log('recaptcha is ready'); // not showing
  grecaptcha.render("recaptcha", {
    sitekey: 'My Site Key',
    callback: function() {
      console.log('recaptcha callback');
    }
  });
}
8
  • You might want to check your <script> tag in your HEAD - you can't call the onload method like that - it needs to go somewhere else, like in your <BODY> tag.
    – Raad
    Commented May 15, 2015 at 14:39
  • recaptchaCallback gets defined but when does it get called?
    – Alex
    Commented May 15, 2015 at 14:39
  • @Raad Thanks for the quick comment, I forgot to mention that I also tried putting the script in the end of the body tag.
    – Gofilord
    Commented May 15, 2015 at 14:41
  • @Alex According to the docs, the onload parameter in the script URL should state the name of the callback function.
    – Gofilord
    Commented May 15, 2015 at 14:43
  • You need to load the .../recaptcha/api.js script using the <SCRIPT> tag, but call the recaptchaCallback function using the onload property of the <BODY> tag, so it's a 2-part implementation.
    – Raad
    Commented May 15, 2015 at 14:43

5 Answers 5

19

I just copied your code, used my own Site Key and it works.

The code I used is:

<html>
  <body>
    <p>ReCaptcha Test</p>

    <div id="recaptcha"></div>

    <script src="https://www.google.com/recaptcha/api.js?onload=recaptchaCallback&render=explicit&hl=iw" async defer></script>

    <script type="text/javascript">
      var recaptchaCallback = function () {
        console.log('recaptcha is ready'); // showing
        grecaptcha.render("recaptcha", {
            sitekey: 'SITE_KEY',
            callback: function () {
                console.log('recaptcha callback');
            }
        });
      }
    </script>

  </body>
</html>

Check your code carefully, as just a single character typo can stop things from working.

5
  • Thanks for the answer. I copied everything again from your code this time and it still doesn't work. I have checked the site key a lot and reordered the scripts but still nothing. If there was an error I would have probably gotten an error, but I just get nothing.
    – Gofilord
    Commented May 19, 2015 at 6:42
  • @Gofilord - this sounds like a different issue - e.g. it may be a problem loading the recaptcha scripts from Google. Use your browser's developer mode and check what is happening to the requests in your browser - look for any errors in the console or the network tab.
    – Raad
    Commented May 19, 2015 at 12:01
  • It's really weird but I tried it this morning, without changing a single thing, and it worked. Thanks for your time.
    – Gofilord
    Commented May 20, 2015 at 6:22
  • @Gofilord - glad you got there in the end!
    – Raad
    Commented May 20, 2015 at 8:59
  • @Gofilord one cause of this is when the bandwidth is low. Suppose you've 1MB/s for downloads and you're downloading a file at the same time you're loading the recaptcha it fails sometimes
    – vcRobe
    Commented Nov 20, 2017 at 21:43
17

Make sure that your onload method is defined before the recaptcha script. Otherwise you will have a race condition where the recaptcha script could be attempting to call your method before it is defined (especially if the recaptcha script is cached).

From the documentation for onload https://developers.google.com/recaptcha/docs/display

Note: your onload callback function must be defined before the reCAPTCHA API loads. To ensure there are no race conditions:

  • order your scripts with the callback first, and then reCAPTCHA
  • use the async and defer parameters in the script tags

For example:

<div id="recaptcha"></div>


<script type="text/javascript">
  var recaptchaCallback = function () {
    console.log('recaptcha is ready'); // not showing
    grecaptcha.render("recaptcha", {
        sitekey: 'SITE_KEY',
        callback: function () {
            console.log('recaptcha callback');
        }
    });
  }
</script>

<script src="https://www.google.com/recaptcha/api.js?onload=recaptchaCallback&render=explicit&hl=iw" async defer></script>
0
0

My problem was that I did not realise that the second callback is only fired upon submission of the form - whereas the first callback is executed on page load.

0

HTML

<div id="captcha"></div>
<script src='https://www.google.com/recaptcha/api.js?onload=recaptchaReadycallback&render=explicit' async defer'></script>

JavaScript

// Render captcha and set call back function on api.js load finish
function recaptchaReadycallback(){
 grecaptcha.render('captcha', {
    'callback' : recaptchaCheckedCallback,
    'expired-callback': recaptchaExpiredCallback,
    'sitekey': 'YOUR-SITE-KEY'

  });
}

// On expiry do stuff. E.g. show error
function recaptchaExpiredCallback(){
   grecaptcha.reset();
   // Show 'check the bloody box' error
};

// On not a robot confirmation do stuff. E.g. hide error
function recaptchaCheckedCallback(){
   // Hide 'check the bloody box' error
}
0
@model TestCaptcha.Models.Login
@inject IConfiguration configuration

@{
    var sitekey = configuration["ReCaptchaSetting:SiteKey"];
    ViewData["Title"] = "Login";
}

<h1>Login</h1>
<hr />
<div class="row">
    <div class="col-md-4">
        <form asp-action="Login" onsubmit="onSubmit(event)">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <div class="form-group">
                <label asp-for="Email" class="control-label"></label>
                <input asp-for="Email" class="form-control" />
                <span asp-validation-for="Email" class="text-danger"></span>
                <input type="text" asp-for="RecaptchaToken" id="recaptchaTokenId" class="form-control" />
            </div>
            <div class="form-group">
                <label asp-for="Password" class="control-label"></label>
                <input asp-for="Password" class="form-control" />
                <span asp-validation-for="Password" class="text-danger"></span>
            </div>
            <div class="form-group form-check">
                <label class="form-check-label">
                    <input class="form-check-input" asp-for="RememberMe" /> @Html.DisplayNameFor(model => model.RememberMe)
                </label>
            </div>
            <div id="html_element" ></div>

            <div class="form-group">
                <input type="submit" value="Create" class="btn btn-primary" />
            </div>
        </form>
    </div>
</div>

<div>
    <a asp-action="Index">Back to List</a>
</div>

@section Scripts {
    <script>
        var onloadCallback = function () {
            console.log('recaptcha is ready'); // Runs Automatically
            grecaptcha.render('html_element', {
                'sitekey': '@sitekey'
            });
        }
        function onSubmit(event) {
            var token = grecaptcha.getResponse();
            document.getElementById("recaptchaTokenId").value = token;
        }
    </script>
    <script src="https://www.google.com/recaptcha/api.js?onload=onloadCallback&render=explicit"
            async defer>
    </script>
    @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
1
  • 1
    Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.
    – Community Bot
    Commented 2 days ago

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