Help with server-side validation, not understanding where the pieces need to go

Before asking, did you search first? Press :mag: at the upper right to search.


I have tried a lot of different things to get this to work but I feel like I’m going in circles.

I have this is the header

<!-- reCaptcha -->
  <script src="" async defer></script>
  <script src=""></script>

and this is the button

<!-- Submit with reCAPTCHA -->
          <div class="cfcapwrap">
            <script type="text/javascript">
              window.onloadTurnstileCallback = function () {
                turnstile.render('cfcaptcha', {
                  sitekey: '0x4AAAAAAAYFWTfOh7mWLOXG',
                  callback: function(token) {
                    console.log(`Challenge Success ${token}`);

              // if using synchronous loading, will be called once the DOM is ready

            <div class="cf-turnstile cfcaptcha" id="cfcaptcha" data-sitekey="0x4AAAAAAAYFWTfOh7mWLOXG" data-callback="javascriptCallback"></div>
          <div class="submitContact">
            <button type="submit" class="submitbtn" tabindex="12"

            >Send Message!</button>



I’ve added this to the end of the page

<!-- reCAPTCHA Script -->

<script src="/js/reCAPTCHAv2.js"></script>

<script src="/js/cfCAPTCHA.js"></script>

and below is for reCAPTCHAv2.js

// This is the demo secret key. In prod, we recommend you store
// your secret key(s) safely.
const SECRET_KEY = 'My Secret Key';

async function handlePost(request) {
  const body = await request.formData();
  // Turnstile injects a token in "cf-turnstile-response".
  const token = body.get('cf-turnstile-response');
  const ip = request.headers.get('CF-Connecting-IP');

  // Validate the token by calling the "/siteverify" API.
  let formData = new FormData();
  formData.append('secret', SECRET_KEY);
  formData.append('response', token);
  formData.append('remoteip', ip);

  const result = await fetch('', {
    body: formData,
    method: 'POST',

  const outcome = await result.json();
  if (!outcome.success) {
    return new Response('The provided Turnstile token was not valid! \n' + JSON.stringify(outcome));
  // The Turnstile token was successfully validated. Proceed with your application logic.
  // Validate login, redirect user, etc.
  // For this demo, we just echo the "/siteverify" response:
  return new Response('Turnstile token successfully validated. \n' + JSON.stringify(outcome));

And below is cfCAPTCHA.js

window.onloadTurnstileCallback = function () {
  turnstile.render('#example-container', {
    sitekey: '0x4AAAAAAAYFWTfOh7mWLOXG',
    callback: function(token) {
      console.log(`Challenge Success ${token}`);

I’m completely lost. The widget appears and works. But even if the widget is still verifying or failed I can submit the form anyways.

I’m a huge noob to this so go easy on me :sweat_smile:

I’m happy to provide any additional details.

Thank you