Skip to content
Myra EU CAPTCHA Online Help Updated · 25 Aug 2026

iOS

The SDK for iOS embeds the widget in a WKWebView and supplies an interface in Swift.

Requirements

The following requirements must be met:

Requirement Value
iOS From version 13.0
Swift From version 5.5
Xcode From version 13
Credentials Public sitekey from the Details view

Embed the SDK

With the Swift Package Manager, add the dependency to Package.swift:

.package(url: "https://github.com/Myra-Security-GmbH/eu-captcha-ios-sdk.git", from: "1.0.0")

In Xcode, you can also add the package with File > Add Package Dependencies.

With CocoaPods, add this line to the Podfile file:

pod 'EuCaptcha', '~> 1.0'

Then run pod install.

Make the widget

import EuCaptcha

let widget = EuCaptchaSDK.createWidget(
    sitekey: "EUCAPTCHA_SITE_KEY",
    theme: .auto,          // .light, .dark, or .auto
    language: "en"         // BCP 47 language code; defaults to system language
)

The theme value controls the appearance with .light, .dark, and .auto. The language value takes a language code as specified in BCP 47. Without a value, the language of the device applies.

Read the events

widget.onComplete = { event in
    // event.response is the token to verify server-side
    submitTokenToServer(event.response)
}

widget.onExpire = { _ in
    // The token has expired; the widget resets automatically
    disableLoginButton()
}

widget.onError = { _ in
    // An error occurred during the proof-of-work
    showErrorMessage()
}

widget.onStateChange = { event in
    print("State:", event.state, "Response:", event.response)
}

Embed the widget

let widgetVC = widget.viewController()
addChild(widgetVC)
view.addSubview(widgetVC.view)
widgetVC.didMove(toParent: self)

widgetVC.view.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
    widgetVC.view.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16),
    widgetVC.view.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -16),
    widgetVC.view.heightAnchor.constraint(equalToConstant: EuCaptchaSDK.preferredHeight),
])

Life cycle of the widget

Method Effect
start() No effect. The widget starts automatically.
reset() Discards the condition and starts a new challenge.
destroy() Releases the resources. Do not use the reference again.
getResponse() Gives the current token.
getState() Gives the current EuCaptchaWidgetState condition.

Conditions of the widget

Condition Meaning
.initial The widget is set up, but not active.
.checking The challenge is in operation.
.completed The challenge passed. The response field contains the token.
.expired The token expired.
.error An error occurred.
.destroyed The widget was removed.

Verify the token

Send the event.response value to your server as client_token. The server verifies the token:

POST https://api.eu-captcha.eu/v1/verify
Content-Type: application/json

{
  "sitekey":           "EUCAPTCHA_SITE_KEY",
  "secret":            "EUCAPTCHA_SECRET_KEY",
  "client_ip":         "<client IP address>",
  "client_token":      "<token from the widget>",
  "client_user_agent": "<client user-agent>"
}

The response is { "success": true, "train": false }.

See Verify a client token.