LogoBetter Captcha

Qwik

Using better-captcha with Qwik

Installation

npm i @better-captcha/qwik

Basic Usage

import { component$ } from "@builder.io/qwik";
import { ReCaptcha } from "@better-captcha/qwik/provider/recaptcha";

export default component$(() => {
  return <ReCaptcha sitekey="your-site-key" />;
});

Imperative Handle

Qwik uses the useCaptchaController hook to access the imperative handle via a controller pattern that works with Qwik's serialization model.

import { component$ } from "@builder.io/qwik";
import { useCaptchaController } from "@better-captcha/qwik";
import { ReCaptcha, type ReCaptchaHandle } from "@better-captcha/qwik/provider/recaptcha";

export default component$(() => {
  const controller = useCaptchaController<ReCaptchaHandle>();

  return (
    <>
      <ReCaptcha 
        sitekey="6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI" 
        controller={controller}
      />
      <button onClick$={() => controller.value?.execute()}>Execute</button>
      <button onClick$={() => controller.value?.reset()}>Reset</button>
      <button onClick$={() => console.log(controller.value?.getResponse())}>Log response</button>
    </>
  );
});

The handle is available once the widget is ready. Always use optional chaining (?.) when calling methods since the controller may not be initialized yet.

Lifecycle Callbacks

All captcha components support three lifecycle callbacks via QRL props. Note the $ suffix required by Qwik for serializable functions.

import { component$, $ } from "@builder.io/qwik";
import { useCaptchaController } from "@better-captcha/qwik";
import { ReCaptcha, type ReCaptchaHandle } from "@better-captcha/qwik/provider/recaptcha";

export default component$(() => {
  const controller = useCaptchaController<ReCaptchaHandle>();

  const handleReady$ = $((handle: ReCaptchaHandle) => {
    console.log("Captcha is ready", handle);
  });

  const handleSolve$ = $((token: string) => {
    console.log("Captcha solved with token:", token);
    // Send token to your backend for verification
  });

  const handleError$ = $((error: Error) => {
    console.error("Captcha error:", error);
  });

  return (
    <ReCaptcha
      sitekey="6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI"
      controller={controller}
      onReady$={handleReady$}
      onSolve$={handleSolve$}
      onError$={handleError$}
    />
  );
});
CallbackParametersDescription
onReady$(handle: Handle) => voidCalled when the widget is rendered and ready (receives handle)
onSolve$(token: string) => voidCalled when the challenge is solved with the response token
onError$(error: Error) => voidCalled when an error occurs during initialization or solving

Manual Rendering

By default, captchas automatically render on mount. For more control, disable auto-rendering and trigger it manually.

import { component$ } from "@builder.io/qwik";
import { useCaptchaController } from "@better-captcha/qwik";
import { ReCaptcha } from "@better-captcha/qwik/provider/recaptcha";

export default component$(() => {
  const controller = useCaptchaController();

  return (
    <>
      <ReCaptcha 
        sitekey="6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI" 
        controller={controller} 
        autoRender={false} 
      />
      <button onClick$={async () => await controller.value?.render()}>Show Captcha</button>
    </>
  );
});

Common Props

PropTypeRequiredDescription
sitekeystringYour provider's site key
controllerSignalController from useCaptchaController() for imperative access
optionsobjectProvider-specific configuration options
autoRenderbooleanWhether to render automatically on mount (default: true)
scriptOptionsobjectScript loading configuration (see Script Options)
onReady$QRLCallback when widget is ready
onSolve$QRLCallback when challenge is solved
onError$QRLCallback when an error occurs

Handle Methods

All providers implement these methods on the handle:

Prop

Type

Available Providers

ProviderImport Path
ReCaptcha@better-captcha/qwik/provider/recaptcha
HCaptcha@better-captcha/qwik/provider/hcaptcha
Turnstile@better-captcha/qwik/provider/turnstile
Friendly Captcha@better-captcha/qwik/provider/friendly-captcha
Private Captcha@better-captcha/qwik/provider/private-captcha
Captcha Fox@better-captcha/qwik/provider/captcha-fox
Prosopo@better-captcha/qwik/provider/prosopo
CapWidget@better-captcha/qwik/provider/cap-widget

See the Provider Documentation for provider-specific options and configuration.

On this page