Axum
TrustCaptcha – Bot protection

Axum CAPTCHA Integration

Wire TrustCaptcha into an Axum handler in just a few lines of Rust. Stop bot-driven spam on logins, signups and contact forms with a shared TrustCaptcha instance via Axum's typed state and a small async helper. EU-hosted, GDPR-ready, no image puzzles.

Quickstart

How the integration works

1. Create a CAPTCHA

Create a user account or log in with an existing one. Then create a new CAPTCHA or select an existing one. If you’re unsure whether TrustCaptcha is right for you, try our CAPTCHA service risk-free for 14 days at no cost.

On the CAPTCHA overview page, you will find all the important information, such as the site key and licence key, and you can also create your API key. Allow your websites to access your CAPTCHA by simply adding them to the access authorised domain list in the CAPTCHA security rules.

Start of the CAPTCHA creation form.
CAPTCHA security rules of a demo CAPTCHA.

2. Add the CAPTCHA widget to your form

Drop the TrustCaptcha widget into the HTML form your Axum handler serves. The widget runs the CAPTCHA in the background and adds a hidden tc-verification-token field on submit, which axum::extract::Form deserializes into your struct.

contact.html
HTML
<script type="module" src="https://cdn.trustcomponent.com/trustcaptcha/3.0.x/trustcaptcha.esm.min.js"></script>

<form method="post" action="/contact">
    <input type="email" name="email" required>
    <trustcaptcha-component sitekey="<your_site_key>"></trustcaptcha-component>
    <button type="submit">Send</button>
</form>

The CAPTCHA widget will then be displayed inside your form:

CAPTCHA done

Need detailed information about the CAPTCHA widget integration?
For the full widget reference — including themes, languages, custom design and more — please read our documentation.

Read the documentation

3. Validate the token in your Axum handler

In your Axum handler, take the verification token from the form, look up the result via our Rust crate, and decide whether to accept the request.

First, install our TrustCaptcha Rust crate:

Install
bash
cargo add trustcaptcha@^3.0

Then validate the token inside your Axum handler and act on the result:

src/main.rs
Rust
use axum::{extract::Form, http::StatusCode, response::IntoResponse};
use serde::Deserialize;
use trustcaptcha::trust_captcha::TrustCaptcha;

#[derive(Deserialize)]
struct ContactForm {
    email: String,
    #[serde(rename = "tc-verification-token")]
    tc_verification_token: String,
}

async fn submit(Form(form): Form<ContactForm>) -> impl IntoResponse {
    let trust_captcha = match TrustCaptcha::builder("<your_api_key>").build() {
        Ok(tc) => tc,
        Err(_) => return (StatusCode::INTERNAL_SERVER_ERROR, "CAPTCHA setup failed.").into_response(),
    };

    let result = match trust_captcha.get_verification_result(&form.tc_verification_token).await {
        Ok(r) => r,
        Err(_) => return (StatusCode::BAD_REQUEST, "CAPTCHA verification failed.").into_response(),
    };

    if !result.verification_passed || result.score > 0.5 {
        return (StatusCode::BAD_REQUEST, "CAPTCHA verification failed.").into_response();
    }

    // CAPTCHA passed — process the request
    (StatusCode::OK, "Thanks!").into_response()
}

Need detailed information about the Axum CAPTCHA integration?
For full step-by-step instructions — including a shared TrustCaptcha via typed state and a reusable verify_token helper — please read our documentation.

Read the documentation

Other backend framework instead of Axum?
If you use a different framework, pick the matching recipe here. If your framework isn’t listed, your software developers can integrate the verification themselves using our documentation or ask our support team for a pre-built integration.

4. Congratulations 🎉

You are now protected by TrustCaptcha - congratulations!

CAPTCHA done

FAQs

Where in an Axum app does the CAPTCHA verification go?
Inside the async handler that receives the form submission. Bind the body with axum::extract::Form<MyForm>, where MyForm carries the CAPTCHA token via #[serde(rename = "tc-verification-token")], then call our Rust crate to fetch the verification result.
How do I share a single TrustCaptcha across handlers?
Build it once at startup, wrap it in Arc, put it in an AppState struct and attach it to the router with .with_state(state). Each handler then receives State<AppState> and reads the SDK from there — the Arc keeps cloning cheap.
Should I extract the CAPTCHA check into a custom Axum extractor?
It's tempting, but FromRequestParts only sees request parts (headers, URI), not the form body — and Form<...> consumes the body. The cleanest pattern is a small async verify_token(...) helper called from inside each protected handler with the ? operator.
Does the Rust SDK fit Axum's Tokio runtime?
Yes. The crate is async/reqwest-based, so you await the verification call directly inside your async fn handler. No blocking workarounds and no thread-pool tricks are needed.
Losing leads to CAPTCHAs?

TrustCaptcha blocks spam and bots, not customers. No puzzles, GDPR-ready, EU-hosted.

CAPTCHA start
CAPTCHA done
Puzzle-free UX
Runs in the background while visitors type — so more people finish your forms and fewer drop off.
GDPR-ready
EU-hosted and privacy-first: no cookies, encrypted transmission, automatic cleanup — with ready-to-use legal resources.
Multi-layer Security
Adaptive protection plus intelligent risk scoring stops abuse early — even when attack traffic spikes.
Full Control
Fine-tune sensitivity, set allow/block lists, and use geoblocking — you decide how strict verification should be.

Protect your Axum application with TrustCaptcha in just a few steps!

  • EU-hosted & GDPR-ready
  • No puzzles
  • Try free for 14 days