Skip to content

Sinatra CAPTCHA Integration

This recipe shows how to integrate TrustCaptcha into a Sinatra application. The frontend setup is the same as for any other Ruby application — this page focuses on the server-side validation.

The setup section gets you to a working integration in three small steps using a route block directly. Below it, an optional refactor section shows the more reusable Sinatra-idiomatic approach (a helper method called from a before filter).

You should have already completed the following steps before you wire TrustCaptcha into your Sinatra application.

  1. Read Get-Started: Get a quick overview of the concepts behind TrustCaptcha and the integration process in get started.

  2. Existing CAPTCHA: If you don’t have a CAPTCHA yet, sign in or create a new user account. Then create a new CAPTCHA.


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 ERB form. The widget appends a hidden tc-verification-token field on submit, which your Sinatra route receives in params like any other form input.

views/contact.erb
<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.

Gemfile
gem 'sinatra'
gem 'trustcaptcha', '~> 3.0'
Terminal window
bundle install
app.rb
require 'sinatra'
require 'trustcaptcha/trust_captcha'
post '/contact' do
# In production, load from env: ENV['TRUSTCAPTCHA_API_KEY']
api_key = '<your_api_key>'
token = params['tc-verification-token'].to_s
begin
trust_captcha = TrustCaptcha.new(api_key)
result = trust_captcha.get_verification_result(token)
rescue StandardError
halt 400, 'CAPTCHA verification failed.'
end
halt 400, 'CAPTCHA verification failed.' unless result.verification_passed && result.score <= 0.5
# CAPTCHA passed — params are safe to use.
# ... your business logic ...
'Thanks!'
end

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 helper + before filter

Section titled “Refactor: extract to a helper + before filter”

If you protect more than one route, the most idiomatic Sinatra approach is a helper method combined with a before filter scoped to the routes that should be protected.

.env
TRUSTCAPTCHA_API_KEY=<your_api_key>
app.rb
require 'sinatra'
require 'trustcaptcha/trust_captcha'
# Build the SDK once at startup
TRUST_CAPTCHA = TrustCaptcha.new(ENV.fetch('TRUSTCAPTCHA_API_KEY'))
helpers do
def verify_trust_captcha!
# Sinatra's `before` matches any HTTP verb on the path — skip the check on
# GETs that just render the form and would never carry a token.
return unless request.post?
token = params['tc-verification-token'].to_s
begin
result = TRUST_CAPTCHA.get_verification_result(token)
rescue StandardError
halt 400, 'CAPTCHA verification failed.'
end
halt 400, 'CAPTCHA verification failed.' unless result.verification_passed && result.score <= 0.5
end
end
# Apply the filter to specific routes
before '/contact' do verify_trust_captcha! end
before '/newsletter' do verify_trust_captcha! end
post '/contact' do
# CAPTCHA already verified — params are safe to use.
'Thanks!'
end
post '/newsletter' do
'Subscribed!'
end

You can also call verify_trust_captcha! directly inside a route if you only need it once. The before filter pattern shines once two or more routes share the check.


Filters scope. A before block without arguments runs for every request. Always pass a route pattern so the filter only triggers on the routes you want to protect — and remember that before '/path' matches all HTTP verbs on that path, so the helper above bails out on anything that isn’t a POST.

Singleton SDK instance. TRUST_CAPTCHA is built once at startup and reused for every request — better connection reuse, lower per-request overhead. For configured usage (custom timeouts, proxy, custom API host), pass them to the constructor: TrustCaptcha.new(api_key, api_host: ..., proxy: ...). See the Ruby Guide for the full constructor options.


Once you have wired TrustCaptcha into your Sinatra 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.