Note:
I have used Google reCAPTCHA v2 Checkbox in the below implementation.
1. Navigate https://www.google.com/recaptcha.
2. Click on the “V3 Admin console” button.
3. Click the ‘+’ create icon.
4. Enter a Label and select reCAPTCHA v2 Checkbox.
5. Add your Experience Cloud domain.

6. Accept the terms of service and click the Submit button.
7. Get the Site Key and Secret Key.
8. Create Remote Site Settings in Salesforce for https://www.google.com.

9. In the Experience Site Builder, update and add the CSPs.

10. Add the following code in the Head Markup.
<!--reCaptcha v2 Checkbox-->
<script>
var grecaptchaReady = false;
var onloadCallback = function(){ grecaptchaReady = true; };
var verifyCallback = function(token) {
document.dispatchEvent(new CustomEvent('grecaptchaVerified', {'detail': {response: token}}));
};
var expireCallback = function() {
document.dispatchEvent(new Event('grecaptchaExpired'));
};
var errorCallback = function() {
document.dispatchEvent(new Event('grecaptchaError'));
};
document.addEventListener('grecaptchaRender', function(e) {
onloadCallback = function() {
grecaptchaReady = true;
grecaptcha.render(e.detail.element, {
'sitekey': '<Add your Site Key>',
'callback': verifyCallback,
'expired-callback': expireCallback,
'error-callback': errorCallback
});
};
if (grecaptchaReady) {
onloadCallback();
}
});
document.addEventListener('grecaptchaReset', function() {
grecaptcha.reset();
});
</script>
<script src='https://www.google.com/recaptcha/api.js?render=explicit&onload=onloadCallback' async defer></script>
Sample Code:
Apex:
public with sharing class RecaptchaController {
private static String recaptchaSecretKey = '<Add Your Secret Key Here>';
@AuraEnabled
public static String insertRecord( SObject record, String recaptchaResponse ) {
Http http = new Http();
HttpRequest request = new HttpRequest();
request.setEndpoint('https://www.google.com/recaptcha/api/siteverify' );
request.setMethod( 'POST');
request.setBody( 'secret=' + recaptchaSecretKey + '&response=' + recaptchaResponse );
HttpResponse response = http.send( request );
if ( response.getStatusCode() == 200 ) {
System.debug( 'Response Body is ' + response.getBody() );
Map < String, Object > result = ( Map< String, Object > ) JSON.deserializeUntyped( response.getBody() );
if ( result.containsKey( 'success' ) && result.get( 'success' ) == true) {
if ( result.containsKey( 'score' ) ) {
String action = ( String )result.get( 'action' );
Decimal threshold = .4;
Decimal score = ( Decimal )result.get( 'score' );
if ( score > threshold ) {
insert record;
return 'Success - v3';
}
} else {
insert record;
return 'Success - v2';
}
} else {
return 'Invalid Verification';
}
}
return 'Invalid Verification Request';
}
}
Aura Component:
<aura:component controller="RecaptchaController" implements="forceCommunity:availableForAllPageTypes" access="global" >
<aura:handler name="init" value="{!this}" action="{!c.onInit}" />
<aura:handler name="render" value="{!this}" action="{!c.onRender}" />
<aura:attribute name="recaptchaResponse" type="String" />
<lightning:recordEditForm aura:id="recordEditForm" objectApiName="Lead" onsubmit="{!c.doSubmit}">
<lightning:messages />
<lightning:inputField fieldName="FirstName" />
<lightning:inputField fieldName="LastName" />
<lightning:inputField fieldName="Email" />
<lightning:inputField fieldName="Phone" />
<lightning:inputField fieldName="Company" />
<div id="recaptchaCheckbox"></div>
<br/>
<lightning:button aura:id="myButton" label="Create Lead" type="submit" disabled="true" />
</lightning:recordEditForm>
</aura:component>
Aura JavaScript Controller:
({
onInit: function (component, event, helper){
document.addEventListener("grecaptchaVerified", function(e) {
component.set('v.recaptchaResponse', e.detail.response);
let myButton = component.find("myButton");
myButton.set('v.disabled', false);
});
document.addEventListener("grecaptchaExpired", function() {
let myButton = component.find( "myButton" );
myButton.set( 'v.disabled', true );
});
},
onRender: function ( component, event, helper ) {
document.dispatchEvent(new CustomEvent( "grecaptchaRender", { "detail" : { element: 'recaptchaCheckbox'} } ) );
},
doSubmit: function ( component, event, helper ) {
console.log( 'Inside Submit' );
event.preventDefault();
let fields = event.getParam( 'fields' );
fields = Object.assign( { 'sobjectType': 'Lead' }, fields );
console.log( 'Fields are ' + JSON.stringify( fields ) );
let action = component.get( "c.insertRecord" );
action.setParams( {
record: fields,
recaptchaResponse: component.get( 'v.recaptchaResponse')
} );
action.setCallback( this, function( response ) {
document.dispatchEvent(new Event( "grecaptchaReset" ) );
let myButton = component.find( "myButton" );
myButton.set( 'v.disabled', true );
let state = response.getState();
if ( state === "SUCCESS" ) {
let result = response.getReturnValue();
console.log( 'Result is ' + JSON.stringify( result ) );
if ( result.includes( 'Success' ) ) {
let showToast = $A.get( "e.force:showToast" );
showToast.setParams( {
title : 'Lead Creation',
message : 'Lead Submitted Sucessfully.' ,
type : 'success',
mode : 'dismissible'
} );
showToast.fire();
}
} else {
let errors = response.getError();
if ( errors ) {
console.log( errors[ 0 ] );
}
let showToast = $A.get( "e.force:showToast" );
showToast.setParams( {
title : 'Lead Creation',
message : 'Lead is not Submitted due to some error.' ,
type : 'error',
mode : 'dismissible'
} );
showToast.fire();
}
});
$A.enqueueAction(action);
}
})
Output:

Reference Article:
https://www.learnexperiencecloud.com/s/article/Implementing-reCAPTCHA-in-Community-Cloud