How to Get a User's IP Address and Location in WordPress (2026)
Get a visitor's IP and location in WordPress three ways: my free User IP and Location plugin (no code), custom PHP with $_SERVER, or WooCommerce's WC_Geolocation. Plus Cloudflare, localhost and GDPR.

You can get a visitor's IP and location in WordPress three ways: a plugin, custom PHP, or WooCommerce. The no-code route is my free User IP and Location plugin, which gives you IP, city, country, browser, and conditional content through shortcodes. For developers, $_SERVER['REMOTE_ADDR'] returns the IP, but behind Cloudflare or a proxy you must read the forwarded header instead. Remember an IP is personal data under GDPR.
Getting a visitor's IP in WordPress sounds like one line of code.
It is. Right up until your site goes behind Cloudflare. Or a caching plugin serves everyone the same page. Or you want the location, not just the number.
I have hit all three. So I built a plugin for it: User IP and Location, free on WordPress.org. Every tool I tried back in 2018 either broke my caching or cost too much for what it did.
The one line works. Getting it right behind a proxy, on a cached page, and inside the law is the actual job.
This guide covers all three honest routes:
- My plugin for the no-code path.
- Custom PHP for developers.
- WooCommerce's built-in class if you already run a store.
Then the things that trip people up: Cloudflare showing the wrong IP, localhost returning 127.0.0.1, and what GDPR means for storing an IP.
Why would you need a visitor's IP?
A quick reality check before the how-to, because the method depends on what you are doing with it.
- Personalisation: show location-specific pricing, currency, shipping, or offers.
- Fraud and spam checks: flag orders or sign-ups where the IP country does not match the billing details.
- Security: log and rate-limit suspicious IPs, or block abusive ones.
- Analytics: understand where your audience actually is.
The job decides the method. If you just need the raw number, code is fine.
Want IP plus location, browser, and content that changes by country? A plugin saves you a lot of work.
The three methods at a glance
| Method | Code? | Best for |
|---|---|---|
| 1. User IP and Location plugin | No | IP + location + conditional content |
| 2. Custom PHP | Yes | Developers who want the raw IP |
| 3. WooCommerce WC_Geolocation | Yes | Stores already running WooCommerce |
Method 1
The User IP and Location plugin (no code)
Best for: Anyone who wants IP, location, and conditional content without writing PHP, on a cached site.
Full disclosure: this is my plugin.
I built User IP and Location to fix the exact problems I kept hitting: tools that broke my page caching, or cost too much for what they did.
I still run it on every site I manage. It is free, and actively maintained.
It pulls the visitor's IP and full geolocation: city, country, ISP, timezone, currency, browser, OS. Any value prints through a shortcode.
The Your Info tab shows exactly what it detects for the current visitor:

How to set it up
- Go to Plugins → Add New, search User IP and Location, then install and activate it.
- That is it for defaults. It works out of the box on the free ip-api tier, no key needed.
- Drop a shortcode wherever you want a value, for example
[userip_location type="ip"]or[userip_location type="country"].
The shortcodes
There are 20+ shortcodes for every field, plus local time and date. The Shortcodes tab lists them all with copy-ready examples:

| Value | Shortcode |
|---|---|
| IP address | [userip_location type="ip"] |
| Country | [userip_location type="country"] |
| City | [userip_location type="city"] |
| Currency | [userip_location type="currency"] |
| Browser | [userip_location type="browser"] |
| Local time | [userip_localtime] |
Conditional content by location
This is the part I use most: show or hide content by country, region, or city.
[userip_conditional country="US"]
🇺🇸 Free shipping on US orders over $50!
[/userip_conditional]
[userip_conditional country="IN"]
🇮🇳 Free shipping on orders above ₹2,000!
[/userip_conditional]Why it works with caching
The plugin renders through AJAX by default. So a cached page loads instantly, and the personalised value fills in a moment later.
Search engines see your static cached HTML. Visitors see the personalised version. Best of both.
Keep that cache on. It is the first lever in speeding up WordPress, and personalisation should never cost you it.
If a shortcode needs to sit inside a form or feed, switch that one to server-side rendering in the settings.
Method 2
Custom PHP
Best for: Developers who want the raw IP in code, with proxy handling done right.
If you would rather write code, PHP exposes the visitor IP through the $_SERVER superglobal. Start simple, then make it production-ready.
The basic version returns the connecting IP:
function tgx_get_ip_basic() {
return $_SERVER['REMOTE_ADDR'];
}REMOTE_ADDR is the most trustworthy source. It is the actual connection, and hard to spoof.
Every other header is a hint, not a fact. The catch is proxies and CDNs. If your site sits behind Cloudflare or a load balancer, REMOTE_ADDR is their IP, and the real visitor sits in a forwarded header.
Here is a version that handles that, and validates the result so a spoofed header can't slip through:
function tgx_get_visitor_ip() {
$keys = [
'HTTP_CF_CONNECTING_IP', // Cloudflare
'HTTP_X_FORWARDED_FOR', // generic proxy / load balancer
'HTTP_X_REAL_IP',
'REMOTE_ADDR', // direct connection
];
foreach ( $keys as $key ) {
if ( empty( $_SERVER[ $key ] ) ) {
continue;
}
// X-Forwarded-For can be a list; the first is the client.
foreach ( explode( ',', $_SERVER[ $key ] ) as $ip ) {
$ip = trim( $ip );
if ( filter_var( $ip, FILTER_VALIDATE_IP ) ) {
return $ip;
}
}
}
return '';
}Only trust forwarded headers if your site genuinely sits behind a proxy you control, otherwise a visitor can fake them. On a direct server, stick to REMOTE_ADDR.
Never trust a client IP for anything security-critical. A header you did not set can be forged, so use it for personalisation and logging, never as the lock on the door.
Method 3
WooCommerce WC_Geolocation
Best for: Stores already running WooCommerce that just need the country.
Already on WooCommerce? You do not need anything extra.
Its built-in WC_Geolocation class returns the IP and geolocates the country, using the database WooCommerce already maintains.
$ip = WC_Geolocation::get_ip_address();
$geo = WC_Geolocation::geolocate_ip();
$country = $geo['country']; // e.g. "US"It is free, already there, and handles proxies for you. The limit is that it is country-level only and tied to WooCommerce. For city, ISP, browser, or conditional content, use Method 1 or a fuller geolocation source.
Which method should you choose?
For most people, the plugin is the answer: IP, full location, and conditional content with no code, and it survives caching.
Use custom PHP when you are a developer who wants the raw IP inside your own logic. Use WC_Geolocation when you already run WooCommerce and only need the country.
Common issues that trip people up
- Cloudflare shows the wrong IP. A CDN or proxy sits in front of your server, so
REMOTE_ADDRis its IP. ReadCF-Connecting-IP(Cloudflare) orX-Forwarded-For, as in Method 2, or use a plugin that already does. - Localhost returns
127.0.0.1. That is your own machine, and a private address cannot be geolocated. Test on a live, public site to see real values. - Caching shows one visitor's data to everyone. If you print the IP server-side on a cached page, every visitor sees the first cached value. Render through AJAX (the plugin's default) so each visitor gets their own.
An IP is personal data, treat it that way
Under GDPR, an IP address counts as personal data.
So if you collect or store it, you need a lawful basis and a line in your privacy policy covering it. For analytics, anonymise or truncate it where you can, and never keep full IPs longer than you need.
Final take
Getting a visitor's IP in WordPress is easy. Getting it right means handling proxies, caching, and privacy.
Want it without code? Install User IP and Location. It is free, I maintain it, and it is built for cached sites.
Writing code? Use the proxy-aware PHP above, and validate the result.
Either way, the IP is personal data. Treat it that way.
Need custom WordPress functionality built right?
Geolocation, custom plugins, performance, security, the kind of WordPress work that has to keep working after every update. Send us what you are trying to build. The first reply comes from Sunny, who wrote the plugin above.
See WordPress developmentCommon questions
How do I get a visitor's IP address in WordPress?
The no-code way is a plugin like my free User IP and Location, which prints the IP with a shortcode. In code, $_SERVER['REMOTE_ADDR'] returns the connecting IP, but behind Cloudflare or a load balancer you read the forwarded header instead and validate it.
Is $_SERVER['REMOTE_ADDR'] reliable in WordPress?
It is the most reliable single source, because it is the actual connecting IP and is hard to spoof. The catch is proxies and CDNs: if your site sits behind Cloudflare or a load balancer, REMOTE_ADDR shows their IP, so you read the forwarded header for the real visitor.
Why does my WordPress site show the wrong IP (Cloudflare)?
Cloudflare and other proxies sit between the visitor and your server, so REMOTE_ADDR is Cloudflare's IP, not the visitor's. The real IP is in the CF-Connecting-IP header (or X-Forwarded-For). Read that header, or use a plugin that already handles it.
Why does my local site return 127.0.0.1?
127.0.0.1 is localhost, your own machine. On a local install there is no external visitor, so that is expected, and a private address cannot be geolocated. Test IP and location code on a live, public site to see real values.
Is collecting a visitor's IP address legal under GDPR?
An IP address is personal data under GDPR, so collecting it needs a lawful basis and a mention in your privacy policy. For analytics, anonymise or truncate it where you can, and avoid storing full IPs longer than you need.
Can I show different content based on a visitor's country?
Yes. The User IP and Location plugin does this with a conditional shortcode, for example [userip_conditional country="US"]…[/userip_conditional], so you can show country-specific pricing, shipping, or offers. In code, look up the country from the IP and branch on it.

SEO Specialist and product builder with 10+ years in search. The notes come from the work, not the theory.