Nawa Captcha
Open source · MIT · self-hosted

Nawa Captcha — the self-hosted, accessible puzzle CAPTCHA

An open-source reCAPTCHA, hCaptcha and Turnstile alternative with 38 puzzle types. Your own server issues the puzzle and verifies the answer — no third-party tracking, no cookies, no data leaving your app. Works with React, Vue, Svelte, Angular or plain HTML, and verifies on Node.js or ASP.NET Core.

30+puzzle types
0runtime dependencies
2languages, RTL
6themes, light & dark

A real puzzle, generated and checked in this page (demo mode).

Playground

Pick a puzzle, or mix several and see how the server chooses between them, chains them, and what ends up in the pass token.

Demo mode: challenges are generated and verified in your browser; in production your server does this.

Puzzles

Selection

Puzzles in a row
Language
Widget theme
Appearance
Page
Sound effects

Visitors can always switch it with the speaker button.

Accessible alternatives
Your configuration

Create your account

Pass token

What the browser received

Inside the sealed token (visible only in demo mode)

Event log

    Want the real thing with a Node server? Open the Express demo in StackBlitz (runs npm run demo), or clone the repository and run it locally.

    A CAPTCHA that looks like part of your product

    A layered, glass-like card with real depth: a subtle perspective tilt that follows the pointer, parallax inside the puzzle frame, pieces that lift and click into place, and a verified state that draws its own checkmark. Six themes in light and dark plus high contrast, or let it pick up your Pelagic UI tokens automatically. Motion switches off for prefers-reduced-motion, every colour pair passes WCAG 2.2 AA, and forced colours are respected.

    🔊 Optional sound

    Soft synthesized cues for grab, snap, step and success (Web Audio, no files). Off by default, never before a click or key press, with a volume slider, a remembered speaker toggle and an app-level mute. Every change is also announced to screen readers.

    🎧 Audio challenge

    For blind and low-vision visitors: a server-synthesized WAV of spoken digits (or beeps to count) over background noise, with a replay limit and no transcript. The answer stays sealed on the server like every other puzzle.

    🎨 Themes and tokens

    theme="pelagic|midnight|aurora|sand|ocean|mono", appearance="auto|light|dark|high-contrast", --nawa-captcha-* overrides, and automatic Pelagic UI --pl-* tokens (legacy --nw-* still work).

    38 puzzle types

    Every type works with mouse, touch and keyboard, and the text alternative is always one click away. The answer never reaches the browser: pictures are rendered on the server, and the solution is sealed inside the challenge token. "Blind guess" is the chance that a random answer passes one attempt; combine weak types with others (steps) or keep them for low-risk forms.

    All challenge types (use the id in types: [...])
    IdPuzzleالعربيةKindBlind guess
    sliderSlider jigsawلغز السحبDrag, slide, rotate, hold≈ 8%
    slide-unlockSlide to the targetاسحب إلى الهدفDrag, slide, rotate, hold≈ 7%
    shadow-dragDrag to the shadowاسحب إلى الظلDrag, slide, rotate, hold< 2%
    jigsawJigsaw (4 pieces)أحجية من 4 قطعDrag, slide, rotate, hold1 in 23
    rotateRotate the sceneتدوير المشهدDrag, slide, rotate, hold≈ 7%
    rotate-objectRotate the objectتدوير الشيءDrag, slide, rotate, hold≈ 7%
    rotate-matchAlign the inner circleمحاذاة الدائرة الداخليةDrag, slide, rotate, hold≈ 7%
    holdHold and releaseاضغط ثم أفلتDrag, slide, rotate, hold≈ 1 in 4
    iconsSelect matching shapesاختيار الأشكال المطابقةSelect in a picture< 1%
    icons-weatherSelect weather iconsاختيار رموز الطقسSelect in a picture< 1%
    icons-objectsSelect everyday objectsاختيار الأشياءSelect in a picture< 1%
    odd-one-outOdd one outالمختلفSelect in a picture1 in 9
    odd-rotationFind the mirrored letterالحرف المعكوسSelect in a picture1 in 6
    color-nameColour by name + patternاللون بالاسم والنقشSelect in a picture< 1%
    biggestLargest / smallestالأكبر / الأصغرSelect in a picture1 in 9
    find-shapeFind the shapeابحث عن الشكلSelect in a picture< 1%
    shadow-pickPick the shadowاختر الظلSelect in a picture1 in 6
    patternWhat comes nextما التاليSelect in a picture1 in 6
    clockRead the clockقراءة الساعةSelect in a picture1 in 6
    math-compareCompare sumsمقارنة النواتجSelect in a picture1 in 62
    symmetryComplete the mirrorأكمل التماثلSelect in a picture< 0.1%
    pairsMatch pairsمطابقة الأزواجSelect in a picture1 in 105
    tap-orderTap numbers in orderانقر الأرقام بالترتيبTap in order< 0.1%
    spellSpell the wordتهجئة الكلمةTap in order< 0.1%
    orderOrder dots / barsترتيب النقاط والأعمدةPut in order1 in 24
    order-sizeOrder by sizeالترتيب حسب الحجمPut in order1 in 24
    order-numbersOrder numbersترتيب الأعدادPut in order1 in 24
    order-timeOrder clock timesترتيب الأوقاتPut in order1 in 24
    storyPicture storyقصة مصورةPut in order1 in 6–24
    traceConnect the dotsتوصيل النقاطDraw a path< 0.1%
    trace-lettersConnect A–Eتوصيل الحروفDraw a path< 0.1%
    mazeMazeمتاهةDraw a path< 0.1%
    mathMath imageعملية حسابيةType the answer≈ 10%
    countCount the objectsعدّ الأشياءType the answer≈ 1 in 5
    diceDice totalمجموع النردType the answer≈ 1 in 6
    powInvisible proof-of-workإثبات عمل غير مرئيInvisible / accessible alternativen/a (CPU cost)
    accessibleAccessible text questionسؤال نصي ميسّرInvisible / accessible alternativemachine-readable
    audioAudio challenge (digits / beeps)تحدٍّ صوتي (أرقام / نغمات)Invisible / accessible alternative1 in 10,000 (digits) · ≈ 1 in 6 (beeps)

    Why Nawa Captcha

    🔒 The client is never trusted

    Puzzles are rendered on the server. The answer is sealed with AES-256-GCM inside the challenge and never reaches the browser.

    ✅ Verify on your backend

    A solved puzzle yields a short-lived, single-use, signed pass token. Your route verifies it locally — like reCAPTCHA's siteverify, without the third party.

    ♿ Everyone can pass it

    Mouse, touch and full keyboard for every puzzle, plus a text alternative with 50+ question templates and an audio challenge for screen-reader users (WCAG 1.1.1, 2.1.1). Arabic and English, RTL.

    🧩 30+ challenge types, your choice

    Allow one, two or many types, per action. Pick at random, in sequence or by an adaptive difficulty ladder, and chain two or three puzzles before a pass token.

    🛡️ Replay & tamper proof

    Single-use tokens, expiry, IP/UA binding, key rotation with key IDs, pointer-trajectory heuristics and rate-limit hooks.

    📦 Zero dependencies

    The Node server uses only node:crypto and node:zlib. The widget is a dependency-free Web Component that runs under a strict CSP.

    Install

    On npm. Install everything in one package, or only the parts you need. The ASP.NET Core package is not on NuGet yet: build it from the dotnet folder.

    npm, yarn, pnpm and bun all work:

    npm i nawa-captcha                # server, widget and every framework wrapper
    npm i @nawa-captcha/server @nawa-captcha/widget
    yarn add @nawa-captcha/react      # or @nawa-captcha/vue, @nawa-captcha/svelte, @nawa-captcha/angular

    Server (Express) — choose your puzzles:

    import { createNawaCaptcha } from '@nawa-captcha/server';
    import { nawaCaptchaExpress, requireCaptcha } from '@nawa-captcha/server/express';
    
    const guard = createNawaCaptcha({
      secret: process.env.NAWA_CAPTCHA_SECRET,
      types: ['slider', 'rotate-object', 'pairs', 'maze'],   // one, two or many
      mode: 'random',                                         // or 'sequence' | 'adaptive'
      perAction: { login: ['pow', 'slider'], signup: { types: ['maze', 'pairs'], steps: 2 } },
    });
    app.use('/captcha', express.json({ limit: '32kb' }), nawaCaptchaExpress(guard));
    app.post('/login', requireCaptcha(guard, { expectedAction: 'login', maxAgeSec: 300 }), handler);

    Browser (any framework) — types can only narrow the server's list:

    <nawa-captcha site-key="main" endpoint="/captcha" action="login" types="slider,rotate-object"></nawa-captcha>

    ASP.NET Core:

    builder.Services.AddNawaCaptcha(builder.Configuration.GetSection("NawaCaptcha"));
    app.MapPost("/api/contact", Handler).RequireNawaCaptcha("contact");

    Supported versions

    PartSupported versions
    Node server (nawa-captcha)Node 18 and up, zero runtime dependencies, Express adapter included
    React18 and 19
    Vue3.3 and up
    Svelte5
    Angular18 and up (standalone component and reactive forms)
    Plain HTML or any framework@nawa-captcha/widget, a Web Component with no framework needed
    ASP.NET CoreNawaCaptcha.AspNetCore on .NET 8

    Nawa Captcha vs reCAPTCHA, hCaptcha and Turnstile

    Feature comparison
    FeatureNawa CaptchareCAPTCHAhCaptchaTurnstile
    Self-hosted, no third-party callsYesNoNoNo
    No user tracking / cookiesYesNoPartialPartial
    Open source (MIT)YesNoNoNo
    You choose the puzzle typesYes (30+)NoNoNo
    Keyboard + screen-reader alternativeYes (text + audio)AudioAccessibility cookieMostly invisible
    Arabic / RTL built inYesYesYesYes
    Themes (light, dark, high contrast)6 presets + your tokensLight/darkLight/darkLight/dark
    ASP.NET Core verifier includedYesCommunityCommunityCommunity

    نوى كابتشا — كابتشا ألغاز مستضافة ذاتياً وسهلة الوصول

    بديل مفتوح المصدر لـ reCAPTCHA: خادمك يُنشئ اللغز ويتحقق من الحل، دون تتبّع أو أطراف ثالثة. أكثر من ثلاثين نوعًا من الألغاز تختار منها ما تشاء، لغزًا واحدًا أو عدة ألغاز، لكل إجراء على حدة، مع إمكانية طلب لغزين متتاليين. دعم كامل للوحة المفاتيح وقارئات الشاشة مع سؤال نصي وتحدٍّ صوتي، والعربية والإنجليزية مع RTL، وستة أنماط ألوان بتصميم ثلاثي الأبعاد. يعمل مع React وVue وSvelte وAngular ويتحقق عبر Node.js أو ASP.NET Core. جرّب الملعب التفاعلي أعلاه باللغة العربية.