Written by Mateus Alexandre, DevOps Engineer at TrackIt

Web applications exposed to the internet are consistently targeted by automated threats such as credential stuffing, content scraping, vulnerability scanning, and denial-of-service attempts. Services like Cloudflare and Amazon CloudFront have popularized the use of browser challenges (automated checks to verify that a request is coming from a legitimate browser) and CAPTCHA as effective defenses against bots and automation.

For infrastructures built on AWS, Amazon CloudFront combined with AWS WAF (Web Application Firewall) provides native, integrated capabilities that offer comparable or enhanced protection—enabling fine-grained control and strong alignment with AWS environments.

The sections below outline how to secure applications using CAPTCHA and Challenge actions in AWS WAF, detailing their functionality and providing guidance on configuration strategies. These recommendations are applicable both when migrating from Cloudflare and when designing a new security approach for applications deployed at the edge.

Understanding CAPTCHA and Challenge Actions in AWS WAF

AWS WAF offers two inspection actions to help protect applications from unwanted or automated traffic: CAPTCHA and Challenge.

  • CAPTCHA (Completely Automated Public Turing test to tell Computers and Humans Apart) presents an interactive puzzle that must be solved to confirm human interaction. This action is particularly effective for scenarios requiring a higher level of confidence — such as login attempts or access to sensitive routes. Upon successful completion, AWS issues a token that allows the requestor to bypass the CAPTCHA for a configurable duration, referred to as immunity time.
  • Challenge performs a silent browser validation without requiring user input. It evaluates client-side behavior, such as support for JavaScript and cookies, to distinguish legitimate browsers from basic bots. This action is useful for mitigating low-complexity automated traffic while maintaining a frictionless experience for legitimate users.

Cloudflare Turnstile

Cloudflare offers an alternative approach with Turnstile, a CAPTCHA replacement designed to verify requests without introducing user-facing friction. It relies on a combination of:

  • Client-side signals (such as browser environment and behavior)
  • Server-side risk scoring
  • Private challenge mechanisms that remain invisible under most conditions

In many cases, Turnstile is able to validate requests without displaying a visual challenge.

AWS WAF vs. Cloudflare Turnstile

While both services aim to protect applications from automated abuse, their approaches differ:

AspectAWS WAF CAPTCHA / ChallengeCloudflare Turnstile
Type of verificationVisual CAPTCHA or JS-based challengeMostly invisible background validation
Control of when to applyFully rule-based (WAF conditions, rate limits, geolocation, etc.)Applied via embedded widget or server config
Integration and DeploymentWorks natively with AWS services like CloudFront, ALB, or API Gateway, and no external routing requiredRequires traffic to pass through Cloudflare as a reverse proxy (CDN or tunnel)
CustomizationTheme, retry limit, immunity time, response codeMinimal
Visibility to end-userCAPTCHA visible when triggered; challenge is transparent but passiveTypically no user-visible element unless needed

One key difference is that AWS WAF does not require changes to front-end or application code to enforce CAPTCHA or Challenge actions. These are triggered automatically based on WAF rule logic, using conditions such as rate limits or geolocation.

In contrast, Cloudflare Turnstile requires embedding a widget into the application and performing token validation on the server side, making it a more tightly integrated front-end implementation.

How to Configure CAPTCHA and Challenge Actions in AWS WAF

The following section outlines a practical example of configuring CAPTCHA and Challenge actions using AWS WAF with CloudFront, through both the AWS Console and Terraform. The objective is to establish a layered defense strategy that enhances protection against bots while preserving the user experience.

This configuration includes:

  • A global Challenge rule applied to all requests, enabling transparent bot detection without affecting legitimate users.
  • A CAPTCHA rule for the /login path, triggered only when a client exceeds a predefined request rate—an effective control for mitigating brute-force attempts while maintaining accessibility for valid users.

Configuration Steps Using AWS Console

Prerequisites

  • An Amazon CloudFront distribution already deployed and serving the application
  • Permissions to associate a Web ACL with the CloudFront distribution
  • A predictable route within the application (e.g., /login)

Create or Edit a Web ACL

  • Navigate to the AWS WAF Console and select Web ACLs
AD 4nXcJwSfcSHiVU kn1lYQ5dZfZD9FbhuTXNmok eN763t5 xTquQ5vJWX0AvTEYXv

  • Switch the region to Global
AD 4nXcv8hr10HsxXJJyyp4odX RsuVQb76XbtRZbQOOq7ueqFUdoW EARMhpyPXbnK3sp I0CVz0eZtQLicLxf asVUu0O0Ll u0sxOtEp7ORfscL9sp 3aRgOsHfbJ21W88o v8pHm
  • Click Create web ACL or select an existing ACL to edit
  • Choose Global resources under Resource type
AD 4nXe4Pbl4 hi3wNgjavp Ff4E3ZQxb FrRJ6v7mkmQdWih2i qh
  • Provide a name for the Web ACL and a corresponding CloudWatch metric name.
  • In the Associated AWS resources section, click Add AWS resources.
AD 4nXek7MpTM7ZNggOyr5M2C9td8VQ4a2YLk63eMmxf6xx0BcIldk4G5aG9OHRG8dEbC2yFumDKdP7XViWuNVTlq0os bYFmjr vWFik
  • Select the appropriate CloudFront distribution and click Add.
image 1
  • Leave the remaining settings at their defaults and click Next to continue.

Add a Global Challenge Rule

  • In the Add rules and rule groups section, click Add rules > Add my own rules and rule groups.
AD 4nXcGYYnNd2PDJ5KawTKnxeKOZvWdb SgPhvBZWVIAndmVwGnSiVih5CL6qGf88L74EXRqMVQTIwU5uHKSmy XnitUSwx6yISr kD4PeNrXfUkk52n9eG6s4 7d9MFN5GiHUrMi2Q
  • For Rule type, select Rule builder.
AD 4nXeoWB eCs3H4eh EJ9u3GwXaWVU8LUrHBgp4uR5XNf5iaXVta4aouz3F8BG0777sdq VonB 77Dse2UpoKgsTsvfDA8bZTa0juxO6LwEx GMuN19GdehAnmSHchf Rgd1Ai7NL
  • Provide a name for the rule and select Regular rule as the type.
AD 4nXfcAccve0mMZ7S01ijDy0WooibO7 5ESOT4y1oi9yKA4GZesDnhKRs6Z7Q1wuIYLca3Q eao1R QEEhKDFtCRbKtdd8d7Vf88Ub3Wr YIoEB 6SmJIZ2mmFqtqQyMhbICpIo8N67Q
  • Under If a request, choose matches the statement.
  • In the Inspection section:
    • Set the field to URI path
    • Select String match condition with match type Starts with string
    • Enter / as the String to match
AD 4nXdQK1Hd0F HRoMgDucDykdtlWuz7 gS1GOu4oLKFHCGTVopYcTqGHPphCM6ox1y38cDkKTM0NH9pBNoztExExPM7NZuVWEjHRowcqeI72Af5iGAuanNo
  • Set the Action to Challenge.
AD 4nXelw3xZh9EEB9SLEKZ46lKYb5r5WzehAdbnlUH72frDhqyTLle0jGznXpzND1nGPZ9QEsvNILoNLzZE2g4DNcF U85D lFLZUOZWweG2Su0eXHN9HLzEgJgTTaZa gv1OoV1zUMaQ
  • Set the Immunity time if needed, and click Add rule.

Add a CAPTCHA Rule for /login with Rate Limiting

  • Click Add rule > Add my own rules and rule groups.
  • Set Rule type to Rule builder.
  • Provide a rule name and select Rate-based rule as the type.

Configure rate-limiting criteria:

  • Set the Rate limit to 10 (minimum value).
  • Set the Evaluation window to 1 minute (60 seconds).
  • Under Request aggregation, choose Source IP address.
  • For Scope of inspection and rate limiting, select Only consider requests that match the criteria in a rule statement.

Define the match criteria:

  • Under If a request, choose matches the statement.
  • In the Statement section:
    • Select URI path in inspect.
    • Match type: String match condition > Exactly matches string.
    • String to match: /login 
AD 4nXdhqxsJ1 R8w PWjxIh65Z01MAX2mz853b3BBNlq8OyL4YFjx1hKQZGqc2OPSu9enOljT2dEUP9NayWcH j0dPycaU1RBoCcPvICNQ9fBhFCbESt35emjtoiJEBLt jG53jURcSHQ
  • In the Action section:
    • Select CAPTCHA.
    • Set the Immunity time if needed, and click Add rule.
AD 4nXeNXmWx
  • After this step, return to the Add rules and rule groups page and click Next to proceed.

Adjust Rule Priorities

  • Assign a lower priority number to the CAPTCHA rule to ensure it takes precedence over the global Challenge rule.
  • Click Next.

Configure Logging and Metrics

  • For each rule, enable sampling of requests and CloudWatch metrics as needed.
  • Set a name for the CloudWatch metric for each rule and set Enable sampled requests.
  • Click Next.

Review and create web ACL

  • Review the settings and click Create web ACL to finalize the setup.

Configuration Steps Using Terraform

Prerequisites

  • An active AWS account with permissions to manage WAF, CloudFront, and IAM
  • A CloudFront distribution already deployed, pointing to the application
  • Terraform installed locally
  • The AWS CLI configured with credentials and default region set to us-east-1
  • A Terraform provider for AWS configured in the project

Create the Web ACL Resource

resource “aws_wafv2_web_acl” “captcha-challenge-acl” {
    name = “captcha-challenge-web-acl”
    description = “WAF ACL with global challenge and rate-based captcha on /login”
    scope = “CLOUDFRONT”

    default_action {
        allow {}
    }
   
    visibility_config {
        cloudwatch_metrics_enabled = true
        metric_name = “waf-captcha-challenge”
        sampled_requests_enabled = true
    }

    rule {
        name = “captcha-web-acl-rule”
        priority = 0
        action {
            captcha {}
        }

        statement {
            rate_based_statement {
                limit = 10
                evaluation_window_sec = 60
                scope_down_statement {
                    byte_match_statement {
                        text_transformation {
                            priority = 0
                            type = “NONE”
                        }

                        positional_constraint = “EXACTLY”
                        search_string = “/login”
                        field_to_match {
                            uri_path {}
                        }
                    }
                }
            }
        }

        captcha_config {
            immunity_time_property {
                immunity_time = 300
            }
        }

        visibility_config {
            cloudwatch_metrics_enabled = true
            metric_name = “captcha-login”
            sampled_requests_enabled = true
        }
    }
    rule {
        name = “challenge-web-acl-rule-1”
        priority = 1

        action {
            challenge {}
        }

        statement {
            byte_match_statement {
                search_string         = “/”
                positional_constraint = “STARTS_WITH”

                field_to_match {
                uri_path {}
                }

                text_transformation {
                priority = 0
                type     = “NONE”
                }
            }
        }

        visibility_config {
            cloudwatch_metrics_enabled = true
            metric_name = “challenge-global”
            sampled_requests_enabled = true
        }
    }
}

Associate the Web ACL with CloudFront

  • In the aws_cloudfront_distribution resource, add the web_acl_id:
resource “aws_cloudfront_distribution” “cloudfront” {
    web_acl_id = aws_wafv2_web_acl.captcha-challenge-acl.arn    â€¦
  • Run the terraform command (plan/apply).

Testing the Configuration

Testing CAPTCHA (Rate-Limited on /login)

  • Open an incognito or private browser window to bypass any cached tokens.
  • Access the /login path: https://your-domain.com/login
  • Refresh the page at least 11 times within a one-minute window.
  • Once the rate limit is exceeded, the CAPTCHA challenge page should appear, confirming that the rule is functioning as intended.
AD 4nXeIahgUOGwRyYhvChzmgqkDxgicodxkadidyxGa4LXnYaZRW9Wxux kIUvCjN94 77 CvaHRO 0qhXojfolHehMxPSGlQXB 8xVYI s5gxnK2UQigs0rh iVIgjGQuj1jrIq1D32w
AD 4nXdzoaxOpiLFQUOG0Ypgges3mMZ5Zcj444p Rs4 Qef8gBtzgbhcgjJVYwt4vygy8qNp9MOrP6eRGg4qekqUQRggjvVt6iQufuGYQr7C3 oiXKG7Xut85Bq2JzPboV5UVRGHRi6r

Testing Challenge (Global)

To validate that the global Challenge rule is active, run the following command in a terminal:

curl –i https://your-domain.com

The expected output will be:

HTTP/2 202
server: CloudFront
content-length: 0
x-amzn-waf-action: challenge

This response indicates that AWS WAF is issuing a challenge. Since curl does not support JavaScript, it cannot complete the challenge validation, resulting in an empty response with a content-length of 0.

Beyond CAPTCHA and Challenge: Building a Broader WAF Protection Strategy

CAPTCHA and Challenge actions are effective for introducing friction in sensitive user-facing workflows such as login, signup, and checkout. These mechanisms help distinguish legitimate users from automated traffic, particularly when behavior appears suspicious but not definitively malicious.

However, some threats require immediate mitigation rather than friction. Attacks involving SQL injection, cross-site scripting (XSS), or traffic from known malicious IPs typically warrant outright blocking.

In such cases, AWS WAF Managed Rule Groups (MRGs) play a critical role by providing preconfigured protections against common and emerging web threats.

Managed Rule Groups

Managed rule groups are preconfigured sets of WAF rules maintained by AWS or third-party vendors available via the AWS Marketplace. Each group targets a specific category of threat—such as injection attacks, protocol anomalies, or automated bot traffic—and is continuously updated to reflect evolving attack patterns.

These rule groups simplify deployment by enabling comprehensive protection without the need to manually create and manage individual rules. While the internal rule logic is not customizable, updates are handled automatically, providing an effective, low-maintenance layer of security.

Detecting Bots with AWS Bot Control

For applications frequently targeted by automated traffic—such as crawlers, scrapers, or credential stuffing tools—AWS offers the Bot Control managed rule group (AWSManagedRulesBotControlRuleSet).

This rule group evaluates requests using attributes like user-agent strings, HTTP headers, and request behavior to detect non-human activity. It can take predefined actions or assign internal labels that can be referenced in custom WAF rules.

When used alongside CAPTCHA or Challenge actions, Bot Control helps apply verification steps selectively to traffic that demonstrates automated characteristics, reducing friction for legitimate users while increasing deterrence for bots.

Combining Protection Layers

The best results often come from combining multiple layers of protection:

  • CAPTCHA and Challenge actions are effective for safeguarding interactive endpoints and slowing down suspicious or high-risk traffic.
  • Managed Rule Groups automatically mitigate known attack vectors, malformed requests, and generic automation.
  • Custom rules using labels offer precise control over specific request patterns and behaviors.

This layered approach improves coverage while minimizing false positives and maintaining a smooth experience for legitimate users.

Conclusion

AWS WAF’s CAPTCHA and Challenge actions provide a configurable and effective means to defend against automated threats. By introducing verification steps only under defined conditions, these mechanisms minimize disruption for legitimate users while mitigating risks such as credential stuffing, scraping, and brute-force attempts.

Compared to solutions like Cloudflare Turnstile, the AWS approach does not require changes to front-end code and offers complete control through rule-based configurations. This is particularly suited to teams aiming to enforce security policies natively within their AWS environment.

When integrated with Managed Rule Groups, CAPTCHA and Challenge actions contribute to a comprehensive security posture—automatically filtering known threats and selectively verifying suspicious traffic. The result is a robust, adaptable protection strategy that balances security, performance, and user experience.

About TrackIt

TrackIt is an international AWS cloud consulting, systems integration, and software development firm headquartered in Marina del Rey, CA.

We have built our reputation on helping media companies architect and implement cost-effective, reliable, and scalable Media & Entertainment workflows in the cloud. These include streaming and on-demand video solutions, media asset management, and archiving, incorporating the latest AI technology to build bespoke media solutions tailored to customer requirements.

Cloud-native software development is at the foundation of what we do. We specialize in Application Modernization, Containerization, Infrastructure as Code and event-driven serverless architectures by leveraging the latest AWS services. Along with our Managed Services offerings which provide 24/7 cloud infrastructure maintenance and support, we are able to provide complete solutions for the media industry.

TrackIt has also achieved the AWS Security Competency, demonstrating our ability to design and implement secure cloud architectures that align with AWS best practices.