Skip to main content

Cloudflare for WordPress: Plugin and Optimal Settings

Cloudflare · 19.04.2026 · 4 min read
Illustration for “Cloudflare for WordPress: Plugin and Optimal Settings”

WordPress requires special configuration when using Cloudflare. Without proper setup, the server logs will record Cloudflare's IP instead of the visitor's real IP.

The IP address problem

Without configuration, WordPress sees all requests coming from Cloudflare IPs (~103.21.244.0/22 and others). This breaks geolocation, anti-spam, and security plugins.

Solution 1: Official Cloudflare plugin

Install the "Cloudflare" plugin (official) → connect it to your account via an API Token. The plugin automatically restores the real IPs.

Solution 2: Manually in wp-config.php

// Restore the real IP from Cloudflare
if (isset($_SERVER['HTTP_CF_CONNECTING_IP'])) {
    $_SERVER['REMOTE_ADDR'] = $_SERVER['HTTP_CF_CONNECTING_IP'];
}

Optimal Cloudflare settings for WordPress

SettingRecommended value
SSL/TLS ModeFull (Strict)
Always Use HTTPS✅ On
Auto MinifyJS + CSS + HTML
Rocket LoaderTest before enabling
Bot Fight Mode✅ On
Cache LevelStandard

Cache auto-purge on publish

The official Cloudflare plugin automatically purges the page cache when:

  • A post is published / updated
  • Site settings are changed
  • Plugins are updated

WooCommerce + Cloudflare

# Cache Rule — bypass cache for WooCommerce
Conditions:
  - Cookie contains: woocommerce_cart_hash
  - OR Cookie contains: woocommerce_session_
  - OR Path contains: /cart
  - OR Path contains: /checkout
  - OR Path contains: /my-account

Cache: Bypass
⚠️ Without these exclusions for WooCommerce, different users may see someone else's cart.
✅ Add to wp-config.php: define('FORCE_SSL_ADMIN', true); when using Cloudflare SSL.

Common problems explained

An infinite redirect loop (ERR_TOO_MANY_REDIRECTS)

This happens when SSL/TLS Mode is set to Flexible while WordPress is also forcing HTTPS (a plugin or FORCE_SSL_ADMIN). Flexible mode means the connection from Cloudflare to the server runs over HTTP, the server sees the request as HTTP and redirects to HTTPS again — that creates a loop. The fix: switch SSL/TLS Mode to Full or Full (Strict) and confirm the server actually has an SSL certificate configured.

Security plugins see Cloudflare's IP instead of the real one

If restoring the real IP has not been set up (neither by the plugin nor manually), WordPress logs and security plugins (Wordfence, anti-spam, geoIP) show one of Cloudflare's own IP ranges. This breaks IP blocking, geo-targeting, and visit statistics. Make sure the server and WordPress read the CF-Connecting-IP header instead of using REMOTE_ADDR directly.

Verifying the real IP is restored

// Add temporarily to a template for diagnostics
echo 'REMOTE_ADDR: ' . $_SERVER['REMOTE_ADDR'];
echo 'CF-Connecting-IP: ' . ($_SERVER['HTTP_CF_CONNECTING_IP'] ?? 'no header');

If both values match and equal the visitor's real IP (not a Cloudflare range), the restoration is set up correctly. Cloudflare's own IP ranges are published at cloudflare.com/ips and updated periodically — worth checking against if the server keeps its own allowlist of trusted proxies.

When the standard setup is not enough

  • The site sits behind several CDNs or proxies before Cloudflare (for example, also a corporate load balancer) — then the whole X-Forwarded-For chain needs parsing, not just Cloudflare's header.
  • You need IP blocking at the server's own firewall level (iptables/CSF), not just in WordPress — then the server must trust only Cloudflare's ranges as the source of incoming connections on 80/443.
  • A custom caching plugin is in use that does not support auto-purge through the Cloudflare API — then cache auto-purge on publish will not work, and for WooCommerce it is better to set up a cache bypass with a separate Cache Rule with a short TTL.

Connecting the official plugin to an account needs an API Token with zone-edit permissions (Zone.Zone and Zone.Cache Purge), not a Global API Key — a Global API Key gives the plugin access to every zone on the account at once, which is excessive and unsafe for a single site.

If the WordPress site already runs its own caching plugin (WP Rocket, W3 Total Cache, LiteSpeed Cache), it is important to separate responsibilities: the server-side plugin caches HTML and objects at the PHP level, while Cloudflare caches static assets at the CDN level. A conflict appears when both try to cache HTML pages at once without one shared invalidation mechanism — after a content update, a stale version can then show up from one cache or the other.

For a WordPress Multisite install across several domains, the official Cloudflare plugin is connected once in the network admin, but the cache auto-purge rule on publish applies individually to the zone of the site where the publish happened — it does not touch the other sites in the network.

Was this article helpful?
← Back to Knowledge Base Ask Support