Try 14 days free
Skip to content

Cloudflare Bot Fight Mode breaks your WooCommerce filter

A WooCommerce filter that returns nothing, hangs on a spinner, or gets a blank response from admin-ajax.php is often not a plugin bug. WooCommerce’s own support team calls Cloudflare Bot Fight Mode blocking that endpoint “known and expected behavior.” After hydration, InstantFilter sends no request to admin-ajax.php at all, so there is nothing on that URL for Bot Fight Mode to challenge.

What does Cloudflare Bot Fight Mode actually do to admin-ajax.php?

Bot Fight Mode and Super Bot Fight Mode score requests and challenge or block the ones scored as automated. WooCommerce staff, answering a support thread titled “Fight Bot Mode In Cloudflare breaks Action Scheduler”, confirmed this is not an edge case: “This feature can block or challenge loopback and REST API requests, which WooCommerce’s Action Scheduler depends on to run background tasks. When those requests are blocked, scheduled actions become past due.” The scoring applies per URL, not per use case — a loopback request from Action Scheduler and a facet click from a shopper’s browser can both land on /wp-admin/admin-ajax.php, and Cloudflare has no built-in way to tell them apart.

If you are searching admin-ajax.php 403 cloudflare or cloudflare bot fight mode breaks woocommerce filter, this is that collision. The filter plugin issues a normal AJAX request. Cloudflare’s edge, sitting in front of every request including that one, decides it looks automated enough to block or present a challenge page instead of forwarding it to WordPress. The shopper sees a spinner that never resolves, an empty result grid, or a console error instead of a filtered product list.

How do you confirm it’s Cloudflare and not the filter plugin?

Two checks, in order. First, log into wp-admin and look for WooCommerce’s own warning banner: Action Scheduler: 11 past-due actions found; something may be wrong. That exact notice, reported verbatim in the support thread above, is WordPress telling you its own background jobs cannot complete — a strong signal that something between the server and the request is interfering, independent of which filter plugin runs on the storefront. Second, open Cloudflare’s dashboard under Security → Events and filter for the path /wp-admin/admin-ajax.php. A row showing “Blocked” or “Managed Challenge” at the same timestamps shoppers report broken filters is the direct confirmation — the request never reached PHP, so no amount of plugin debugging on the WordPress side will explain it.

This is also why the symptom reads as “broken,” not “slow.” A request that gets 200 after three seconds is slow. A request that gets a Cloudflare challenge page, a 403, or a silently dropped connection looks to the filter’s JavaScript like the server is down, because as far as that XHR is concerned, it is.

What exactly shows up in DevTools when the request is blocked?

Open the Network panel, click a filter attribute, and look at the request to admin-ajax.php. A plugin bug usually still returns a 200 with malformed JSON, or a 500 with a PHP stack trace in the response body. A Cloudflare block looks different: a 403 with an HTML body instead of JSON, a 503 carrying a cf-mitigated: challenge response header, or a managed-challenge page served where the filter’s JavaScript expected a product list. None of that body ever touched WordPress, so searching the PHP error log or enabling WP_DEBUG turns up nothing, because there is nothing on the WordPress side to log.

One diagnostic trap worth naming: running wp action-scheduler run over SSH can report success even while the live site is blocked. WP-CLI executes locally on the server and calls the scheduler’s code directly — it never travels through Cloudflare’s edge the way a shopper’s browser request does. A clean CLI run is evidence the scheduler code itself works. It is not evidence that a real AJAX request from a browser, which does cross the edge, gets through.

Why can’t you just switch to “a less aggressive setting” on every plan?

Because that option does not exist on every plan. In the same thread, the store owner pointed out that Cloudflare’s Free plan only offers the basic Bot Fight Mode toggle: on or off, with no intermediate aggressiveness slider and no custom Firewall Rules to carve out an exception. Super Bot Fight Mode, which does expose tuning and a dedicated “Optimize for WordPress” switch, is documented by Cloudflare itself as available to Super Bot Fight Mode customers — a paid-tier feature, not something every Free-plan site can enable. A fix written for a Pro or Business account can be a dead end for a site on Cloudflare Free, which is exactly what happened in that thread: allow-listing an IP or writing a Firewall Rule needed a plan upgrade the store didn’t have. Checking which plan a site runs on, before recommending a fix, saves a round trip with the client or the host.

What’s the actual fix — allow-list, firewall rule, or Optimize for WordPress?

WooCommerce support’s own fix list, in order of what’s available per plan:

1. Allow-list your server’s IP in Cloudflare, if that IP is static. The thread’s own follow-up flags the catch: “if your server’s IP isn’t static, allow-listing it won’t be reliable since the rule would break as soon as the IP changes.”

2. Create a Firewall Rule (WAF custom rule on current Cloudflare dashboards) to bypass bot checks specifically for /wp-admin/admin-ajax.php, /wp-json/, and /wp-cron.php — the three paths named explicitly in WooCommerce’s recommended fix.

3. On Super Bot Fight Mode, turn on “Optimize for WordPress” under Security → Bot traffic. Cloudflare’s own documentation describes exactly this collision: “automated loopback requests made by your WordPress site will be authorized even when Super Bot Fight Mode blocks other bots” — while noting loopback requests can still be blocked separately by I’m Under Attack Mode or other custom WAF rules layered on top.

Resolving this at the server and host level is worth doing regardless of filter plugin: the thread’s final working setup combined a self-managed server-side cron job with the three-path Cloudflare bypass rule, after which Action Scheduler ran cleanly with Bot Fight Mode re-enabled. Disabling Bot Fight Mode entirely, the first instinct in that thread, removes the bot protection the site presumably wanted in the first place — the scoped bypass is the fix that keeps both working.

Does this affect InstantFilter the same way?

Not on the part a shopper clicks. After the archive hydrates, InstantFilter filters in the browser against the codebook it already downloaded — no XHR to admin-ajax.php, no REST call, nothing on that URL for Bot Fight Mode to score. A facet click that previously depended on Cloudflare correctly classifying an AJAX request as legitimate traffic now depends on nothing from Cloudflare at all, because the request doesn’t exist.

The sync step that builds that codebook is a different case worth being precise about: it runs from inside wp-admin while you are logged in, which is a different risk profile than an anonymous shopper’s facet click, but Cloudflare’s rules still apply site-wide unless /wp-admin/ paths are separately excluded. If Action Scheduler or wp-admin AJAX calls are already being blocked site-wide, the same Cloudflare bypass described above — covering /wp-admin/admin-ajax.php, /wp-json/, and /wp-cron.php — is still the fix, independent of which filter architecture runs on the storefront.

Keep going

A blocked request and a slow request look similar from the storefront. These pages cover the rest of the request.

Questions about Cloudflare blocking WooCommerce filters

WooCommerce support calls it known and expected behavior, not a bug on either side. Bot Fight Mode scores the URL, and admin-ajax.php is shared by Action Scheduler, REST requests, and AJAX filter plugins alike.
Custom WAF Firewall Rules and the Super Bot Fight Mode “less aggressive” setting are tied to paid Cloudflare plans. On Free, allow-listing a static server IP or disabling Bot Fight Mode are the more limited options.
It resolves the symptom but removes the bot protection you enabled it for. A scoped bypass for /wp-admin/admin-ajax.php, /wp-json/, and /wp-cron.php fixes the collision without turning off protection site-wide.
Not for the filter click itself — that click never calls admin-ajax.php after hydration. A site-wide Cloudflare block on wp-admin AJAX can still affect the sync step, like it affects any other WordPress background task.

Ready to make filtering instant?

Download the free 14-day trial of Pro. No credit card required — test immediately.