# \[Marketplace\] Cloudflare Turnstile Widget

**URL:** <https://community.weweb.io/t/marketplace-cloudflare-turnstile-widget/10731>\
**Category:** Tutorials\
**Tags:** supabase, captcha, turnstile, cloudflare, recaptcha\
**Created:** [September 10, 2024, 7:22am UTC](https://community.weweb.io/t/marketplace-cloudflare-turnstile-widget/10731 "2024-09-10T07:22:36Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![Broberto](https://sea2.discourse-cdn.com/flex016/user_avatar/community.weweb.io/broberto/32/5918_2.png) [@Broberto](https://community.weweb.io/u/Broberto)\
**Post date:** [September 10, 2024, 7:22am UTC](https://community.weweb.io/t/marketplace-cloudflare-turnstile-widget/10731/1 "2024-09-10T07:22:36Z")

</div>

Hello everyone, I saw that implementing any type of Captcha in WeWeb is quite a challenge for y’all. I’ve worked on this for one of my partners recently and decided to share it with you all actually.

I’ve just released a Marketplace Custom Coded Element that solves this once for all. You can now import Cloudflare Turnstile simply by dragging and dropping the widget to your WeWeb project (and of course setting your token). It also has a possibility to:

 ![Screenshot 2024-09-09 at 19.46.31](https://us1.discourse-cdn.com/flex016/uploads/weweb/original/2X/1/1c88afd1b0f926d79a88abaf967b0f8d92539638.png)

- Refresh the widget - this removes and adds a new widget, effectively generating a new captcha via the Execute component action → Re-render Turnstile
- Change language - you can select any of the many languages that are available by Cloudflare (such as Farsi, Chinese, Bulgarian etc. there is really many)
- Change the theme - Light mode, Dark mode, or Automatic selection of the theme

It exposes the token as a variable so you can bind it in WeWeb without all the work to even get it into WeWeb.

 ![Screenshot 2024-09-10 at 09.16.36](https://us1.discourse-cdn.com/flex016/uploads/weweb/original/2X/6/6d15c06772721e60f1ad5e46b0c232c111853b45.png)

You can find the widget in the marketplace, there also is an interactive demo.  
[https://marketplace.weweb.io/libraries/d318f23f-789f-4229-9460-8d547cfa9f07/](https://marketplace.weweb.io/libraries/d318f23f-789f-4229-9460-8d547cfa9f07/)

---

<div class="post-metadata">

**Author:** ![dorilama](https://sea2.discourse-cdn.com/flex016/user_avatar/community.weweb.io/dorilama/32/10403_2.png) [@dorilama](https://community.weweb.io/u/dorilama)\
**Post date:** [September 10, 2024, 10:09am UTC](https://community.weweb.io/t/marketplace-cloudflare-turnstile-widget/10731/2 "2024-09-10T10:09:37Z")

</div>

Congratulations for publishing the component! 🎉  
Some feedback (I hope it can be useful):

- `[Brotilities Turnstile]` logs can be debug level logs to allow easy filtering in the dev tools
- a global property to disable every log is useful if you don’t want to show logs in the published app, make it bindable so you can easily keep logs for dev and staging)
- since you are opting for explicitly rendering the widget you may want to disable [implicit rendering](https://developers.cloudflare.com/turnstile/get-started/client-side-rendering/#implicitly-render-the-turnstile-widget) by appending the parameter `render=explicit` to the script url
- not sure if it is intentional, but there is an error because the script is loaded with instructions to run a callback (`_turnstileCb`) that doesn’t exists in the global scope

---

<div class="post-metadata">

**Author:** ![Broberto](https://sea2.discourse-cdn.com/flex016/user_avatar/community.weweb.io/broberto/32/5918_2.png) [@Broberto](https://community.weweb.io/u/Broberto)\
**Post date:** [September 10, 2024, 10:49am UTC](https://community.weweb.io/t/marketplace-cloudflare-turnstile-widget/10731/3 "2024-09-10T10:49:34Z")

</div>

Thanks for the feedback, I pushed the Debug property, but i haven’t re-published 😃 So yeah, fixed but not. As for the other two, they’re actually connected, in the docs, if you have a look, the explicitly loading can happen with a callback only in the string, which was the approach I went for before anything else. It didn’t work, but I forgot to swap it for the render = explicit indeed. Great catch 🙂 I for some reason didn’t see the error at first. Will be fixed in a few, thanks again, useful as usually 🙂

---

<div class="post-metadata">

**Author:** ![Vaclav](https://avatars.discourse-cdn.com/v4/letter/v/34f0e0/32.png) [@Vaclav](https://community.weweb.io/u/Vaclav)\
**Post date:** [July 22, 2025, 3:52pm UTC](https://community.weweb.io/t/marketplace-cloudflare-turnstile-widget/10731/4 "2025-07-22T15:52:46Z")

</div>

Hi Broberto,

This is a great component that has made my work much easier, but I’m running into a few problems with its implementation. It’s probably more of a problem with the Supabase Auth plugin from WeWeb, and I’m sure you’ve encountered it too, so I just want to make sure I’ve chosen the right approach.

When a user wants to resend the OTP code to verify their email, if I select the action from the plugin, I get an error saying that I didn’t enter the captcha “captcha verification process failed”, which this action doesn’t even allow me to do, or rather, there is nowhere to enter the captcha token - I managed to get around this by re-registering the user = they get the OTP code again.

But I ran into a problem with “forgot password” and “change password”—is the solution to use the Rest API? Is it as simple to implement as when I call the Supabase function using the Rest API, or is there something I need to watch out for?

Thank you in advance for your response.

---

<div class="post-metadata">

**Author:** ![Broberto](https://sea2.discourse-cdn.com/flex016/user_avatar/community.weweb.io/broberto/32/5918_2.png) [@Broberto](https://community.weweb.io/u/Broberto)\
**Post date:** [July 23, 2025, 9:09am UTC](https://community.weweb.io/t/marketplace-cloudflare-turnstile-widget/10731/5 "2025-07-23T09:09:49Z")

</div>

Hi, I can see the issue. In the Supabase plugin from WeWeb it sometimes happens, that there is bugs where you either can’t use settings that are exposed, or they aren’t exposed at all - I’ve noticed this too. As you correctly said it’s either REST API, or you could use the Supabase instance which WeWeb exposes:

```auto
// Custom JavaScript Workflow Action
// ----------------------------------------------------

const supabase = wwLib.wwPlugins.supabase.instance

// Your OTP here
const { data, error } = await supabase.auth.signInWithOtp({
  phone: '+13334445555',
  options: {
  captchaToken: [your_variable_here]
  }
})

// ----------------------------------------------------

```

For the full reference, check out Supabase Docs, [JavaScript API Reference | Supabase Docs](https://supabase.com/docs/reference/javascript/auth-signinwithotp)

---

<div class="post-metadata">

**Author:** ![Vaclav](https://avatars.discourse-cdn.com/v4/letter/v/34f0e0/32.png) [@Vaclav](https://community.weweb.io/u/Vaclav)\
**Post date:** [July 23, 2025, 10:29am UTC](https://community.weweb.io/t/marketplace-cloudflare-turnstile-widget/10731/6 "2025-07-23T10:29:58Z")

</div>

Oh, I didn’t know about the instance. It was much more convenient to implement, and it works exactly as it should. Thanks!

---

<div class="post-metadata">

**Author:** ![felix](https://avatars.discourse-cdn.com/v4/letter/f/aeb1de/32.png) [@felix](https://community.weweb.io/u/felix)\
**Post date:** [October 28, 2025, 2:56pm UTC](https://community.weweb.io/t/marketplace-cloudflare-turnstile-widget/10731/7 "2025-10-28T14:56:41Z")

</div>

Hi Broberto, it doesn’t seem like you deployed the debug property, right?

---

<div class="post-metadata">

**Author:** ![Broberto](https://sea2.discourse-cdn.com/flex016/user_avatar/community.weweb.io/broberto/32/5918_2.png) [@Broberto](https://community.weweb.io/u/Broberto)\
**Post date:** [October 28, 2025, 4:51pm UTC](https://community.weweb.io/t/marketplace-cloudflare-turnstile-widget/10731/8 "2025-10-28T16:51:22Z")

</div>

Hi, sadly I haven’t been able to update the component, because WeWeb was unable to solve (since then) to fix a bug I’m having - any update being pushed to the component doesn’t reflect in the editor. After weeks of asking for updates, I eventually gave up on asking. So the component currently comes as is, as I’m unable to work on it.

---

<div class="post-metadata">

**Author:** ![felix](https://avatars.discourse-cdn.com/v4/letter/f/aeb1de/32.png) [@felix](https://community.weweb.io/u/felix)\
**Post date:** [November 19, 2025, 1:41pm UTC](https://community.weweb.io/t/marketplace-cloudflare-turnstile-widget/10731/9 "2025-11-19T13:41:16Z")

</div>

Hi Broberto,  
We enabled Captcha with your widget, and it works great.  
But in our app, we have a page where anonymous users can interact.  
And it fails since wwLib.wwPlugins.supabaseAuth.publicInstance.auth.signInAnonymously() is now waiting for a captcha token.  
Do you have some piece of advice on how to resolve the issue (obviously we don’t want to add a captcha to an anonymous page)?

---

<div class="post-metadata">

**Author:** ![Broberto](https://sea2.discourse-cdn.com/flex016/user_avatar/community.weweb.io/broberto/32/5918_2.png) [@Broberto](https://community.weweb.io/u/Broberto)\
**Post date:** [November 19, 2025, 2:49pm UTC](https://community.weweb.io/t/marketplace-cloudflare-turnstile-widget/10731/10 "2025-11-19T14:49:27Z")

</div>

Hi, you need to either use the wwLib.wwPlugins instance to use the anonymous sign-in manually (with code) and pass in the token. There is many topics on the forum mentioning how to work around roadblocks with this pattern.

Or an another option would be to open a ticket and hope your issue is important enough for WeWeb to consider it (and fix it within a reasonable time).

Also thanks for purchasing the component and I’m glad it works for you 🙂

---

<div class="post-metadata">

**Author:** ![felix](https://avatars.discourse-cdn.com/v4/letter/f/aeb1de/32.png) [@felix](https://community.weweb.io/u/felix)\
**Post date:** [November 19, 2025, 5:22pm UTC](https://community.weweb.io/t/marketplace-cloudflare-turnstile-widget/10731/11 "2025-11-19T17:22:06Z")

</div>

To my knowledge, the signInAnonymously() function doesn’t take the captcha token as a parameter.

---

<div class="post-metadata">

**Author:** ![Broberto](https://sea2.discourse-cdn.com/flex016/user_avatar/community.weweb.io/broberto/32/5918_2.png) [@Broberto](https://community.weweb.io/u/Broberto)\
**Post date:** [November 19, 2025, 7:37pm UTC](https://community.weweb.io/t/marketplace-cloudflare-turnstile-widget/10731/12 "2025-11-19T19:37:28Z")

</div>

![Screenshot 2025-11-19 at 20.35.52](https://us1.discourse-cdn.com/flex016/uploads/weweb/original/2X/9/95b1a3f450139b247a56eac0fcbc1b91df4bd058.png)  
It might not in WeWeb, because it’s not implemented. But the [underlying library definitely does.](https://supabase.com/docs/reference/javascript/auth-signinanonymously) Or at least the latest version of it. That also might be a culprit, an outdated version of Supabase wouldn’t be a new thing in the WeWeb’s plugin, I also had to wait like a month+ for them to roll it out with the new version when I needed it last time 🙂

---

<div class="post-metadata">

**Author:** ![felix](https://avatars.discourse-cdn.com/v4/letter/f/aeb1de/32.png) [@felix](https://community.weweb.io/u/felix)\
**Post date:** [November 20, 2025, 9:37am UTC](https://community.weweb.io/t/marketplace-cloudflare-turnstile-widget/10731/13 "2025-11-20T09:37:11Z")

</div>

Thanks Broberto, it works fine with:  
const { data, error } = await wwLib.wwPlugins.supabaseAuth.publicInstance.auth.signInAnonymously({options: {captchaToken: your\_token || undefined}});

---

<div class="post-metadata">

**Author:** ![Broberto](https://sea2.discourse-cdn.com/flex016/user_avatar/community.weweb.io/broberto/32/5918_2.png) [@Broberto](https://community.weweb.io/u/Broberto)\
**Post date:** [November 20, 2025, 1:41pm UTC](https://community.weweb.io/t/marketplace-cloudflare-turnstile-widget/10731/14 "2025-11-20T13:41:25Z")

</div>

Amazing! Glad to see you did it 🙏🔥
