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.
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.
Puzzles
Visitors can always switch it with the speaker button.
Your configuration
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.
theme="midnight"theme="aurora"theme="sand" lang="ar"🔊 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.
| Id | Puzzle | العربية | Kind | Blind guess |
|---|---|---|---|---|
slider | Slider jigsaw | لغز السحب | Drag, slide, rotate, hold | ≈ 8% |
slide-unlock | Slide to the target | اسحب إلى الهدف | Drag, slide, rotate, hold | ≈ 7% |
shadow-drag | Drag to the shadow | اسحب إلى الظل | Drag, slide, rotate, hold | < 2% |
jigsaw | Jigsaw (4 pieces) | أحجية من 4 قطع | Drag, slide, rotate, hold | 1 in 23 |
rotate | Rotate the scene | تدوير المشهد | Drag, slide, rotate, hold | ≈ 7% |
rotate-object | Rotate the object | تدوير الشيء | Drag, slide, rotate, hold | ≈ 7% |
rotate-match | Align the inner circle | محاذاة الدائرة الداخلية | Drag, slide, rotate, hold | ≈ 7% |
hold | Hold and release | اضغط ثم أفلت | Drag, slide, rotate, hold | ≈ 1 in 4 |
icons | Select matching shapes | اختيار الأشكال المطابقة | Select in a picture | < 1% |
icons-weather | Select weather icons | اختيار رموز الطقس | Select in a picture | < 1% |
icons-objects | Select everyday objects | اختيار الأشياء | Select in a picture | < 1% |
odd-one-out | Odd one out | المختلف | Select in a picture | 1 in 9 |
odd-rotation | Find the mirrored letter | الحرف المعكوس | Select in a picture | 1 in 6 |
color-name | Colour by name + pattern | اللون بالاسم والنقش | Select in a picture | < 1% |
biggest | Largest / smallest | الأكبر / الأصغر | Select in a picture | 1 in 9 |
find-shape | Find the shape | ابحث عن الشكل | Select in a picture | < 1% |
shadow-pick | Pick the shadow | اختر الظل | Select in a picture | 1 in 6 |
pattern | What comes next | ما التالي | Select in a picture | 1 in 6 |
clock | Read the clock | قراءة الساعة | Select in a picture | 1 in 6 |
math-compare | Compare sums | مقارنة النواتج | Select in a picture | 1 in 62 |
symmetry | Complete the mirror | أكمل التماثل | Select in a picture | < 0.1% |
pairs | Match pairs | مطابقة الأزواج | Select in a picture | 1 in 105 |
tap-order | Tap numbers in order | انقر الأرقام بالترتيب | Tap in order | < 0.1% |
spell | Spell the word | تهجئة الكلمة | Tap in order | < 0.1% |
order | Order dots / bars | ترتيب النقاط والأعمدة | Put in order | 1 in 24 |
order-size | Order by size | الترتيب حسب الحجم | Put in order | 1 in 24 |
order-numbers | Order numbers | ترتيب الأعداد | Put in order | 1 in 24 |
order-time | Order clock times | ترتيب الأوقات | Put in order | 1 in 24 |
story | Picture story | قصة مصورة | Put in order | 1 in 6–24 |
trace | Connect the dots | توصيل النقاط | Draw a path | < 0.1% |
trace-letters | Connect A–E | توصيل الحروف | Draw a path | < 0.1% |
maze | Maze | متاهة | Draw a path | < 0.1% |
math | Math image | عملية حسابية | Type the answer | ≈ 10% |
count | Count the objects | عدّ الأشياء | Type the answer | ≈ 1 in 5 |
dice | Dice total | مجموع النرد | Type the answer | ≈ 1 in 6 |
pow | Invisible proof-of-work | إثبات عمل غير مرئي | Invisible / accessible alternative | n/a (CPU cost) |
accessible | Accessible text question | سؤال نصي ميسّر | Invisible / accessible alternative | machine-readable |
audio | Audio challenge (digits / beeps) | تحدٍّ صوتي (أرقام / نغمات) | Invisible / accessible alternative | 1 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
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
| Part | Supported versions |
|---|---|
Node server (nawa-captcha) | Node 18 and up, zero runtime dependencies, Express adapter included |
| React | 18 and 19 |
| Vue | 3.3 and up |
| Svelte | 5 |
| Angular | 18 and up (standalone component and reactive forms) |
| Plain HTML or any framework | @nawa-captcha/widget, a Web Component with no framework needed |
| ASP.NET Core | NawaCaptcha.AspNetCore on .NET 8 |
Nawa Captcha vs reCAPTCHA, hCaptcha and Turnstile
| Feature | Nawa Captcha | reCAPTCHA | hCaptcha | Turnstile |
|---|---|---|---|---|
| Self-hosted, no third-party calls | Yes | No | No | No |
| No user tracking / cookies | Yes | No | Partial | Partial |
| Open source (MIT) | Yes | No | No | No |
| You choose the puzzle types | Yes (30+) | No | No | No |
| Keyboard + screen-reader alternative | Yes (text + audio) | Audio | Accessibility cookie | Mostly invisible |
| Arabic / RTL built in | Yes | Yes | Yes | Yes |
| Themes (light, dark, high contrast) | 6 presets + your tokens | Light/dark | Light/dark | Light/dark |
| ASP.NET Core verifier included | Yes | Community | Community | Community |
نوى كابتشا — كابتشا ألغاز مستضافة ذاتياً وسهلة الوصول
بديل مفتوح المصدر لـ reCAPTCHA: خادمك يُنشئ اللغز ويتحقق من الحل، دون تتبّع أو أطراف ثالثة. أكثر من ثلاثين نوعًا من الألغاز تختار منها ما تشاء، لغزًا واحدًا أو عدة ألغاز، لكل إجراء على حدة، مع إمكانية طلب لغزين متتاليين. دعم كامل للوحة المفاتيح وقارئات الشاشة مع سؤال نصي وتحدٍّ صوتي، والعربية والإنجليزية مع RTL، وستة أنماط ألوان بتصميم ثلاثي الأبعاد. يعمل مع React وVue وSvelte وAngular ويتحقق عبر Node.js أو ASP.NET Core. جرّب الملعب التفاعلي أعلاه باللغة العربية.