Google reCAPTCHA with Aurelia

Quick post to show how to create an Aurelia custom element that renders a Google reCAPTCHA.

1. Register

Register for reCAPTCHA API keys on the reCAPTCHA admin site.

2. Load the API

Load google's reCAPTCHA API. When you register your site google provides some markup containing logic to load the API using an async <script> element. We're going to write the equivalent logic in JavaScript which will give us the ability to control when the API is loaded, the callback to use to tell us the API is ready and most importantly, control over which element(s) are converted to reCAPTCHAs. Check out the docs for more info.


// The name of the global function the recaptcha API will call when
// it's ready.
const recaptchaCallbackName = 'setRecaptchaReady';

// An "API ready" promise that will be resolved when the reCAPTCHA API 
// is ready.
const ready = new Promise(
  resolve => window[recaptchaCallbackName] = resolve);

// Inject an async script element to load the reCAPTCHA API.
// Notice the callback name is passed as an argument on the query string 
// as well as the "render" option which tells the API we don't want the
// reCAPTCHAs automatically rendered, we will render them explicitly.
let script = document.createElement('script');
script.src = `${recaptchaCallbackName}&render=explicit`;
script.async = true;
script.defer = true;


3. Add your site key

The site key is public and needs to match your domain.

const sitekey = '6LfwTRkTAAAAAKl5YtVOgNVsENf5TysXLJaZjIen';


4. Create a <recaptcha> custom element

The custom element below has two bindable properties: verified enables binding a callback that will be invoked once the reCAPTCHA is verifies the user is not a robot and theme enables picking the light or dark theme.

The element's attached method waits for the "API ready" promise to resolve before asking the API to render the reCAPTCHA.

export class Recaptcha {
  @bindable verified;
  @bindable theme = 'light';
  constructor(element) {
    this.element = element;
  attached() {
    ready.then(() => grecaptcha.render(this.element, { 
      sitekey: sitekey, 
      theme: this.theme,
      callback: this.verified


Here's what it looks like in action: