- Installation
- Requirements
- Pre-requisites
- Examples
- Use cases
- Compiled size
- Known issues
- License
- Troubleshooting
Add hCaptcha to your project. This library automatically handles hCaptcha's events and returns a validation token, presenting the challenge via a modal if needed.
To secure your application, you need to send the token received here to your backend for server-side validation via the api.hcaptcha.com/siteverify endpoint.
HCaptcha is available through CocoaPods and packaged for Carthage and SPM (Swift Package Manager).
To install it, simply add the following line to your dependencies file:
pod "HCaptcha"
# or
pod "HCaptcha/RxSwift"github "hCaptcha/HCaptcha-ios-sdk"Carthage will create two different frameworks named HCaptcha and HCaptcha_RxSwift, the latter containing the RxSwift extension for the HCaptcha framework.
Known issues:
- Carthage doesn't support prebuilt zips for
xcframeworkso use--no-use-binaries- Carthage/Carthage#3130 - Carthage has a
RxSwiftbuild issue, also avoidable via--no-use-binaries- Carthage/Carthage#3243
Standard SPM formula: uses Package.swift
| Platform | Requirements |
|---|---|
| iOS | âś… >= 12.0 |
| WatchOS | ✖️ |
Once you have the hCaptcha apiKey (also referred to as sitekey, which can be obtained at https://dashboard.hcaptcha.com/sites),
the hCaptcha apiKey can be specified in Info.plist keys or can be passed as parameters when instantiating HCaptcha().
For the Info.plist configuration, add HCaptchaKey (sitekey) and HCaptchaDomain (with a protocol, i.e. https://) to your Info.plist.
HCaptchaKeyis your hCaptcha sitekey.HCaptchaDomainshould be a string likehttps://www.your.com
If you prefer to keep the information out of the Info.plist, you can instead use:
let hcaptcha = try? HCaptcha(
apiKey: "YOUR_HCAPTCHA_KEY",
baseURL: URL(string: "YOUR_HCAPTCHA_DOMAIN")!
)
...Notes:
- in most cases
baseURLcan behttp://localhost. This value is mainly used for your convenience in analytics. baseURLshould matchHCaptchaDomainif specified; it controls the URI used to initialize the hCaptcha session. Example:https://www.your.com
If you are looking for a complete example please check links below:
By default, Locale.current is used to automatically set the language for the SDK, but this behavior can be changed by explicitly passing the locale parameter to HCaptcha:
let hcaptcha = try? HCaptcha(
...
locale: Locale(identifier: "zh-CN"),
...
)
...Since this SDK uses local resources, you may want to set a host override for better tracking and enforcement of siteverify parameters.
You can achieve this by passing the extra param host:
let hcaptcha = try? HCaptcha(
...
host: "your-domain.com",
...
)
...Note: this should be the bare host, i.e. not including a protocol prefix like https://.
The SDK supports three built-in themes: light, dark, and contrast
let hcaptcha = try? HCaptcha(
...
theme: "dark", // "light" or "contrast"
...
)
...For Enterprise sitekeys we also support custom themes via the customTheme parameter, described below.
If you are an Enterprise user with first-party hosting access, you can use your own endpoint (i.e. verify.your.com).
You can then enable it in your code:
let hcaptcha = try? HCaptcha(
...
endpoint: URL("https://custom.endpoint")!,
...
)
...Enterprise params like:
reportapi(string)assethost(string)imghost(string)sentry(bool)customTheme(string representation of JS Object or JSON; see Enterprise docs)
Can be passed via HCaptcha(...)
Please see the hCaptcha Enterprise documentation for more details.
Note: The rqdata parameter has been moved from HCaptchaConfig to HCaptchaVerifyParams for better API consistency. The old rqdata property in HCaptchaConfig is now deprecated, and will be removed in the next major version.
This iOS SDK assumes by default that you want an "invisible" checkbox, i.e. that triggering the hCaptcha flow from within your app should either return a token or show the user a challenge directly. (Note: "invisible" refers to the checkbox. If you want no or few visual challenges, choose Passive or 99.9% Passive as the behavior type for the sitekey in the hCaptcha dashboard.)
If you instead want the classic "normal" or "compact" checkbox behavior of showing a checkbox to tick and then either closing or showing a challenge, you can pass size to the HCaptcha initializer.
let hcaptcha = try? HCaptcha(size: .compact)And you will now get the desired behavior.
The orientation argument can be set either .portrait or .landscape orientation to adjust challenge modal behavior.
let hcaptcha = try? HCaptcha(orientation: .landscape)By default, orientation is portrait and does not reflow.
However, if you have an app used exclusively in landscape mode (e.g. a game) then you can also switch the challenge UI to match this design choice.
This SDK allows you to receive interaction events, for your analytics via the onEvent method. At the moment the SDK supports:
openfires when hCaptcha is opened and a challenge is visible to an app userexpiredfires when the passcode response expires and the user must re-verifychallengeExpiredfires when the user display of a challenge times out with no answerclosefires when the user dismisses a challenge.errorfires when an internal error happens during challenge verification, for example a network error. Details about the error will be provided by thedataparam, as in the example below. Note: This event is not intended for error handling, but only for analytics purposes. For error handling please see thevalidateAPI call docs.
You can check the implementation details in:
Each emitted token has an expiration time. Once this time is reached, you will receive a .sessionTimeout error or an .expired event in the onEvent closure, if it is set.
However, this error/event will not be emitted in the following cases:
HCaptchaResult.dematerialize()is called; in this case, the token is considered consumed.HCaptcha.stop()is called; in this case, the SDK stops all processing, and no errors or events will be emitted.
Note that Enterprise customers have additional options: please contact support for guidance if necessary.
By default the SDK will automatically fetch a new token upon expiry once you have requested a token via validate. This behavior can be adjusted by passing resetOnError: false to the validate call:
hcaptcha.validate(on: view, resetOnError: false) { result in
// Handle result
}The SDK supports phone prefix and phone number parameters for MFA (Multi-Factor Authentication) flows. You can pass these parameters when calling the validate method:
// Using phone prefix (country code without '+')
let verifyParams = HCaptchaVerifyParams(phonePrefix: "44")
hcaptcha.validate(on: view, verifyParams: verifyParams) { result in
// Handle result
}
...
// Using phone number (full E.164 format)
let verifyParams = HCaptchaVerifyParams(phoneNumber: "+44123456789")
hcaptcha.validate(on: view, verifyParams: verifyParams) { result in
// Handle result
}
...
hcaptcha.validate(on: view, verifyParams: verifyParams) { result in
// Handle result
}Note: If you update verify parameters and call validate a second time, call reset() before the second validation to ensure updated parameters are consumed by the SDK.
HCaptcha pod size: 140 KB as of Jan 2024. You can always see the latest number in the CI logs by searching for the "pod size" string.
- WebView crashes on Simulator iOS 14.x (arm64) but not on real devices. More details
HCaptcha is available under the MIT license. See the LICENSE file for more info.
Q. I'm getting a "Could not load embedded HTML" exception. What does this mean?
A. Most likely you have not included an asset in your build. Please double-check assets, and see the example app for more details.
Q. I'm getting "xcconfig: unable to open file" after upgrading the SDK. (Or changing SDK and running Example app.)
A. In your app or the Example app dir, run pod deintegrate && pod install to refresh paths.
Q: The challenge modal is displayed, but I can't interact with it. How do I fix this?
A: There are several ways this can happen:
-
Your app called
UIApplication.shared.beginIgnoringInteractionEvents(), which prevents any user interaction, before calling the execute method of the SDK. Make sure to callUIApplication.shared.endIgnoringInteractionEvents()to re-enable interaction before executing the SDK token request if you use this method. -
You may have unintentionally added a transparent overlay over the SDK's view layer. This can be checked with the view debugger
Originally forked from fjcaetano's ReCaptcha IOS SDK, licensed under MIT.