ArkCaptcha is a lightweight, self-hosted CAPTCHA solution for ASP.NET Core and modern web applications.
It provides:
- π Server-side CAPTCHA generation (ASP.NET Core)
- π Browser SDK (
ark-captcha.js) - π§© Razor TagHelper (
<ark-captcha>) - β‘ Zero external dependencies (no Google reCAPTCHA)
- π’ Enterprise-ready architecture (scalable & extensible)
- Image-based CAPTCHA with noise & distortion
- Token-based validation (one-time use)
- Auto-rendered UI (no HTML required)
- Custom UI support
- TagHelper integration for Razor
- Built-in CSS injection (no external styles required)
- Multi-instance safe (script loads only once)
- Async-friendly API
dotnet add package ArkCaptcha.AspNetCorenpm install ark-captchaOR
<script src="https://cdn.jsdelivr.net/npm/ark-captcha@latest/ark-captcha.js"></script>Browser (ArkCaptcha JS / TagHelper)
β
ASP.NET Core API (/ark/api/captcha)
β
Token + Image
β
User Input
β
Validation (Server-side)
builder.Services.AddSingleton<ArkCaptchaService>();app.MapControllers();| Endpoint | Description |
|---|---|
/ark/api/captcha |
Generate CAPTCHA |
/ark/api/captcha/validate |
Validate CAPTCHA |
<div id="captcha"></div>
<script>
new ArkCaptcha({
container: document.getElementById("captcha"),
apiUrl: "/ark/api/captcha",
enableVerify: true
});
</script>β Fully automatic UI β Built-in styling β Optional verify button
<img id="img" />
<input id="input" />
<button id="refresh">Refresh</button>
<button id="submit">Validate</button>
<script>
const captcha = new ArkCaptcha({
apiUrl: "/ark/api/captcha",
imageElement: document.getElementById("img"),
inputElement: document.getElementById("input"),
refreshButton: document.getElementById("refresh")
});
document.getElementById("submit").onclick = async () => {
const valid = await captcha.validate();
console.log(valid);
};
</script><ark-captcha api-url="/ark/api/captcha" enable-verify="true"></ark-captcha>- Auto loads
ark-captcha.js(once globally) - Supports multiple instances per page
- Injects UI automatically
- Exposes instance via DOM:
document.querySelector("#captcha_id").captchaconst data = await captcha.getValue();
/*
{
token: "...",
value: "USER_INPUT"
}
*/[HttpPost]
public IActionResult Submit(FormModel model)
{
var isValid = _captchaService.ValidateCaptcha(
model.Token,
model.Value
);
if (!isValid)
{
return BadRequest("Invalid Captcha");
}
return Ok();
}- Returns: CAPTCHA image (PNG)
- Header:
X-Ark-Captcha-Token: <token>
{
"token": "string",
"value": "string"
}Response:
{
"success": true
}If no elements are provided:
-
ArkCaptcha auto-injects:
- HTML
- CSS
- Interaction logic
Optional:
enableVerify: trueπ Adds built-in Verify button
new ArkCaptcha({
apiUrl: "/ark/api/captcha",
container: HTMLElement,
imageElement: HTMLElement,
inputElement: HTMLElement,
refreshButton: HTMLElement,
enableVerify: true
});Refresh CAPTCHA image
const result = await captcha.validate();Returns:
true | falseconst data = await captcha.getValue();Returns:
{
token,
value
}Manually control UI state
- One-time token validation
- Token removed after validation
- Case-insensitive comparison
- No external tracking
- Self-hosted (GDPR friendly)
ArkCaptcha/
βββ ArkCaptcha.AspNetCore/
β βββ ArkCaptchaService.cs
β βββ CaptchaController.cs
β βββ CaptchaTagHelper.cs
βββ ark-captcha.js
βββ LICENSE
βββ README.md
- MIT License (your code)
- Uses BSD-3 licensed dependencies (e.g. SkiaSharp)
- Use Redis / distributed cache instead of in-memory store
- Add token expiry (5β10 minutes)
- Enable rate limiting for
/captchaendpoints - Use HTTPS in production
- Avoid exposing token in URLs
- Dark mode UI
- Canvas-based CAPTCHA
- Invisible CAPTCHA mode
- Blazor component
- Multi-language support
Contributions are welcome!
- Fork the repo
- Create a feature branch
- Submit a PR
If you find ArkCaptcha useful, give it a β on GitHub!