IP Intelligence — Geolocation, ASN, Hosting, Tor, Abuse Contact
Pricing
from $0.70 / 1,000 result items
IP Intelligence — Geolocation, ASN, Hosting, Tor, Abuse Contact
Bulk IPv4/IPv6 lookup: country/city, ASN & BGP prefix, reverse DNS (FCrDNS), cloud/hosting detection (AWS, GCP, Oracle, DigitalOcean, Cloudflare, Fastly), Tor exits, RDAP abuse contacts and a risk score. Extracts IPs from logs. No API key.
Pricing
from $0.70 / 1,000 result items
Rating
0.0
(0)
Developer
Samat Makatov
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
10 days ago
Last modified
Categories
Share
Bulk IP lookup for fraud triage, security and data enrichment. For each IPv4/IPv6 address (or hostname) you get country/city, ASN and BGP prefix, reverse DNS with forward confirmation, datacenter/cloud detection with provider, service and region, Tor exit status, registry owner and abuse email, and a transparent risk score. It also pulls IPs out of raw log text. No API key, proxy or browser needed. Every data source is free and allows commercial use.
Use cases
- Signup / payment fraud triage: flag signups coming from datacenters, Tor or countries you don't serve (
allowedCountries,onlyFlagged). - Security log enrichment: paste raw nginx or firewall logs into
textand get ASN, owner and abuse contact for every attacker IP. - Abuse reporting:
includeRdapreturns the network name, CIDR and the abuse email of the RIR (ARIN, RIPE NCC, APNIC, LACNIC, AFRINIC). - Crawler / bot verification: reverse DNS plus
forwardConfirmed(FCrDNS) shows whether "Googlebot" really comes from google.com. - Infrastructure due diligence: resolve a company's hostnames and see which clouds, CDNs and regions they run on.
- Lead enrichment / analytics: turn visitor IPs into country, city, ISP and company network.
Input
| Field | Type | Default | Allowed values / notes |
|---|---|---|---|
ips | string[] | — | IPv4, IPv6 (IPv4-mapped normalized) or hostnames. |
text | string | — | Free text (logs, CSV, email headers); all valid IPs are extracted and merged with ips. |
resolveHostnames | boolean | true | Non-IP entries are resolved to all A/AAAA records (one row per IP). |
maxItems | integer | 1000 | 1–5000. Cap on processed IPs after dedupe. |
dedupe | boolean | true | Look up each distinct IP once. |
geoProvider | enum | auto | auto, ipwhois, countryis, none (see Reference). Any other value is refused by Apify before the run starts. |
includeAsn | boolean | true | ASN, AS name, BGP prefix, RIR, allocation date (Team Cymru). |
includeReverseDns | boolean | true | PTR names + forward confirmation. |
includeHostingCheck | boolean | true | Official cloud IP ranges → hosting ASN list → AS-name keywords. |
includeTorCheck | boolean | true | Official Tor Project exit list. |
includeRdap | boolean | false | Registry network + abuse email. One request per distinct network, ~2.5/s. |
allowedCountries | string[] | — | ISO 3166-1 alpha-2 codes, e.g. ["KZ","US"]. |
onlyFlagged | boolean | false | Keep only Tor, hosting, bogon or outside-allowed-country rows. |
minRiskScore | integer | 0 | 0–100. |
skipBogons | boolean | false | Drop private/reserved addresses from the output. |
fields | string[] | — | Output columns to keep, in your order. id and input are always kept (first, unless you list them elsewhere). Case, _ and - do not matter (country_code = countryCode, latitude = lat); each correction is named in the status. A name that is no column is left out and named in the status and SUMMARY.notes; if no name is a column, the run fails and lists the columns (no rows are billed). |
Reference
Geolocation providers
| Value | Source | Notes |
|---|---|---|
auto | ipwho.is, then country.is | Rich fields first. Switches to country.is for the rest of the run at once when ipwho.is answers with its quota (HTTP 429/403 or a limit message), after 3 failed ipwho.is lookups in a row (no answer within 8 s, HTTP 5xx), or when ipwho.is, one IP at a time, could not answer the remaining IPs before the run timeout. Every IP ipwho.is did not answer is asked at country.is. SUMMARY.geo counts the answers per source, and the status message names a switch. |
ipwhois | ipwho.is free plan | Region code, postal, ISP, org, domain, EU flag, calling code, UTC offset. About 1,000 requests a day per client IP, commercial use allowed. At the quota, or after 3 failures in a row, the remaining rows have no geolocation and error says why (no switch in this mode). |
countryis | country.is (MaxMind GeoLite2) | Bulk (100 per request), fast, gives accuracyRadiusKm. No ISP/domain. |
none | — | Skip geolocation; network, hosting and risk only. |
Hosting detection (hostingSource)
| Value | Meaning |
|---|---|
cloud-ranges | IP is inside an official published range: AWS (ip-ranges.json, with service such as EC2/S3/CLOUDFRONT/ROUTE53 and region), Google Cloud (cloud.json, with region), Oracle Cloud (with region), DigitalOcean (with datacenter), Cloudflare, Fastly. |
asn-list | ASN is on a curated list of about 60 well-known hosting, cloud, CDN and VPS networks (Azure, Hetzner, OVH, Vultr, Linode, Contabo, Scaleway, Alibaba, Tencent, Leaseweb, M247…). |
asn-name | AS name contains hosting keywords (hosting, cloud, datacenter, server, VPS, colo, CDN). This is a weaker signal. |
Risk score: additive, capped at 100. It's a heuristic for triage, not a fraud verdict.
| Signal | Points |
|---|---|
| Tor exit node | +60 |
| Bogon/reserved address | +50 |
Hosting via cloud-ranges or asn-list | +35 |
Hosting via asn-name | +20 |
Country not in allowedCountries | +25 |
| No reverse DNS | +5 |
riskLevel: none (0), low (1–29), medium (30–59), high (60+).
Bogon types: private, loopback, link-local, carrier-grade-nat, documentation, benchmarking, multicast, reserved, this-network, ietf-protocol, unique-local, unspecified, nat64, discard. Bogons are never sent to remote services.
Examples
Fraud triage: signups that should come from Kazakhstan only
{ "ips": ["5.34.0.1", "52.95.110.1", "159.89.10.10", "185.220.101.1"], "allowedCountries": ["KZ"], "onlyFlagged": true }
Enrich an access log and collect abuse contacts
{ "text": "185.220.101.1 - - [13/Sep/2026] \"POST /login\" 401\n159.89.10.10 - - [13/Sep/2026] \"POST /login\" 401", "includeRdap": true, "fields": ["ip", "countryCode", "asn", "asName", "networkName", "networkCidr", "abuseEmail", "riskScore"] }
Where does a company host? (hostnames → cloud provider/region)
{ "ips": ["apify.com", "api.apify.com", "console.apify.com"], "geoProvider": "none", "includeReverseDns": false, "fields": ["input", "ip", "asn", "asName", "cloudProvider", "cloudService", "cloudRegion"] }
Large list, fastest settings
{ "ips": ["8.8.8.8", "1.1.1.1"], "geoProvider": "countryis", "includeReverseDns": false, "maxItems": 5000 }
Verify that "Googlebot" requests are genuine
{ "ips": ["66.249.66.1", "203.0.113.50"], "geoProvider": "none", "includeHostingCheck": false, "includeTorCheck": false, "fields": ["ip", "hostname", "forwardConfirmed", "asName"] }
Output
Example row (trimmed, from a local run with geoProvider: "countryis", includeRdap: true, allowedCountries: ["KZ"]):
{"id": "159.89.10.10","input": "159.89.10.10","ip": "159.89.10.10","ipVersion": 4,"isValid": true,"isBogon": false,"bogonType": null,"found": true,"country": "Germany","countryCode": "DE","city": "Frankfurt am Main","lat": 50.1169,"lon": 8.6837,"accuracyRadiusKm": 20,"timezone": "Europe/Berlin","asn": 14061,"asName": "DIGITALOCEAN-ASN - DigitalOcean, LLC, US","bgpPrefix": "159.89.0.0/20","rir": "ARIN","hostname": null,"isHosting": true,"hostingSource": "cloud-ranges","cloudProvider": "DigitalOcean","cloudRegion": "DE-Frankfurt","isTorExit": false,"networkName": "DIGITALOCEAN-159-89-0-0","abuseEmail": "abuse@digitalocean.com","outsideAllowedCountries": true,"riskScore": 65,"riskLevel": "high","riskReasons": ["datacenter / cloud network", "country DE not in allowed list", "no reverse DNS"],"geoSource": "country.is","sources": ["country.is", "team-cymru", "reverse-dns", "cloud-ip-ranges", "tor-exit-list", "rdap"],"error": null,"fetchedAt": "2026-09-13T13:40:00.000Z"}
| Field | Description |
|---|---|
id, input, ip, ipVersion | Canonical IP (stable id), original input (hostname for resolved rows), 4 or 6. |
isValid, isBogon, bogonType | Validation (always true on rows — invalid inputs go to SUMMARY.errors) and reserved-range type. |
found | Geolocation or ASN data was found. |
continent, continentCode, country, countryCode, region, regionCode, city, postal, lat, lon, accuracyRadiusKm, timezone, utcOffset, isEu, callingCode, flag | Geolocation. Which fields are filled depends on geoSource. |
asn, asName, asCountry, bgpPrefix, rir, prefixAllocatedAt | Routing data (Team Cymru). |
isp, org, domain | ISP and organization (ipwho.is; org falls back to country.is/RDAP). |
hostname, reverseDns, forwardConfirmed | PTR records and FCrDNS result. |
isHosting, hostingSource, cloudProvider, cloudService, cloudRegion | Datacenter detection. |
isTorExit, isProxy | Tor exit status. isProxy is true for Tor exits and null otherwise, because commercial VPN/proxy databases are not free. |
networkName, networkHandle, networkRange, networkCidr, networkType, networkCountry, networkRegisteredAt, abuseEmail, rdapUrl | RIR registration (only with includeRdap). |
outsideAllowedCountries, riskScore, riskLevel, riskReasons | Risk triage. |
geoSource, sources, error, fetchedAt | Provenance, per-row soft errors and timestamp. |
The dataset has three views: Overview, Risk triage and Network & abuse contacts.
Use it from code / agents
curl (synchronous, returns items)
curl -X POST "https://api.apify.com/v2/acts/yadroo~ip-intel/run-sync-get-dataset-items?token=$APIFY_TOKEN" \-H 'content-type: application/json' \-d '{"ips":["185.220.101.1","159.89.10.10"],"allowedCountries":["KZ"]}'
JavaScript (apify-client)
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: process.env.APIFY_TOKEN });const run = await client.actor('yadroo/ip-intel').call({ ips: ['8.8.8.8', '185.220.101.1'], onlyFlagged: true });const { items } = await client.dataset(run.defaultDatasetId).listItems();
Python (apify-client)
from apify_client import ApifyClientclient = ApifyClient("<APIFY_TOKEN>")run = client.actor("yadroo/ip-intel").call(run_input={"text": open("access.log").read(), "includeRdap": True})items = client.dataset(run["defaultDatasetId"]).list_items().items
AI agents (MCP): add yadroo/ip-intel as a tool through the Apify MCP server at mcp.apify.com. The input schema descriptions are written so an agent can pick sources and filters on its own.
Pricing
Pay per event: $0.001 per run start + $0.001 per output row. For example:
- 100 signup IPs → $0.101
- 1,000 log IPs → $1.001
- A hostname that resolves to 12 IPs produces 12 rows (12 × $0.001).
Bronze −10 %, Silver −20 %, Gold and above −30 % on the row price; the start event is the same on every plan; platform usage is included.
Rows removed by onlyFlagged, minRiskScore or skipBogons are not pushed, so they are not charged. Neither are invalid inputs or hostnames that do not resolve (see SUMMARY).
Your maximum cost per run is respected: rows are saved and charged in chunks of 50 IPs as they are looked up, and the run stops at the row that would cross the limit and says so ("Stopped at your spending limit: N rows delivered"). IPs it did not reach are listed in SUMMARY.notProcessed.
Limits & FAQ
- Speed: ipwho.is is queried one IP at a time (about 3 per second, 8 s timeout per request). country.is works in batches of 100. DNS lookups run 10 in parallel. RDAP asks one network at a time (a pause of 0.4 s between requests) and reuses a network's answer for its other IPs. IPs are looked up in chunks of 50, and each chunk's rows are saved before the next chunk starts. For thousands of IPs, use
geoProvider: "countryis"and leaveincludeRdapoff. - Capacity (measured on 02.10.2026 with the default 256 MB and the default sources):
countryislooked up 1,000 IPs in 52 s, so the 5,000 of themaxItemsmaximum take about 4–5 minutes (estimated, not measured).autotook 160 s for 600 IPs (ipwho.is answered all of them, ~0.26 s per IP); past the ipwho.is quota it continues on country.is at thecountryispace. WithincludeRdap, 200 IPs from 199 different networks took 121 s (~0.6 s per new network), so about 1,300 new networks fit in a 900 s run; IPs of a network already looked up cost nothing extra. - Timeout: the default run timeout is 900 s. A run near its timeout stops starting new lookups, keeps every row it saved and ends SUCCEEDED with "Stopped before the run timeout: N rows saved"; the IPs it did not reach are listed in
SUMMARY.notProcessed(not charged). Raise the timeout or split the list to get the rest. - Quotas, and why there is no proxy option: ipwho.is allows about 1,000 free lookups a day per client IP, and Apify's outgoing IPs are shared with other users, so part of that quota may be used before your run starts. The actor does not rotate proxies to get more: that would only multiply the load on a free service past the limit it sets per client. country.is (MaxMind GeoLite2) has no daily quota and answers 100 IPs per request, so for large lists use
geoProvider: "countryis"(orauto, which switches to it by itself). - Freshness: cloud ranges and the Tor exit list are downloaded fresh on every run. Geolocation is as fresh as the providers (GeoLite2 is updated daily/weekly).
- Errors: a source that fails never kills the run. Its fields stay
null, a warning is logged, and per-row problems go toerror. A source that fails 3 times in a row (ipwho.is, or one RIR's RDAP server) is not asked again in that run, so an outage cannot eat the run's time. Invalid inputs and hostnames that do not resolve are not rows (and not charged): they are listed in theSUMMARYrecord of the default key-value store (errors[{input, error}],notFound[], with counts) and in the run's status message. The run fails only when no input is a valid IP address or hostname. - Not included: commercial VPN/residential-proxy detection and mobile-carrier flags. The free sources that offer them (e.g. ip-api.com) forbid commercial use, and RIPEstat also restricts commercial use, so this actor does not use them.
- Accuracy: IP geolocation is approximate, especially city level and for mobile/CGNAT networks. Treat
riskScoreas a triage signal. - Roadmap: Azure service-tag ranges, more hosting ASNs, CIDR input expansion.
Made by Yadroo. Sibling actors: domain-intel · sanctions-screen · wallet-intel · osm-geocode · github-repo-intel