Guide

How to Geo-Target Ads & Filter Invalid Traffic by IP

Segment by country, region and city for creative — and filter datacentre invalid traffic — from one lookup.

You can pick the right regional creative and filter out non-human datacentre traffic from a single IP lookup — before you spend a cent serving an impression. The response gives you country, region and city for segmentation, and a connection type that flags hosting/datacentre origins where invalid traffic concentrates.

Python

The examples here are Python, standard library only — but the same logic maps directly onto our official SDKs for TypeScript, Go, Ruby, Java and 7 more. Field paths and the worked outputs below are all verified against the live API.

1Get a key and call the API securely

Create a free account here — 2,000 lookups/day, no card. Send the key as an Authorization: Bearer header from an environment variable, keeping it out of URLs and logs:

Python
import os, urllib.request, json

API_KEY=***  # export it; never hardcode

def lookup(ip):
    req = urllib.request.Request(
        f"https://api.ipwho.org/ip/{ip}",
        headers={"Authorization": f"Bearer {API_KEY}", "User-Agent": "MyApp/1.0"},
    )
    with urllib.request.urlopen(req, timeout=10) as resp:
        return json.loads(resp.read())["data"]

2Segment by geography and flag invalid traffic:

Use geoLocation.country / region / city to choose regional creative, and treat a Corporate connection type as a strong invalid-traffic (IVT) signal — ad impressions from cloud and hosting ranges are very often non-human. One caveat: Corporate also includes office and campus networks with real people, so pair it with the VPN/Tor flags and your own frequency rules rather than hard-excluding on network type alone:

Python
def ad_segment(data):
    geo  = data.get("geoLocation") or {}
    conn = data.get("connection") or {}

    # Datacentre/hosting origins are where most invalid (non-human) traffic sits
    invalid = conn.get("connection_type") == "Corporate"
    return {
        "country": geo.get("countryCode"),
        "region":  geo.get("region"),
        "city":    geo.get("city"),
        "invalid_traffic": invalid,
        "serve_ads": not invalid,
    }

print(ad_segment(lookup("91.0.0.1")))

3Serve or filter — the full script:

Drop the datacentre impressions before you pay for them, and route everyone else to the right regional creative. Note that region and city can be null on some IPs — fall back to country-level targeting when they are:

Python
#!/usr/bin/env python3
"""Geo-segment + invalid-traffic filter from an IP (IPWho IP geolocation API)."""
import os, sys, urllib.request, json

API_KEY=*** lookup(ip):
    req = urllib.request.Request(
        f"https://api.ipwho.org/ip/{ip}",
        headers={"Authorization": f"Bearer {API_KEY}", "User-Agent": "IPWho-Ads/1.0"},
    )
    with urllib.request.urlopen(req, timeout=10) as resp:
        return json.loads(resp.read())["data"]

def ad_segment(data):
    geo  = data.get("geoLocation") or {}
    conn = data.get("connection") or {}
    invalid = conn.get("connection_type") == "Corporate"
    return {
        "country": geo.get("countryCode"),
        "region":  geo.get("region"),
        "city":    geo.get("city"),
        "invalid_traffic": invalid,
        "serve_ads": not invalid,
    }

if __name__ == "__main__":
    ip = sys.argv[1] if len(sys.argv) > 1 else "91.0.0.1"
    print(f"{ip}: {ad_segment(lookup(ip))}")
Output
$ python3 ads.py 91.0.0.1        # Germany, residential
91.0.0.1: {'country': 'DE', 'region': 'North Rhine-Westphalia', 'city': 'Düsseldorf', 'invalid_traffic': False, 'serve_ads': True}

$ python3 ads.py 76.102.11.203   # California, residential
76.102.11.203: {'country': 'US', 'region': 'California', 'city': 'Los Altos', 'invalid_traffic': False, 'serve_ads': True}

$ python3 ads.py 52.95.110.1     # AWS datacentre -> filtered
52.95.110.1: {'country': 'US', 'region': None, 'city': None, 'invalid_traffic': True, 'serve_ads': False}

Start with a free API key

Free tier: 2,000 lookups/day, no card. Paid plans from $2.50/month. Full field reference here, or see the ad-targeting use case here.