

**Introducing a new console experience for AWS WAF**

You can now use the updated experience to access AWS WAF functionality anywhere in the console. For more details, see [Working with the console](https://docs.aws.amazon.com/waf/latest/developerguide/working-with-console.html). 

# Using the CAPTCHA JavaScript API
<a name="waf-js-captcha-api"></a>

This section provides instructions for using the CAPTCHA integration API.

The CAPTCHA JavaScript API allows you to configure the CAPTCHA puzzle and place it where you want in your client application. This API leverages the features of the intelligent threat JavaScript APIs to acquire and use AWS WAF tokens after an end user successfully completes a CAPTCHA puzzle. 

Implement the JavaScript integration first in a test environment, then in production. For additional coding guidance, see the sections that follow. 

**To use the CAPTCHA integration API**

1. **Install the API**

   1. Sign in to the AWS Management Console and open the AWS WAF console at [https://console.aws.amazon.com/wafv2/homev2](https://console.aws.amazon.com/wafv2/homev2). 

   1. In the navigation pane, choose **Application integration**. On the **Application integration** page, you can see tabbed options. 

   1. Select **CAPTCHA integration**.

   1. Copy the listed JavaScript integration script tag for use in your integration.

   1. In your application page code, in the `<head>` section, insert the script tag that you copied. This inclusion makes the CAPTCHA puzzle available for configuration and use. 

      ```
      <head>
          <script type="text/javascript" src="integrationURL/jsapi.js" defer></script>
      </head>
      ```

      This `<script>` listing is configured with the `defer` attribute, but you can change the setting to `async` if you want a different behavior for your page. 

      The CAPTCHA script also automatically loads the intelligent threat integration script if it isn't already present. The intelligent threat integration script causes your client application to automatically retrieve a token in the background on page load, and provides other token management functionality that you need for your use of the CAPTCHA API. 

1. **(Optional) Add domain configuration for the client's tokens** – By default, when AWS WAF creates a token, it uses the host domain of the resource that’s associated with the protection pack (web ACL). To provide additional domains for the JavaScript APIs, follow the guidance at [Providing domains for use in the tokens](waf-js-challenge-api-set-token-domain.md). 

1. **Get the encrypted API key for the client** – The CAPTCHA API requires an encrypted API key that contains a list of valid client domains. AWS WAF uses this key to verify that the client domain you're using with the integration is approved to use AWS WAF CAPTCHA. To generate your API key, follow the guidance at [Managing API keys for the JS CAPTCHA API](waf-js-captcha-api-key.md).

1. **Code your CAPTCHA widget implementation** – Implement the `renderCaptcha()` API call in your page, at the location where you want to use it. For information about configuring and using this function, see the following sections, [CAPTCHA JavaScript API specification](waf-js-captcha-api-specification.md) and [How to render the CAPTCHA puzzle](waf-js-captcha-api-render.md). 

   The CAPTCHA implementation integrates with the intelligent threat integration APIs for token management and to run fetch calls that use the AWS WAF tokens. For guidance about using these APIs, see [Using the intelligent threat JavaScript API](waf-js-challenge-api.md).

1. **Add token verification in your protection pack (web ACL)** – Add at least one rule to your protection pack (web ACL) that checks for a valid CAPTCHA token in the web requests that your client sends. You can use the CAPTCHA rule action to check, as described in [CAPTCHA and Challenge in AWS WAF](waf-captcha-and-challenge.md). 

   The protection pack (web ACL) additions verify that requests going to your protected endpoints include the token that you've acquired in your client integration. Requests that include a valid, unexpired CAPTCHA token pass the CAPTCHA rule action inspection and do not present your end user with another CAPTCHA puzzle. 

After you've implemented the JavaScript API, you can review the CloudWatch metrics for CAPTCHA puzzle attempts and solutions. For metrics and dimension details, see [Account metrics and dimensions](waf-metrics.md#waf-metrics-account).

**Topics**
+ [CAPTCHA JavaScript API specification](waf-js-captcha-api-specification.md)
+ [How to render the CAPTCHA puzzle](waf-js-captcha-api-render.md)
+ [Handling a CAPTCHA response from AWS WAF](waf-js-captcha-api-conditional.md)
+ [Managing API keys for the JS CAPTCHA API](waf-js-captcha-api-key.md)

# CAPTCHA JavaScript API specification
<a name="waf-js-captcha-api-specification"></a>

This section lists the specification for the methods and properties of the CAPTCHA JavaScript APIs. Use the CAPTCHA JavaScript APIs to run custom CAPTCHA puzzles in your client applications. 

This API builds on the intelligent threat APIs, which you use to configure and manage AWS WAF token acquisition and use. See [Intelligent threat API specification](waf-js-challenge-api-specification.md). .

**`AwsWafCaptcha.renderCaptcha(container, configuration)`**  
Presents an AWS WAF CAPTCHA puzzle to the end user and, upon success, updates the client token with the CAPTCHA validation. This is available only with the CAPTCHA integration. Use this call along with the intelligent threat APIs to manage token retrieval and to provide the token in your `fetch` calls. See the intelligent threat APIs at [Intelligent threat API specification](waf-js-challenge-api-specification.md).  
Unlike the CAPTCHA interstitial that AWS WAF sends, the CAPTCHA puzzle rendered by this method displays the puzzle immediately, without an initial title screen.     
**`container`**  
The `Element` object for the target container element on the page. This is commonly retrieved by calling `document.getElementById()` or `document.querySelector()`.  
Required: Yes  
Type: `Element`  
**configuration**  
An object containing CAPTCHA configuration settings, as follows****:    
**`apiKey`**   
The encrypted API key that enables permissions for the client's domain. Use the AWS WAF console to generate your API keys for your client domains. You can use one key for up to five domains. For information, see [Managing API keys for the JS CAPTCHA API](waf-js-captcha-api-key.md).   
Required: Yes  
Type: `string`  
**`onSuccess: (wafToken: string) => void;`**   
Called with a valid AWS WAF token when the end user successfully completes a CAPTCHA puzzle. Use the token in the requests that you send to the endpoints that you protect with an AWS WAF protection pack (web ACL). The token provides proof and the timestamp of the latest successful puzzle completion.   
Required: Yes  
**`onError?: (error: CaptchaError) => void;`**   
Called with an error object when an error occurs during the CAPTCHA operation.   
Required: No  
**`CaptchaError` class definition** – The `onError` handler supplies an error type with the following class definition.   

```
CaptchaError extends Error {
    kind: "internal_error" | "network_error" | "token_error" | "client_error";
    statusCode?: number;
}
```
+ `kind` – The kind of error returned. 
+ `statusCode` – The HTTP status code, if available. This is used by `network_error` if the error is due to an HTTP error.  
**`onLoad?: () => void;`**   
Called when a new CAPTCHA puzzle loads.  
Required: No  
**`onPuzzleTimeout?: () => void;`**   
Called when a CAPTCHA puzzle isn't completed before it expires.  
Required: No  
**`onPuzzleCorrect?: () => void;`**   
Called when a correct answer is provided to a CAPTCHA puzzle.  
Required: No  
**`onPuzzleIncorrect?: () => void;`**   
Called when an incorrect answer is provided to a CAPTCHA puzzle.  
Required: No  
**`defaultLocale`**   
The default locale to use for the CAPTCHA puzzle. The written instructions for CAPTCHA puzzles are available in Arabic (ar-SA), simplified Chinese (zh-CN), Dutch (nl-NL), English (en-US), French (fr-FR), German (de-DE), Italian (it-IT), Japanese (ja-JP), Brazilian Portuguese (pt-BR), Spanish (es-ES), and Turkish (tr-TR). Audio instructions are available for all of the written languages except Chinese and Japanese, which default to English. To change the default language, provide the international language and locale code, for example, `ar-SA`.  
Default: The language currently in use in the end user's browser  
Required: No  
Type: `string`  
**`disableLanguageSelector`**   
If set to `true`, the CAPTCHA puzzle hides the language selector.   
Default: `false`  
Required: No  
Type: `boolean`  
**`dynamicWidth`**   
If set to `true`, the CAPTCHA puzzle changes width for compatibility with the browser window width.   
Default: `false`  
Required: No  
Type: `boolean`  
**`skipTitle`**   
If set to `true`, the CAPTCHA puzzle doesn't display the puzzle title heading **Solve the puzzle**.   
Default: `false`  
Required: No  
Type: `boolean`

# How to render the CAPTCHA puzzle
<a name="waf-js-captcha-api-render"></a>

This section provides an example `renderCaptcha` implementation.

You can use the AWS WAF `renderCaptcha` call where you want to in your client interface. The call retrieves a CAPTCHA puzzle from AWS WAF, renders it, and sends the results to AWS WAF for verification. When you make the call, you provide the puzzle rendering configuration and the callbacks that you want to run when your end users complete the puzzle. For details about the options, see the preceding section, [CAPTCHA JavaScript API specification](waf-js-captcha-api-specification.md).

Use this call in conjunction with the token management functionality of the intelligent threat integration APIs. This call gives your client a token that verifies the successful completion of the CAPTCHA puzzle. Use the intelligent threat integration APIs to manage the token and to provide the token in your client's calls to the endpoints that are protected with AWS WAF protection packs (web ACLs). For information about the intelligent threat APIs, see [Using the intelligent threat JavaScript API](waf-js-challenge-api.md).

**Example implementation**  
The following example listing shows a standard CAPTCHA implementation, including the placement of the AWS WAF integration URL in the `<head>` section. 

This listing configures the `renderCaptcha` function with a success callback that uses the `AwsWafIntegration.fetch` wrapper of the intelligent threat integration APIs. For information about this function, see [How to use the integration `fetch` wrapper](waf-js-challenge-api-fetch-wrapper.md).

```
<head>
    <script type="text/javascript" src="<Integration URL>/jsapi.js" defer></script>
</head>

<script type="text/javascript">
    function showMyCaptcha() {
        var container = document.querySelector("#my-captcha-container");
        
        AwsWafCaptcha.renderCaptcha(container, {
            apiKey: "...API key goes here...",
            onSuccess: captchaExampleSuccessFunction,
            onError: captchaExampleErrorFunction,
            ...other configuration parameters as needed...
        });
    }
    
    function captchaExampleSuccessFunction(wafToken) {
        // Captcha completed. wafToken contains a valid WAF token. Store it for
        // use later or call AwsWafIntegration.fetch() to use it easily.
        // It will expire after a time, so calling AwsWafIntegration.getToken()
        // again is advised if the token is needed later on, outside of using the
        // fetch wrapper.
        
        // Use WAF token to access protected resources
        AwsWafIntegration.fetch("...WAF-protected URL...", {
            method: "POST",
            headers: {
                "Content-Type": "application/json",
            },
            body: "{ ... }" /* body content */
        });
    }
    
    function captchaExampleErrorFunction(error) {
        /* Do something with the error */
    }
</script>

<div id="my-captcha-container">
    <!-- The contents of this container will be replaced by the captcha widget -->
</div>
```

**Example configuration settings**  
The following example listing shows the `renderCaptcha` with non-default settings for the width and the title options. 

```
        AwsWafCaptcha.renderCaptcha(container, {
            apiKey: "...API key goes here...",
            onSuccess: captchaExampleSuccessFunction,
            onError: captchaExampleErrorFunction,
            dynamicWidth: true, 
            skipTitle: true
        });
```

For full information about the configuration options, see [CAPTCHA JavaScript API specification](waf-js-captcha-api-specification.md).

# Handling a CAPTCHA response from AWS WAF
<a name="waf-js-captcha-api-conditional"></a>

This section provides an example of handling a CAPTCHA response.

An AWS WAF rule with a CAPTCHA action terminates the evaluation of a matching web request if the request doesn't have a token with a valid CAPTCHA timestamp. If the request is a `GET` text/html call, the CAPTCHA action then serves the client an interstitial with a CAPTCHA puzzle. When you don't integrate the CAPTCHA JavaScript API, the interstitial runs the puzzle and, if the end user successfully solves it, automatically resubmits the request. 

When you integrate the CAPTCHA JavaScript API and customize your CAPTCHA handling, you need to detect the terminating CAPTCHA response, serve your custom CAPTCHA, and then if the end user successfully solves the puzzle, resubmit the client's web request. 

The following code example shows how to do this. 

**Note**  
The AWS WAF CAPTCHA action response has a status code of HTTP 405, which we use to recognize the CAPTCHA response in this code. If your protected endpoint uses an HTTP 405 status code to communicate any other type of response for the same call, this example code will render a CAPTCHA puzzle for those responses as well. 

```
<!DOCTYPE html>
<html>
<head>
    <script type="text/javascript" src="<Integration URL>/jsapi.js" defer></script>
</head>
<body>
    <div id="my-captcha-box"></div>
    <div id="my-output-box"></div>

    <script type="text/javascript">
    async function loadData() {
        // Attempt to fetch a resource that's configured to trigger a CAPTCHA
        // action if the rule matches. The CAPTCHA response has status=HTTP 405.
        const result = await AwsWafIntegration.fetch("/protected-resource");

        // If the action was CAPTCHA, render the CAPTCHA and return

        // NOTE: If the endpoint you're calling in the fetch call responds with HTTP 405
        // as an expected response status code, then this check won't be able to tell the
        // difference between that and the CAPTCHA rule action response.

        if (result.status === 405) {
            const container = document.querySelector("#my-captcha-box");
            AwsWafCaptcha.renderCaptcha(container, {
                apiKey: "...API key goes here...",
                onSuccess() {
                    // Try loading again, now that there is a valid CAPTCHA token
                    loadData();
                },
            });
            return;
        }

        const container = document.querySelector("#my-output-box");
        const response = await result.text();
        container.innerHTML = response;
    }

    window.addEventListener("load", () => {
        loadData();
    });
    </script>
</body>
</html>
```

# Managing API keys for the JS CAPTCHA API
<a name="waf-js-captcha-api-key"></a>

This section provides instructions for generating and deleting API keys.

To integrate AWS WAF CAPTCHA into a a client application with the JavaScript API, you need the JavaScript API integration tag and the encrypted API key for the client domain where you want to run your CAPTCHA puzzle. 

The CAPTCHA application integration for JavaScript uses the encrypted API keys to verify that the client application domain has permission to use the AWS WAF CAPTCHA API. When you call the CAPTCHA API from your JavaScript client, you provide an API key with a domain list that includes a domain for the current client. You can list up to 5 domains in a single encrypted key. 

**API key requirements**  
The API key that you use in your CAPTCHA integration must contain a domain that applies to the client where you use the key. 
+ If you specify a `window.awsWafCookieDomainList` in your client's intelligent threat integration, then at least one domain in your API key must be an exact match for one of the token domains in `window.awsWafCookieDomainList` or it must be the apex domain of one of those token domains. 

  For example, for the token domain `mySubdomain.myApex.com`, the API key `mySubdomain.myApex.com` is an exact match and the API key `myApex.com` is the apex domain. Either key matches the token domain. 

  For information about the setting the token domain list, see [Providing domains for use in the tokens](waf-js-challenge-api-set-token-domain.md).
+ Otherwise, the current domain must be contained in the API key. The current domain is the domain that you can see in the browser address bar. 

The domains that you use must be ones that AWS WAF will accept, based on the protected host domain and the token domain list that's configured for the web ACL. For more information, see [AWS WAF protection pack (web ACL) token domain list configuration](waf-tokens-domains.md#waf-tokens-domain-lists).

**How to choose the Region for your API key**  
AWS WAF can generate CAPTCHA API keys in any Region where AWS WAF is available. 

As a general rule, you should use the same Region for your CAPTCHA API key as you use for your protection pack (web ACL). If you expect a global audience for a regional protection pack (web ACL), however, you can obtain a CAPTCHA JavaScript integration tag that's scoped to CloudFront and an API key that's scoped to CloudFront, and use them with a regional protection pack (web ACL). This approach allows clients to load a CAPTCHA puzzle from the Region that's closest to them, which reduces latency. 

CAPTCHA API keys that are scoped to Regions other than CloudFront are not supported for use across multiple Regions. They can only be used in the Region they are scoped to. 

**To generate an API key for your client domains**  
To obtain the integration URL and generate and retrieve the API keys through the console. 

1. Sign in to the AWS Management Console and open the AWS WAF console at [https://console.aws.amazon.com/wafv2/homev2](https://console.aws.amazon.com/wafv2/homev2). 

1. In the navigation pane, choose **Application integration**. 

1. In the pane, **protection packs (web ACLs) that are enabled for application integration**, select the Region that you want to use for your API key. You can also select the Region in the **API keys** pane of the **CAPTCHA integration** tab.

1. Choose the tab **CAPTCHA integration**. This tab provides the CAPTCHA JavaScript integration tag, which you can use in your integration, and the API keys listing. Both are scoped to the selected Region.

1. In the **API keys** pane, choose **Generate key**. The key generation dialogue appears. 

1. Enter the client domains that you want to include in the key. You can enter up to 5. When you're finished, choose **Generate key**. The interface returns to the CAPTCHA integration tab, where your new key is listed. 

   Once created, an API key is immutable. If you need to make changes to a key, generate a new key and use that instead. 

1. (Optional) Copy the newly generated key for use in your integration. 

You can also use the REST APIs or one of the language-specific AWS SDKs for this work. The REST API calls are [CreateAPIKey](https://docs.aws.amazon.com/waf/latest/APIReference/API_CreateAPIKey.html) and [ListAPIKeys](https://docs.aws.amazon.com/waf/latest/APIReference/API_ListAPIKeys.html). 

**To delete an API key**  
To delete an API key, you must use the REST API or one of the language specific AWS SDKs. The REST API call is [DeleteAPIKey](https://docs.aws.amazon.com/waf/latest/APIReference/API_DeleteAPIKey.html). You can't use the console to delete a key. 

After you delete a key, it can take up to 24 hours for AWS WAF to disallow use of the key in all regions. 