Stop account takeover attacks (Free, Pro, and Business)
When your site has login pages, you need to decide how to verify that visitors are human, how aggressively to limit failed attempts, and which request patterns to block. This guide covers five stages: enforce HTTPS, turn on bot protection, add Turnstile to your login form, create Application Security rate limiting rules and custom rules for suspicious patterns, and monitor for ongoing attacks using SSL/TLS transport security and Cloudflare bot solutions. The core workflow covers features available on Free, Pro, and Business plans. Enterprise features such as leaked credentials custom detection locations and Bot Management custom rules are included as callouts.
Credentials sent over plain HTTP are visible to anyone on the network path between the visitor and your origin server. Cloudflare SSL/TLS provides two settings that enforce HTTPS connections: Always Use HTTPS and HTTP Strict Transport Security (HSTS). For additional control over which encryption standards your domain accepts, refer to Cipher suites.
Always Use HTTPS redirects all visitor requests from http to https for all subdomains and hosts.
To enable Always Use HTTPS in the dashboard:
-
In the Cloudflare dashboard, go to the SSL/TLS Overview page.
Go to Overview -
Make sure that your SSL/TLS encryption mode is not set to Off. When you set your encryption mode to Off, the Always Use HTTPS option will not be visible in your Cloudflare dashboard.
-
Go to the Edge Certificates ↗ page.
-
Turn on Always Use HTTPS.
To enable or disable Always Use HTTPS with the API:
- Make sure that your SSL/TLS encryption mode is not set to Off.
- Send a
PATCHrequest withalways_use_httpsas the setting name in the URI path, and thevalueparameter set to your desired setting ("on"or"off").
Cloudflare provides bot protection on all plans, with features that vary by plan tier. Turning on bot protection before configuring login-specific rules gives you a baseline filter against automated traffic across your entire domain.
Bot Fight Mode challenges requests that match known bot patterns. It applies to all traffic on your domain and cannot be customized with exceptions or path-specific rules.
-
In the Cloudflare dashboard, go to the Security Settings page.
Go to Settings -
Filter by Bot traffic.
-
Go to Bot fight mode.
-
Turn Bot fight mode on.
- Log in to the Cloudflare dashboard ↗, and select your account and domain.
- Go to Security > Bots.
- For Bot Fight Mode, select On.
Super Bot Fight Mode identifies traffic matching patterns of known bots, can challenge or block bots, and offers protection for static resources. You configure a separate action for each bot grouping: Definitely automated, Likely automated, and Verified bots. You can also configure exceptions using Application Security custom rules with the Skip action.
-
In the Cloudflare dashboard, go to the Security Settings page.
Go to Settings -
Filter by Bot traffic.
-
Go to Super Bot fight mode.
-
Turn Super Bot fight mode on.
-
Choose how your domain should respond to various types of traffic by selecting the associated edit icon:
- For more details on verified bots, refer to Verified Bots.
- For more details on supported file types, refer to Static resource protection.
- For more details on invisible code injection, refer to JavaScript detections.
- For more details on WordPress optimization, refer to Super Bot Fight Mode for WordPress.
-
Log in to the Cloudflare dashboard ↗, and select your account and domain.
-
Go to Security > Bots.
-
Select Configure Super Bot Fight Mode.
-
Choose how your domain should respond to various types of traffic:
- For more details on verified bots, refer to Verified Bots.
- For more details on supported file types, refer to Static resource protection.
- For more details on invisible code injection, refer to JavaScript detections.
- For more details on WordPress optimization, refer to Super Bot Fight Mode for WordPress.
For login protection, the following are recommended starting values. Adjust based on your traffic patterns.
- Definitely automated: Managed Challenge. After reviewing Security Events to confirm the setting does not affect legitimate traffic, switch to Block.
- Likely automated: Managed Challenge.
- Verified bots: Allow.
Custom rules are executed before Super Bot Fight Mode. To create exceptions for specific paths or traffic, create a custom rule with the Skip action. The Skip action allows the request to bypass the Super Bot Fight Mode phase without terminating the request, enabling it to continue through the rest of the security stack.
Two tools protect login endpoints from automated abuse, and they cover different attack vectors:
- Turnstile verifies that visitors are human without showing a CAPTCHA. It can be embedded into any website without sending traffic through Cloudflare. Use Turnstile to challenge automated form submissions.
- Application Security rate limiting rules define rate limits for requests matching an expression and the action to perform when those limits are reached. Use rate limiting to protect login endpoints from abuse, such as brute-force attacks.
Both together provide the strongest coverage. Turnstile challenges automated submissions at the form level. Rate limiting catches high-volume attacks that bypass or do not encounter the form, such as direct POST requests to the endpoint.
Implementing Turnstile involves three steps: create a widget, add the client-side snippet to your login form, and validate the token on your server. Turnstile supports multiple rendering methods including explicit and implicit rendering. You can also inject Turnstile into HTML using a Cloudflare Worker if you do not control the login form source code.
Turnstile is configured at the account level.
-
In the Cloudflare dashboard, go to the Turnstile page.
Go to Turnstile -
Select Add widget.
-
Fill out the required information:
- Widget name: A descriptive name for your widget.
- Hostname management: Domains where the widget will be used.
- Widget mode: Choose from Managed, Non-Interactive, or Invisible.
-
(Optional) Configure Pre-clearance support for single-page applications.
-
Select Create to save your widget.
-
Copy your sitekey and secret key, and store the secret key securely.
You need both the sitekey and secret key in the following steps.
Add the Turnstile script and widget container to your login form. Replace <YOUR-SITE-KEY> with the sitekey from the previous step.
<form id="login-form"> <input type="text" id="username" placeholder="Username" required /> <input type="password" id="password" placeholder="Password" autocomplete="off" required /> <div class="cf-turnstile" data-sitekey="<YOUR-SITE-KEY>"></div> <button type="submit">Log in</button></form>
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>The widget renders inside the div and produces a token when the visitor passes the challenge. When the form is submitted, a cf-turnstile-response token is included in the form data.
Before processing the form submission, send the token to the Turnstile siteverify endpoint to confirm the visitor passed the challenge.
const SECRET_KEY = "your-secret-key";
async function validateTurnstile(token, remoteip) { try { const response = await fetch( "https://challenges.cloudflare.com/turnstile/v0/siteverify", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ secret: SECRET_KEY, response: token, remoteip: remoteip, }), }, );
const result = await response.json(); return result; } catch (error) { console.error("Turnstile validation error:", error); return { success: false, "error-codes": ["internal-error"] }; }}Replace "your-secret-key" with your Turnstile secret key. The endpoint returns a JSON object with a success field. Only process the form submission if success is true.
For additional fraud detection, Turnstile supports Ephemeral IDs that provide a unique, temporary identifier for each visitor session without storing personal data.
For the complete response format, error codes, and examples in other languages, refer to Validate the token.
Turnstile provides test site keys that return predictable results without contacting the Siteverify API.
- Always passes: Use site key
1x00000000000000000000AAand secret key1x0000000000000000000000000000000AAto simulate a successful challenge. - Always blocks: Use site key
2x00000000000000000000ABand secret key2x0000000000000000000000000000000AAto simulate a failed challenge. - Forces interactive challenge: Use site key
3x00000000000000000000FFto test the interactive challenge flow.
For the full list of test keys and expected behaviors, refer to Test your Turnstile implementation.
The following example creates a rate limiting rule that issues a Managed Challenge after more than five POST requests to your login path from the same IP within one minute. Start with Managed Challenge rather than Block. Managed Challenge allows legitimate users who trigger the limit to pass by completing a challenge, while blocking automated traffic that cannot solve it. After monitoring Security Events to confirm the rule is not producing false positives, switch to Block. Adjust the path (/login), threshold, and period for your site.
-
In the Cloudflare dashboard, go to the Security rules page.
Go to Security rules -
Select Create rule and choose Rate limiting rules.
-
Enter a name for the rule (for example, "Rate limit login endpoint").
-
Under When incoming requests match, enter the following expression:
http.host eq "example.com" and http.request.uri.path eq "/login" and http.request.method eq "POST"Replace
example.comwith your domain and/loginwith your login endpoint path. -
Under With the same characteristics, verify that IP is selected. On Free plans, this is preset to IP.
-
Under When rate exceeds, enter 5 for Requests and select a value for Period. On Free plans, select 10 seconds. Pro and above plans offer additional periods. For available values by plan, refer to Rate limiting parameters.
-
Under Then take action, select an action from the Choose action dropdown. On Free plans, select Block. On Pro and above, Managed Challenge is recommended as it allows legitimate users who trigger the limit to pass by completing a challenge.
-
Under For duration, select a duration for the action. On Free plans, select 10 seconds. Pro and above plans offer longer durations. This is how long the action applies after the rate limit is triggered.
-
Select Deploy.
For sites that experience sustained credential stuffing campaigns, consider deploying multiple rate limiting rules with increasing severity. The Rate limiting best practices page describes an escalating penalty pattern that uses three rules: a short-window rule for quick bursts, a medium-window rule for slower distributed attacks, and a long-window rule that blocks persistent attackers from the entire domain. The counting expressions use response status codes, so successful logins do not count against the limit. Refer to the best practices page for the recommended thresholds and expression syntax.
Application Security custom rules and traffic detections give you additional signals beyond request rate to identify and act on suspicious login traffic. Detections populate request fields (such as leaked credential status and bot score) that your custom rules can then reference.
Leaked credentials detection scans incoming login requests for usernames and passwords that appear in known data breach databases. Cloudflare hashes credentials before comparison and does not store plaintext passwords. When a match is found, the detection populates fields you can use in custom rules and rate limiting rules.
The cf.waf.credential_check.password_leaked field is available on all plans.
On Free plans, the leaked credentials detection is enabled by default, and no action is required. On paid plans, you can turn on the detection in the Cloudflare dashboard, via API, or using Terraform.
-
In the Cloudflare dashboard, go to the Security Settings page.
Go to Settings -
(Optional) Filter by Detection tools.
-
Turn on Leaked credential detection.
- Log in to the Cloudflare dashboard ↗, and select your account and domain.
- Go to Security > Settings.
- Under Incoming traffic detections, turn on Leaked credentials.
Use a POST request similar to the following:
Required API token permissions
At least one of the following token permissions
is required:
Zone WAF WriteAccount WAF Write
curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/leaked-credential-checks" \ --request POST \ --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ --json '{ "enabled": true }'Use the cloudflare_leaked_credential_check resource to enable leaked credentials detection for a zone. For example:
resource "cloudflare_leaked_credential_check" "zone_lcc_example" { zone_id = "<ZONE_ID>" enabled = true}After turning on the detection, your origin server can receive leaked credential status via the Exposed-Credential-Check request header. To forward this header, turn on the Add leaked credentials checks header managed transform. Your origin can then trigger a password reset for affected users.
Before deploying rules that challenge or block login traffic, create a skip rule that exempts known legitimate automated traffic. This prevents your monitoring tools, health checks, and partner integrations from being blocked by the rules that follow.
-
In the Cloudflare dashboard, go to the Security rules page.
Go to Security rules -
Select Create rule and choose Custom rules.
-
Enter a name for the rule (for example, "Skip login rules for known clients").
-
Select Edit expression and enter an expression that matches your legitimate automated traffic. For example, to skip verified bots and a specific monitoring service IP:
(cf.client.bot) or (ip.src eq 198.51.100.1)Replace
198.51.100.1with the IP address of your monitoring service. Add additional conditions for other known clients. -
Under Then take action, select Skip. Under WAF components to skip, select the components that apply to your login protection rules (for example, All remaining custom rules and All rate limiting rules).
-
Select Deploy.
-
Under Place at, place the rule above your blocking and challenge rules. Custom rules execute in order, so the skip rule must come first.
For more information about the Skip action and available skip options, refer to Skip action.
Credential stuffing tools often send requests without standard browser headers or with known-bad User-Agent patterns. Create a custom rule that issues a Managed Challenge for POST requests to your login path where the User-Agent is empty. This targets direct POST requests from tools like curl, python-requests, or undici that do not set a User-Agent header.
-
In the Cloudflare dashboard, go to the Security rules page.
Go to Security rules -
Select Create rule and choose Custom rules.
-
Enter a name for the rule (for example, "Challenge empty UA on login").
-
Select Edit expression and enter:
(http.request.uri.path eq "/login" and http.request.method eq "POST" and len(http.user_agent) eq 0)Replace
/loginwith your login endpoint path. -
Under Then take action, select Managed Challenge.
-
Select Deploy.
Combine rate limiting with leaked credentials detection to throttle login attempts that use known-compromised passwords. This rule issues a Managed Challenge when the same IP sends more than three requests with leaked passwords within one minute.
-
On the Security rules page, select Create rule and choose Rate limiting rules.
Go to Security rules -
Enter a name for the rule (for example, "Rate limit leaked credentials").
-
Under When incoming requests match, enter the following expression:
http.request.uri.path eq "/login" and http.request.method eq "POST" and cf.waf.credential_check.password_leakedReplace
/loginwith your login endpoint path. -
Under With the same characteristics, verify that IP is selected. On Free plans, this is preset to IP.
-
Under When rate exceeds, enter 3 for Requests and select a value for Period. On Free plans, select 10 seconds.
-
Under Then take action, select an action. On Free plans, select Block. On Pro and above, Managed Challenge is recommended.
-
Under For duration, select a duration for the action. On Free plans, select 10 seconds.
-
Select Deploy.
After deploying the rules and configurations from the previous sections, monitor your login endpoint to verify the rules are working and to detect new attack patterns.
Security Events shows requests that Cloudflare security products acted on or flagged, including blocks, challenges, and skips.
-
In the Cloudflare dashboard, go to the Analytics page.
Go to Analytics -
Select the Events tab.
Review the Sampled logs to inspect individual requests. Each log entry shows the action taken, the rule that triggered, the source IP, user agent, URI path, and country. Use the Add filter button to narrow results by action, source IP, ASN, or other fields.
Look for false positives — legitimate traffic that your rules incorrectly challenged or blocked. Common signs include:
- Requests from known monitoring services or payment processors appearing in blocked events
- High volumes of challenged requests from countries where you have real users
- Rate limiting rules triggering on legitimate users during peak traffic
If you see legitimate users being affected, adjust your rate limiting thresholds or add skip rules for specific IP ranges.
Set up a Security Events Alert notification to receive alerts when security event volume spikes, giving you early warning of a new attack campaign. This notification is in the WAF category of the Notifications page. For setup instructions, refer to Create a notification. Enterprise customers can use Advanced Security Events Alert for more granular filtering.
Bot traffic analytics show bot score distribution on your login endpoint over time. A sudden spike in low-score traffic (scores 1-29) on your login path is an early signal of a credential stuffing campaign.
Cloudflare classifies bot traffic into categories based on bot scores and verification status:
- Verified bots: Crawlers and services that Cloudflare has confirmed as legitimate, such as Googlebot, Bingbot, and uptime monitors. Cloudflare maintains a verified bot list with strict requirements.
- Automated (score 1): Cloudflare is quite certain the request is automated.
- Likely automated (scores 2-29): Probably a bot. This category and Automated are the primary targets for security rules, including scrapers, credential stuffing tools, and spam submitters.
- Likely human (scores 30-99): These requests appear to come from real users. Do not challenge or block this traffic.
-
In the Cloudflare dashboard, go to Security > Analytics > Bot analysis.
-
Review the traffic distribution across the bot score groupings above.
If you see sustained automated traffic reaching your login endpoint despite the rules deployed in this guide, review the Security features interoperability page to verify your rules are executing in the expected order, and consider adjusting thresholds.
Application Security
- Rate limiting best practices — recommended patterns for login protection and credential stuffing
- Custom rules — create rules using request fields including bot score and leaked credentials
- Leaked credentials detection — scan incoming requests for credentials from known data breaches
- Security Events — review requests acted on by security products
Cloudflare Bots
- Bot Fight Mode — free bot protection that challenges known bot patterns
- Super Bot Fight Mode — Pro and Business bot protection with configurable actions
- Bot Management — Enterprise bot protection with ML-powered scoring and custom rules
Turnstile
- Get started with Turnstile — create widgets and implement client-side and server-side validation
- Server-side validation — validate Turnstile tokens on your server
- Turnstile Pre-Clearance — pre-clear visitors for SPA and AJAX login flows
SSL/TLS
- Always Use HTTPS — redirect all HTTP requests to HTTPS
- HTTP Strict Transport Security (HSTS) — prevent browser downgrade attacks with HSTS headers