How to Log the Real Visitor IP Address When Using Cloudflare

If you accept connections from websites or API running behind Cloudflare, there’s a hidden “gotcha” you must know about:

By default, your end-point server will NOT see the real end-user’s IP address.

Instead, every incoming request appears to come from a Cloudflare data center.
This impacts:

  • Abuse prevention (rate limiting)
  • Accurate analytics
  • Geo-targeting
  • Any IP-based feature or logging

Why?

Cloudflare acts as a reverse proxy, routing all traffic through their global edge network.
Your server’s REMOTE_ADDR variable now reflects the Cloudflare node—not your actual visitor.


The Solution: Use the Special HTTP Header

Cloudflare automatically sends the true client IP in the CF-Connecting-IP HTTP header.

To reliably log and process the real user’s IP in PHP, use this snippet:

function getRealIp() {
// Prefer Cloudflare's header if present
if (!empty($_SERVER['HTTP_CF_CONNECTING_IP'])) {
return $_SERVER['HTTP_CF_CONNECTING_IP'];
}
// Optionally support generic proxies
if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
return explode(',', $_SERVER['HTTP_X_FORWARDED_FOR'])[0];
}
// Fallback to server-provided address
return $_SERVER['REMOTE_ADDR'] ?? 'UNKNOWN';
}

Best Practices:

  • Use this getRealIp() helper everywhere you log, rate-limit, or analyze IP addresses.
  • If you use other CDNs or reverse proxies, check their docs for equivalent headers.
  • Do not trust X-Forwarded-For unless you control all proxy hops—it can be spoofed by end users.

Why This Matters:

  • Without this fix: All requests appear to originate from Cloudflare, making IP-based abuse detection and analytics impossible.
  • With this fix: You’ll always have the real end-user IP, whether you’re behind Cloudflare or not.

Resources:


TL;DR:
When accounting for Cloudflare, always log and use the IP from CF-Connecting-IP, not just REMOTE_ADDR.
It’s a simple fix that saves hours of debugging and improves your site’s security and analytics.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *