ReCaptcha Reaches 1.0

November 13, 2017

Fork me on GitHub

With the new Swift 4 support, ReCaptcha has finally reached a stable release! Now you can safely use Google’s Invisible ReCaptcha in your app!

Using the JS API, ReCaptcha tries to validate the challenge automatically and retrieve a token, however, if the API can’t ensure the user is human, a challenge may be presented.

Example Gif 2 Example Gif


Register a new site to use Invisible reCaptcha at the admin page. Make sure to add correct domain owned by you or your company!

This will return you two keys: a Site key and a Secret key. The former is the public key which will be used in your frontend to start the validation. This is the key must be used in the app. DO NOT USE THE SECRET KEY!

The Secret key is for the validation in the server side of the application!

Warning ⚠️

Beware that this library only works for Invisible ReCaptcha keys! Make sure to check the Invisible reCAPTCHA option when creating your API Key.


You can install ReCaptcha using CocoaPods, Carthage or as a submodule. The library comes with a RxSwift extension.


Add the following to your Podfile:

pod "ReCaptcha", '~> 1.0'
# or
pod "ReCaptcha/RxSwift", '~> 1.0'
github "fjcaetano/ReCaptcha" ~> 1.0

If you decide to use the reactive extension, be sure to link both frameworks ReCaptcha and ReCaptcha_RxSwift to your project. The latter, simply contains the reactive extension for the ReCaptcha class.

iOS Setup

Open your project’s Info.plist file and add two entries:

  • ReCaptchaKey: The Site key created in the previous step.
  • ReCaptchaDomain: A valid domain registered with the key in the previous step.

These values may also be sent as parameters to ReCaptcha() init. In this case, the parameters will override the values in the Info.plist.


Before starting the validation, you must call the configureWebView(_:) method. This is for when the webview needs to be presented for the user to complete the ReCaptcha challenge. If this method is not called, the validation may fail.

recaptcha.configureWebView { [weak self] (webview: WKWebView) in
    // Configure webview for presentation
    // Make sure its frame is not

This is the moment to add AutoLayout constraints and store a reference to the webview, which will already have a superview that is provided when starting the validation.

The configureWebView(_:) won’t necessarily be called. Only if the invisible validation is not possible.


To start the validation, per se, you must call the validate(on:) method.

recaptcha.validate(on: view) { [weak self] (result: ReCaptchaResult) in
    print(try? result.dematerialize())

The view given as parameter, must be visible, i.e. be in the active window hierarchy, its bounds must be valid and it can’t be marked as hidden. This view will contain the ReCaptcha webview as a subview.

By default, ReCaptcha won’t remove the webview from its superview, so it may be interesting to have some clean up after the closure is called.

Error Handling

ReCaptcha may throw you some errors if incorrectly configured or when execution fails. In any case, you can always try calling recaptcha.reset() on errors or providing resetOnError: true to the validate method.

  • ReCaptchaError.htmlLoadError: If by some reason, the library’s bundle is unreachable, the template HTML won’t be loaded.
  • ReCaptchaError.apiKeyNotFound: No API key has been provided to the library. Either set a ReCaptchaKey entry in the app’s Info.plist or pass it as argument to ReCaptcha’s init.
  • ReCaptchaError.baseURLNotFound: No domain has been provided to the library. Either set a ReCaptchaDomain entry in the app’s Info.plist or pass it as argument to ReCaptcha’s init.
  • ReCaptchaError.wrongMessageFormat: This means the JS context provided an unexpected message to the API. Shouldn’t happen, so, if it does, be sure to open an issue.
  • ReCaptchaError.unexpected(Error): 💩 happens ¯\_(ツ)_/¯. The only moment this error could be thrown is if JavaScript sends an error. Shouldn’t happen, but if it does, don’t be shy and open an issue.

Firewall bypass

If your firewall is blocking Google’s ReCaptcha, or if you’re behind the Great Firewall of China, you may use an alternate endpoint for the JS API that points to

try ReCaptcha(endpoint: .alternate)

The default value for the endpoint parameter points the API to

Full Documentation

Rendering enums in SwiftUI

Enums are an excellent way to leverage Swift's value-types and immutability principles for handling states. Imagine you have a view that …… Continue reading

Using native and non-native animations together

Published on November 11, 2019

Rogue Bit 🕹

Published on October 31, 2019