FastAPI CAPTCHA Integration
This recipe shows how to integrate TrustCaptcha into a FastAPI application. The frontend setup is the same as for any other Python application — this page focuses on the server-side validation.
The setup section gets you to a working integration in three small steps using a path operation directly. Below it, an optional refactor section shows the more reusable FastAPI-idiomatic approach (a dependency injected via Depends).
Preparation
Section titled “Preparation”You should have already completed the following steps before you wire TrustCaptcha into your FastAPI application.
Read Get-Started: Get a quick overview of the concepts behind TrustCaptcha and the integration process in get started.
Existing CAPTCHA: If you don’t have a CAPTCHA yet, sign in or create a new user account. Then create a new CAPTCHA.
1. Embed the frontend widget
Section titled “1. Embed the frontend widget”First, add the TrustCaptcha script to your page (see the JavaScript Guide for version pinning and self-hosting options).
Then place the <trustcaptcha-component> element inside your form. The widget appends a hidden tc-verification-token field on submit, which your FastAPI endpoint receives like any other form input.
<script type="module" src="https://cdn.trustcomponent.com/trustcaptcha/3.0.x/trustcaptcha.esm.min.js"></script>
<form method="post" action="/contact"> <label>Email</label> <input type="email" name="email" required>
<trustcaptcha-component sitekey="<your_site_key>"></trustcaptcha-component>
<button type="submit">Send</button></form>See the Widget Overview for the full property reference.
2. Install the Python SDK
Section titled “2. Install the Python SDK”pip install "trustcaptcha>=3.0.0,<4.0.0"3. Validate the token in your path operation
Section titled “3. Validate the token in your path operation”from fastapi import FastAPI, Form, HTTPExceptionfrom fastapi.concurrency import run_in_threadpoolfrom trustcaptcha.trust_captcha import TrustCaptcha
app = FastAPI()
@app.post("/contact")async def submit( email: str = Form(...), tc_verification_token: str = Form(..., alias="tc-verification-token"),): # In production, load from env: os.environ["TRUSTCAPTCHA_API_KEY"] api_key = "<your_api_key>"
trust_captcha = TrustCaptcha(api_key) try: result = await run_in_threadpool(trust_captcha.get_verification_result, tc_verification_token) except Exception: raise HTTPException(status_code=400, detail="CAPTCHA verification failed.")
if not result.verification_passed or result.score > 0.5: raise HTTPException(status_code=400, detail="CAPTCHA verification failed.")
# CAPTCHA passed — request data is safe to use. # ... your business logic ...
return {"status": "ok"}That’s it — the form is now protected. For real deployments, move the API key out of the source code (see the comment) and consider explicit failover handling — see Failover Behavior for the reasoning and a code template.
Refactor: extract to a dependency
Section titled “Refactor: extract to a dependency”If you protect more than one endpoint, the most idiomatic FastAPI approach is a custom dependency that performs the verification before your endpoint runs. The verification call then becomes a single Depends(...) line on every protected endpoint.
Configure the API key and share the SDK
Section titled “Configure the API key and share the SDK”Use FastAPI’s own dependency system to expose a single TrustCaptcha instance across the whole app — lru_cache ensures the SDK is built exactly once and reused across requests:
import osfrom functools import lru_cachefrom fastapi import Depends, Form, HTTPExceptionfrom fastapi.concurrency import run_in_threadpoolfrom trustcaptcha.trust_captcha import TrustCaptcha
@lru_cachedef get_trust_captcha() -> TrustCaptcha: return TrustCaptcha(os.environ["TRUSTCAPTCHA_API_KEY"])Create the dependency
Section titled “Create the dependency”async def verify_trust_captcha( tc_verification_token: str = Form(..., alias="tc-verification-token"), trust_captcha: TrustCaptcha = Depends(get_trust_captcha),) -> None: try: result = await run_in_threadpool(trust_captcha.get_verification_result, tc_verification_token) except Exception: raise HTTPException(status_code=400, detail="CAPTCHA verification failed.")
if not result.verification_passed or result.score > 0.5: raise HTTPException(status_code=400, detail="CAPTCHA verification failed.")Use the dependency on your endpoints
Section titled “Use the dependency on your endpoints”from fastapi import Depends, Formfrom captcha import verify_trust_captcha
@app.post("/contact", dependencies=[Depends(verify_trust_captcha)])async def submit(email: str = Form(...)): # CAPTCHA already verified — the endpoint only runs if it passed. return {"status": "ok"}Adding dependencies=[Depends(verify_trust_captcha)] to any endpoint now opts the route into CAPTCHA verification.
Form vs JSON body. The examples use Form(...) because the widget posts a hidden form field. For JSON endpoints, declare the token in your Pydantic request model instead and read it inside the dependency.
Async / blocking. The SDK’s get_verification_result is blocking I/O. In async def endpoints, wrap it in run_in_threadpool (or asyncio.to_thread) so it doesn’t block the event loop. In def endpoints, FastAPI handles the threadpool for you.
Singleton SDK instance. For configured usage (custom timeouts, proxy, custom API host), pass them to the constructor: TrustCaptcha(api_key, api_host=..., proxy=...). See the Python Guide for the full constructor options.
Next steps
Section titled “Next steps”Once you have wired TrustCaptcha into your FastAPI application, you can use TrustCaptcha to its full extent. However, we still recommend the following additional technical and organizational measures:
Security rules: You can find many security settings for your CAPTCHA in the CAPTCHA settings. These include, for example, authorized websites, CAPTCHA bypass for specific IP addresses, bypass keys, IP based blocking, geoblocking, individual difficulty and duration of the CAPTCHA, and much more. Learn more about the security rules.
Privacy & GDPR compliance: Include a passage in your privacy policy that refers to the use of TrustCaptcha. We also recommend that you enter into a data processing agreement with us to stay GDPR-compliant. Learn more about data protection.
Accessibility & UX: Customize TrustCaptcha to your website so that your website is as accessible as possible and offers the best possible user experience. More about accessibility.
Failover behavior: Decide how your backend should behave when our service is temporarily unreachable. This is particularly important for high-availability flows where blocking real users during an outage is worse than letting through a small amount of unverified traffic. Learn more about failover behavior.
Testing: If you use automated testing, make sure that the CAPTCHA does not block it. Learn more about testing.