Persilsoft.Turnstile.Blazor 1.0.2

There is a newer version of this package available.
See the version list below for details.
dotnet add package Persilsoft.Turnstile.Blazor --version 1.0.2
                    
NuGet\Install-Package Persilsoft.Turnstile.Blazor -Version 1.0.2
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Persilsoft.Turnstile.Blazor" Version="1.0.2" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Persilsoft.Turnstile.Blazor" Version="1.0.2" />
                    
Directory.Packages.props
<PackageReference Include="Persilsoft.Turnstile.Blazor" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Persilsoft.Turnstile.Blazor --version 1.0.2
                    
#r "nuget: Persilsoft.Turnstile.Blazor, 1.0.2"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Persilsoft.Turnstile.Blazor@1.0.2
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Persilsoft.Turnstile.Blazor&version=1.0.2
                    
Install as a Cake Addin
#tool nuget:?package=Persilsoft.Turnstile.Blazor&version=1.0.2
                    
Install as a Cake Tool

Persilsoft.Turnstile.Blazor

Persilsoft.Turnstile.Blazor is a Blazor component that integrates Cloudflare Turnstile CAPTCHA into Blazor WebAssembly and Blazor Server applications.

It provides:

  • ✅ A reusable CAPTCHA component.
  • ✅ A service to manage Turnstile lifecycle.
  • ✅ Full JavaScript interop handling.
  • ✅ The ability to retrieve CAPTCHA tokens and send them to your backend for secure verification.

🚀 Installation

  1. Install the NuGet package:
dotnet add package Persilsoft.Turnstile.Blazor
  1. Register the Turnstile services in your Blazor application's DI container:
using Persilsoft.Turnstile.Shared.Options;
using Persilsoft.Turnstile.Blazor;

Action<TurnstileOptions> turnstileOptionsConfigurator = options =>
    builder.Configuration.GetRequiredSection(TurnstileOptions.SectionKey).Bind(options);

builder.Services.AddTurnstileServices(turnstileOptionsConfigurator);

🔧 Configuration

Add the following section to your appsettings.json:

"TurnstileOptions": {
  "WebApiBaseAddress": "https://localhost:7292",
  "SiteKey": "YOUR_SITE_KEY"
}
Key Description
WebApiBaseAddress The base URL of your backend where the token verification endpoint resides.
SiteKey Your public site key from Cloudflare Turnstile.

🔐 Backend Verification Requirement

⚠️ Important:
The CAPTCHA component generates a validation token. Your backend must verify this token with Cloudflare's /siteverify API to ensure it is valid.

Option 1 — Manual verification (DIY):

[HttpPost("api/turnstile-verify")]
public async Task<IActionResult> Verify([FromBody] CaptchaVerificationRequest request)
{
    var secret = _config["Turnstile:SecretKey"];
    var httpClient = _httpClientFactory.CreateClient();

    var parameters = new Dictionary<string, string>
    {
        { "secret", secret },
        { "response", request.Token }
    };

    var content = new FormUrlEncodedContent(parameters);
    var response = await httpClient.PostAsync("https://challenges.cloudflare.com/turnstile/v0/siteverify", content);
    var json = await response.Content.ReadAsStringAsync();

    var result = JsonSerializer.Deserialize<TurnstileResponse>(json);

    if (result != null && result.Success)
        return Ok(new { success = true });

    return BadRequest(new { success = false, errors = result?.ErrorCodes });
}

Option 2 — Use Persilsoft.Turnstile.Server

💡 Recommended: You can avoid implementing the verification endpoint manually by using the complementary NuGet package Persilsoft.Turnstile.Server.

With it, you simply register the backend service and call TurnstileService.VerifyAsync(token) — no need to deal with HttpClient, FormUrlEncodedContent, or JSON parsing.


🧠 Component Parameters

Parameter Type Required Description
Action string Action name for token verification context.
Theme TurnstileTheme? Widget theme: Auto, Dark, or Light.
Language string? Language code (e.g., en, es-PE).
Size TurnstileSize Widget size: Normal, Compact, Invisible.
Appearance TurnstileAppearance Appearance behavior: Always or Execute.
OnSuccess EventCallback<string> Triggered with the CAPTCHA token when successfully completed.
OnError EventCallback Triggered when CAPTCHA encounters an error.
OnExpired EventCallback Triggered when the CAPTCHA token expires.

💡 Example Usage

Razor Page Example

@page "/turnstile"
<PageTitle>Turnstile</PageTitle>

<h3>Turnstile CAPTCHA Demo</h3>

<EditForm Model="@model" OnValidSubmit="Send">
    <DataAnnotationsValidator />
    <div class="mb-3">
        <label for="name" class="form-label">Name</label>
        <input type="text" @bind="model.Name" class="form-control" id="name" name="name" />
        <ValidationMessage For="@(() => model.Name)" />
    </div>

    <div class="d-grid gap-2 col-6 mx-auto">
        <button class="btn btn-info" type="submit" disabled="@(!captchaSuccess)">Submit</button>
    </div>

    <div class="d-grid gap-2 col-6 mx-auto mt-2">
        <button class="btn btn-warning" type="button" disabled="@(!captchaSuccess)" @onclick="ResetCaptcha">Reset CAPTCHA</button>
    </div>

    <div class="d-grid gap-2 col-6 mx-auto mt-2">
        <button class="btn btn-danger" type="button" disabled="@(!captchaSuccess)" @onclick="RemoveCaptcha">Remove CAPTCHA</button>
    </div>

    <div class="d-flex justify-content-center mt-2">
        <TurstileComponent Action="SendForm"
                            Theme="TurnstileTheme.Auto"
                            Language="en-US"
                            Size="TurnstileSize.Flexible"
                            Appearance="TurnstileAppearance.Always"
                            OnSuccess="OnSuccess"
                            OnError="OnError"
                            OnExpired="OnExpired"
                            @ref="myTurnstile" />
    </div>

    <hr />

    <div class="mt-3">
        <textarea disabled class="form-control">@result</textarea>
    </div>
</EditForm>

Code Behind Example

@code {
    private TurstileComponent myTurnstile = null!;
    private bool captchaSuccess = false;
    private DemoModel model = new();
    private string result = string.Empty;

    [Inject] private GatewayTest Gateway { get; set; } = null!;

    private async Task Send()
    {
        try
        {
            await Gateway.SendAsync(model); // Send to backend
            result = "Form submitted successfully!";
        }
        catch (Exception ex)
        {
            result = ex.Message;
        }
    }

    private async Task ResetCaptcha()
    {
        captchaSuccess = false;
        model = new();
        result = null!;
        await myTurnstile.ResetAsync();
    }

    private async Task RemoveCaptcha() =>
        await myTurnstile.RemoveAsync();

    private async Task OnSuccess(string token)
    {
        captchaSuccess = true;
        model.CaptchaToken = token;
        await Task.CompletedTask;
    }

    private async Task OnError()
    {
        captchaSuccess = false;
        await Task.CompletedTask;
    }

    private async Task OnExpired()
    {
        captchaSuccess = false;
        await Task.CompletedTask;
    }
}

📜 License

MIT License


✨ Credits

Developed by Persilsoft.
For full backend support, check out Persilsoft.Turnstile.Server.

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on Persilsoft.Turnstile.Blazor:

Package Downloads
Persilsoft.Membership.Blazor

Contains razor clases for use in frontend membership projects

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.5 222 12/31/2025
1.0.4 120 12/31/2025
1.0.3 725 12/2/2025
1.0.2 699 12/2/2025
1.0.1 1,283 5/31/2025
1.0.0 231 5/28/2025