I am needing to add a reCaptcha test in a Lightning community, but with the locker service the script has to be loaded from a static resource rather than directly from the Google website... but is that going to break it?


4 Answers 4


Serve reCaptcha's api.js file locally (as a javascript static resource) does prevent correct behavior.

api.js has a magic url in it that changes periodically, so it does need to be either updated very frequently or served from google's servers.

Source: https://stackoverflow.com/questions/27613461/is-serving-google-no-captcha-recaptchas-api-js-locally-preventing-correct-behav

  • 1
    Spent couple of days on that, and there are only bad solutions on how to do that in Lightning unfortunately... 1- A static resource will break at any time... 2- An iFrame (through a VF page), albeit complicated, will fail to be properly responsive, when for example, the captcha changes from simply clicking a checkbox to selecting images which make the UX terrible Another terrible Lightning limitation. Jun 28, 2018 at 15:20

From Linked Answer:

The solution to this can be built by using two guides which Salesforce provides

  1. Adding CAPTCHA to force.com sites link here (https://developer.salesforce.com/page/Adding_CAPTCHA_to_Force.com_Sites). This document explains how to implement CAPTCHA in a visual force page.
  2. Embedding a VF page in a Lightning component. Link here (https://developer.salesforce.com/blogs/developer-relations/2017/01/lightning-visualforce-communication.html). This document explains how to embed a VF page in Lightning component and how to communicate between the two.

The soution at a very high level is as follows:

  1. Implement CAPTCHA in a VF page as per above guide.
  2. Disable sidebar and header of the VF page
  3. Enable the VF page for all profiles and add it to your site (to enable for guest user). This makes the VF page public.
  4. Embed the VF page in your lightning component within an iframe as per guide above.
  5. Make the iframe borderless.
  6. Communicate status between the VF page and Lightning component through parent.postMessage javascript API.
  7. When VF page indicates to the Lightning component that CAPTCHA has been verified, fire an Application event from your lightning component to announce that user has completed CAPTCHA and take action accordingly in same/other components.
  • 2
    Can you also add few details on solution specified in the link.
    – Reshma
    Feb 27, 2017 at 12:15

Indeed this can be done by creating a VisualForce page containing the captcha script and embedding the VF page in an IFrame in your lightning component.

A great example by Varasi can be found here: http://varasi.com/salesforce/embedding-google-recaptcha-v2-in-salesforce-lightning-component-to-increase-security/

  • This is a dead link now. Feb 18, 2022 at 23:15
  • Thanks for letting me know! I replaced it by a working link (to the same solution) Feb 19, 2022 at 13:07

You can take advantage of JavaScript events and Head Markup to achieve this without needing a VisualForce iframe: https://www.learncommunitycloud.com/s/article/Implementing-reCAPTCHA-in-Community-Cloud

An example for v2 Invisible from the above link:

Head Markup

<!--reCaptcha v2 Invisible-->
    var verifyCallback = function(token) {
        document.dispatchEvent(new CustomEvent('grecaptchaVerified', {'detail': {response: token }}));
    var errorCallback = function() {
        document.dispatchEvent(new Event('grecaptchaError'));
    document.addEventListener('grecaptchaRender', function(e) {   
        grecaptcha.render(e.detail.element, {
            'sitekey': 'reCAPTCHA_site_key',
            'callback': verifyCallback,
            'error-callback': errorCallback,
            'size': 'invisible',
            'badge': e.detail.hasOwnProperty('badge') ? e.detail.badge : 'bottomright'
    document.addEventListener('grecaptchaReset', function() {
    document.addEventListener('grecaptchaExecute', function() {
<script src='https://www.google.com/recaptcha/api.js?render=explicit' async defer></script>

Aura component

<aura:component controller="RecaptchaDemo" implements="forceCommunity:availableForAllPageTypes" access="global" >
    <aura:handler name="init" value="{!this}" action="{!c.onInit}" />
    <aura:handler name="render" value="{!this}" action="{!c.onRender}" />

    <h2>v2Invisible Demo</h2>
    <br />
    <div id="recaptchaInvisible"></div>
    <br />
    <lightning:button aura:id="myButton" label="Submit" onclick="{!c.doSubmit}" />


    onInit: function (component, event, helper){ 
        document.addEventListener("grecaptchaVerified", function(e) {
            var action = component.get("c.insertRecord");
                record: null, //TODO: map UI fields to sobject
                recaptchaResponse: e.detail.response

            action.setCallback(this, function(response) {         
                document.dispatchEvent(new Event("grecaptchaReset"));
                var state = response.getState();
                if (state === "SUCCESS") {
                    var result = response.getReturnValue();
                } else {
                    var errors = response.getError();
                    if (errors) {

    onRender: function (component, event, helper){ 
        //valide values for badge: bottomright bottomleft inline
        var payload = {element: 'recaptchaInvisible',badge: 'bottomright'};
        document.dispatchEvent(new CustomEvent("grecaptchaRender", {"detail": payload}));
    doSubmit: function (component, event, helper){
        document.dispatchEvent(new Event("grecaptchaExecute"));

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .