Country is an estimate derived from a network address
A country field in a visitor report is usually an estimate made by looking up an IP address in a geolocation database. It is not a browser-reported identity, a GPS coordinate, or proof of where a person lives. VPNs, corporate gateways, mobile carrier routing, and database coverage can all make the result differ from someone's physical location.
The address being looked up matters just as much as the database. When traffic passes through a CDN or reverse proxy, the origin server's TCP peer is often the proxy. If GeoIP runs against that peer address, it may classify the CDN edge instead of the original visitor.
Cloudflare documents that a proxied origin normally sees a Cloudflare address and that the original visitor address is sent in `CF-Connecting-IP`. It also documents that Nginx needs its real-IP module and trusted proxy configuration to use that header. The safe rule is to trust the header only when the request came from a proxy range you control.
Restore the visitor address only from trusted proxy networks
For Nginx behind Cloudflare, keep the current Cloudflare IPv4 and IPv6 ranges in a managed include. The include should contain one `set_real_ip_from` entry per published CIDR; generate and refresh it from Cloudflare's official IP range list rather than copying a static list into an article.
# In the http context, after creating a maintained include containing
# set_real_ip_from entries for Cloudflare's current IPv4 and IPv6 ranges:
include /etc/nginx/cloudflare-realip.conf;
real_ip_header CF-Connecting-IP;
geoip2 /var/lib/geo/country.mmdb {
$visitor_country country iso_code;
}
server {
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Visitor-Country $visitor_country;
proxy_pass http://127.0.0.1:3000;
}
}This is a placement example, not a complete server configuration. Use the real-IP module supported by your Nginx build, confirm the include is loaded in the correct context, and restrict direct origin access where practical. Never add `set_real_ip_from 0.0.0.0/0` or trust arbitrary forwarding headers: a direct client could then claim someone else's address. Keep the Cloudflare range file current when their published ranges change.
- Check `nginx -V` for the real-IP module, then review the active configuration with `nginx -T` without sharing unrelated configuration or secrets.
- Run `nginx -t` before reloading. A syntax check does not prove the trusted CIDRs or header behavior are correct.
- Send a test request through the actual CDN path and verify the address Nginx uses after real-IP processing. Do not rely on a direct-origin test to validate a Cloudflare request path.
- After the address is restored, verify one synthetic visitor event and the resulting country code. Avoid keeping raw client IPs in permanent logs just for this test.
Keep the reported location coarse and honest
A country database has its own coverage and update limits. DB-IP describes its free Country Lite database as a reduced subset with lower coverage and accuracy than its commercial databases. Even with the correct client IP, country should remain a directional geography signal. Do not use it to identify a company or person, verify a user's address, enforce legal eligibility, or make a high-impact decision.
WhoVisited stores a validated two-letter country code on the visitor record; it does not store the raw IP as part of the event. The ingestion route takes an `X-WhoVisited-Country` header from the server, and Nginx is intended to overwrite that value using GeoIP. The application ignores malformed codes and `ZZ`. A missing or stale country can remain until another accepted event provides a usable code.
There is also a current hosted-service limitation to disclose. On 2026-11-03 we checked WhoVisited's public Cloudflare-routed site and the active origin Nginx configuration: GeoIP2 reads `$remote_addr`, but the active config has no `set_real_ip_from` or `real_ip_header` directives. That means the country lookup may be using a Cloudflare edge address instead of the visitor's. Until this trusted-proxy configuration is corrected and verified, treat WhoVisited country values as unreliable. This is a service-side configuration issue; adding an origin to your website's WhoVisited allowlist does not fix it.
Because the code stores only country rather than the address, historical events cannot be accurately re-geolocated after the proxy configuration changes. Later accepted events can update a visitor's country with the corrected lookup; old page-view events do not contain an IP that can be replayed.
Test the full trust chain before acting on a report
- Confirm the DNS record is actually proxied through the CDN you intend to trust, and confirm requests reach the expected origin server.
- Check the CDN's current published proxy ranges and the active Nginx include; confirm only those ranges are trusted for the replacement header.
- Make a synthetic visit through the public hostname from a network whose country you can reasonably identify. Check one country code after collection and avoid recording or sharing the raw IP.
- Repeat from a VPN or another network if available. Differences can reveal routing or database effects, but they do not prove which location is the visitor's home.
- Use country only for coarse report segmentation. If the value is unexpected, investigate proxy configuration and database freshness before drawing a marketing conclusion.
For the exact behavior of your own stack, inspect the active server configuration rather than relying on a template file in source control. Cloudflare's [original visitor IP guide](https://developers.cloudflare.com/support/troubleshooting/restoring-visitor-ips/restoring-original-visitor-ips/) and Nginx's [real-IP module reference](https://nginx.org/en/docs/http/ngx_http_realip_module.html) explain the trusted-proxy step. DB-IP documents the [Country Lite database limitations](https://db-ip.com/db/lite.php). WhoVisited's [visitor tracking guide](https://whovisited.net/guides/website-visitor-tracking) explains what a visitor record represents.