iOS SDK
Install the EuCaptcha library to integrate EU CAPTCHA into your iOS application.
| Package | Version |
|---|---|
EuCaptcha |
1.0.0 |
Server-side verification is identical regardless of client platform — see Server-Side Verification. For other mobile integrations see Android SDK and Flutter.
Requirements
- iOS 13.0 or later
- Swift 5.5+
- Xcode 13+
Installation
In Xcode, go to File > Add Package Dependencies and enter the repository URL, or add it directly to Package.swift:
dependencies: [
.package(url: "https://github.com/Myra-Security-GmbH/eu-captcha-ios-sdk.git", from: "1.0.0")
]
Basic usage
1. Create a widget
Call the static factory method from wherever you set up your view controller:
import EuCaptcha
let widget = EuCaptchaSDK.createWidget(
sitekey: "EUCAPTCHA_SITE_KEY",
theme: .auto, // .light, .dark, or .auto (follows system appearance)
language: "en" // BCP 47 language tag; defaults to device language
)
2. Handle events
Assign closures to the widget before embedding its view:
widget.onComplete = { [weak self] event in
// event.response is the token — send it to your server
DispatchQueue.main.async {
self?.submitButton.isEnabled = true
self?.captchaToken = event.response
}
}
widget.onExpire = { [weak self] _ in
DispatchQueue.main.async {
self?.submitButton.isEnabled = false
}
}
widget.onError = { [weak self] _ in
DispatchQueue.main.async {
self?.showErrorMessage()
}
}
3. Embed the widget view controller
Obtain the widget's UIViewController and add it as a child:
let widgetVC = widget.viewController()
addChild(widgetVC)
widgetVC.view.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(widgetVC.view)
widgetVC.didMove(toParent: self)
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),
])
EuCaptchaSDK.preferredHeight is 70 pt. EuCaptchaSDK.maxWidth is 420 pt.
4. Submit the token
Pass the token from event.response to your server as the eu-captcha-response field. After a rejected submission, call widget.reset() so the user can complete a new challenge.
Customisation
EuCaptchaSDK.createWidget() parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
sitekey |
String |
— | Your public sitekey (required) |
theme |
EuCaptchaWidgetTheme |
.auto |
.light, .dark, or .auto (follows system appearance) |
language |
String? |
nil |
BCP 47 language tag (e.g. "en", "de"). Defaults to the device language. |
Event callbacks
Assign closures directly to properties on EuCaptchaWidget. All callbacks are delivered on the thread the widget's web view uses — dispatch to the main thread before updating the UI.
| Property | Event type | Fired when |
|---|---|---|
onComplete |
EuCaptchaWidgetCompleteEvent |
The challenge finishes successfully. event.response holds the token. |
onExpire |
EuCaptchaWidgetExpireEvent |
The token expires (60 minutes after completion). |
onError |
EuCaptchaWidgetErrorEvent |
A network or server error occurs. event.response is ".ERROR". |
onStateChange |
EuCaptchaWidgetStateChangeEvent |
Any state transition occurs. event.state and event.response reflect the new state. Covers all of the above. |
Widget states
EuCaptchaWidgetState is a Swift enum reported via onStateChange and widget.state:
| Case | Description |
|---|---|
.initial |
Widget loaded; challenge not yet started |
.checking |
Proof-of-work challenge in progress |
.completed |
Challenge finished — token is available in event.response |
.expired |
Token has expired; prompt the user to retry |
.error |
An error occurred during verification |
.destroyed |
Widget has been destroyed |
API reference
EuCaptchaSDK
All members are static. Do not instantiate this class directly.
| Member | Description |
|---|---|
createWidget(sitekey:theme:language:) -> EuCaptchaWidget |
Creates and returns a new widget handle. |
preferredHeight: CGFloat |
Recommended widget height in points (70). |
maxWidth: CGFloat |
Recommended maximum widget width in points (420). |
EuCaptchaWidget
Returned by EuCaptchaSDK.createWidget().
| Member | Type | Description |
|---|---|---|
state |
EuCaptchaWidgetState |
The current widget state. |
response |
String |
The current token, or a sentinel value if the challenge is not yet complete. |
onComplete |
((EuCaptchaWidgetCompleteEvent) -> Void)? |
Closure called when the challenge completes. |
onExpire |
((EuCaptchaWidgetExpireEvent) -> Void)? |
Closure called when the token expires. |
onError |
((EuCaptchaWidgetErrorEvent) -> Void)? |
Closure called on error. |
onStateChange |
((EuCaptchaWidgetStateChangeEvent) -> Void)? |
Closure called on every state change. |
viewController() -> UIViewController |
Returns the UIViewController to embed in your view hierarchy. |
|
getResponse() -> String |
Alternative getter for response. |
|
getState() -> EuCaptchaWidgetState |
Alternative getter for state. |
|
reset() |
Reload the widget so a new challenge can be solved. Call after a rejected submission. | |
destroy() |
Release WKWebView resources. Discard the handle afterwards. |
Server-side verification
After your server receives the form submission, verify the token by passing event.response as client_token to the Verification API.
For ready-made server libraries, see Server-Side Verification.