IP Geolocation — Country, City, ISP, CSV, No API Key, Bulk
Pricing
Pay per usage
IP Geolocation — Country, City, ISP, CSV, No API Key, Bulk
20 runs. IP intel as CSV/JSON — country, region, city, ISP, ASN, timezone, lat/lon, isMobile/isProxy flags. Accepts IPs + domains. Backed by 951-run Trustpilot flagship + 31-actor portfolio. For fraud + ad-targeting + GDPR audits. spinov001@gmail.com · blog.spinov.online · t.me/scraping_ai
Pricing
Pay per usage
Rating
0.0
(0)
Developer
Alex
Actor stats
0
Bookmarked
2
Total users
0
Monthly active users
3 days ago
Last modified
Categories
Share
IP Geolocation Lookup — Bulk IP & Domain → Country, ISP, ASN
Resolve a list of IPv4 addresses (and/or domain names) to country / region / city / ISP / ASN / mobile / proxy / hosting flags using the public ip-api.com JSON API. Domain inputs are first resolved to A records via Google DNS, then each resolved IP is looked up.
Verified against src/main.js — every output field below is what the actor actually pushes.
What you get per IP (24 fields)
| Field | Type | Example | Source |
|---|---|---|---|
ip | string | 8.8.8.8 | ip-api query |
continent | string | North America | ip-api continent |
continentCode | string | NA | ip-api continentCode |
country | string | United States | ip-api country |
countryCode | string | US | ip-api countryCode |
region | string | California | ip-api regionName (full name) |
regionCode | string | CA | ip-api region (code) |
city | string | Mountain View | ip-api city |
zip | string | 94043 | ip-api zip |
latitude | number | 37.386 | ip-api lat |
longitude | number | -122.084 | ip-api lon |
timezone | string | America/Los_Angeles | ip-api timezone |
utcOffset | number | -25200 | ip-api offset (seconds) |
currency | string | USD | ip-api currency |
isp | string | Google LLC | ip-api isp |
organization | string | Google Public DNS | ip-api org |
asn | string | AS15169 Google LLC | ip-api as |
asnName | string | GOOGLE | ip-api asname |
reverseDns | string | dns.google | ip-api reverse |
isMobile | boolean | false | ip-api mobile |
isProxy | boolean | false | ip-api proxy (commercial proxy / VPN / Tor exit) |
isHosting | boolean | true | ip-api hosting (datacenter ASN) |
inputDomain | string | null | example.com | first domain in input (when domains supplied) |
scrapedAt | ISO string | 2026-04-29T10:30:00Z | actor capture time |
Inputs
| Parameter | Type | Default | Description |
|---|---|---|---|
ipAddresses | string[] | [] | IPv4 addresses (e.g. ["8.8.8.8", "1.1.1.1"]) |
domains | string[] | [] | Domain names — resolved to A records via Google DNS, then each A record is looked up |
If both are empty the actor pushes { error: 'No IPs or domains provided' }.
Rate limits and capacity (corrected math)
- ip-api.com free tier: 45 requests / minute, HTTP only (HTTPS requires paid plan — see security note below)
- The actor enforces
1500 msdelay between lookups + a60 spause after every 40 lookups - Sustained throughput ≈ 20 IPs/min: 40 lookups × 1.5 s = 60 s, then 60 s pause = 120 s per batch of 40 → 40/120 s = 20/min
- Practical capacity per 10-min run: ~200 IPs (NOT 400 — earlier README overstated this)
- For larger lists: split across runs, or request a custom build with ip-api Pro key (no rate-limit, HTTPS)
Use cases
- Security / SOC — enrich IPs from SIEM/WAF logs with country + ISP + ASN signals
- Fraud prevention — flag sign-ups whose declared country mismatches
countryCode - Ops mapping — segment events by
asn/countryto spot unusual traffic patterns - Analytics — append
country+region+cityto event data for dashboards - Datacenter detection —
isHosting: trueindicates the IP belongs to a hosting/cloud provider ASN
Quick start
from apify_client import ApifyClientclient = ApifyClient("YOUR_APIFY_TOKEN")run = client.actor("knotless_cadence/ip-geolocation-lookup").call(run_input={"ipAddresses": ["8.8.8.8", "1.1.1.1"],"domains": ["example.com", "github.com"],})for r in client.dataset(run["defaultDatasetId"]).iterate_items():print(f"{r['ip']:18} {r['countryCode']} {r['city']:20} {r.get('asn','')}")if r.get('isHosting'):print(f" ↳ hosting/datacenter")if r.get('isProxy'):print(f" ↳ proxy/VPN/Tor exit (ip-api flag)")
Bash one-liner
curl -s "https://api.apify.com/v2/acts/knotless_cadence~ip-geolocation-lookup/run-sync-get-dataset-items?token=$APIFY_TOKEN" \-H "Content-Type: application/json" \-d '{"ipAddresses":["8.8.8.8","1.1.1.1"]}' \| jq '.[] | {ip, countryCode, city, asn, isHosting, isProxy}'
How it works
- Build the IP queue:
ipAddresses+ DNS-resolved A records fromdomains - For each IP: call
http://ip-api.com/json/<ip>?fields=...with the 24-field bitmask - Push the normalized record to the dataset with
inputDomain(first input domain) +scrapedAt - 1.5s delay between calls; 60s pause every 40 calls
The isProxy flag aggregates ip-api's commercial-proxy / VPN / Tor-exit detection — it does not distinguish between those categories. For higher-fidelity Tor detection, cross-reference against the public Tor relay list separately.
Related actors
- SSL Certificate Checker — cert chain, expiry, fingerprint →
apify.com/knotless_cadence/ssl-certificate-checker - Whois Domain Lookup — RDAP-backed domain registration data →
apify.com/knotless_cadence/whois-domain-lookup - Website Tech-Stack Detector — frameworks, CDN, analytics →
apify.com/knotless_cadence/website-tech-stack-detector - PageSpeed Insights Scraper — Core Web Vitals →
apify.com/knotless_cadence/pagespeed-insights-scraper
Need a custom build?
Apify-as-a-Service tiers:
- Pilot — $97: 1 actor, basic config, 7-day support
- Standard — $297: custom actor + Slack/email alerts, 30-day support
- Premium — $797: custom actor + dashboard + 90-day support + 1 modification round
Common custom builds for IP enrichment: SIEM webhook integration, multi-source aggregation (paid ip-api + IPinfo + MaxMind), high-throughput async pipelines bypassing the 45/min free-tier cap.
Email: spinov001@gmail.com Blog (case studies): https://blog.spinov.online Telegram channel (scraping & data engineering): https://t.me/scraping_ai
Honest disclosure / limitations
- HTTP not HTTPS — ip-api.com's free tier is HTTP-only (HTTPS requires paid plan). Geolocation responses traverse the public network in cleartext; on hostile WiFi / shared infrastructure they are MITM-tamperable. For tamper-resistant enrichment, use ip-api Pro (paid) or MaxMind GeoIP2 (offline DB). Custom build available.
inputDomainis ALWAYS the FIRST domain in input — even when:- the IP came from
ipAddresses(no domain associated at all → still tagged withdomains[0]whendomains.length > 0) - the IP came from a DIFFERENT domain than
domains[0]in a multi-domain run (the actor doesn't track per-IP origin domain) → If you need accurate IP↔domain join, run one domain per call, or request a custom build that tracks origin per record.
- the IP came from
- Single-attempt fetch per IP — no retry on transient 5xx / network errors. Failed lookups are logged and skipped (no record pushed for that IP).
- Sequential DNS resolution —
domainsare resolved one-by-one againstdns.google/resolvewith no parallelism or retry; a slow DNS response delays the whole queue. - Single data source: ip-api.com public tier. The actor does NOT aggregate MaxMind, IP2Location, or IPinfo. For multi-source fallback / higher accuracy / no rate-limit, use the paid ip-api Pro tier or a separate enrichment service (custom build).
- No standalone VPN/Tor/datacenter detection — only ip-api's own
proxy(commercial proxy / VPN / Tor exit, aggregated) andhosting(datacenter ASN) flags. Heuristic, not exhaustive. For Tor-specific detection, cross-reference against the public Tor relay list separately. - 45 req/min upstream ceiling — actor sustains ~20/min after pauses. Practical capacity per 10-min Apify run = ~200 IPs (corrected from earlier "~400" overstatement).
- IPv4 only via current code path —
dns.google/resolve?type=Aresolves to A records only; the actor does not request AAAA records, sodomainsinputs only return IPv4-mapped lookups. Direct IPv6 strings inipAddressesare forwarded to ip-api which has its own IPv6 support. zipandcurrencymay be empty strings — ip-api does not return them for every IP (small-population regions, datacenter IPs).- Both
ipAddresses = []ANDdomains = []→ actor pushes a single{ error: 'No IPs or domains provided' }record and exits. - Independent project — not affiliated with ip-api.com or Google.