ASN lookup by IP: find the network, ISP and organization behind any address

The country tells you where an address is. The autonomous system number tells you whose network it is, and that is often the more useful question. How to look up ASNs by hand and in code, and what to do with them.

On this page What you can do with an ASN

Every public IP address is announced to the internet by an autonomous system (AS): a network run by one organization with its own routing policy, such as an ISP, a cloud provider, a university or a large company. Each AS has a number, the ASN. 15169 is Google, for example.

For many tasks the ASN is more useful than the location. It tells you whether a request comes from a home broadband connection, a mobile carrier or a cloud data centre. This guide shows how to look ASNs up and how to put them to work.

What you can do with an ASN

  • Separate data-centre from consumer traffic. Sign-ups or checkouts from cloud-hosting ASNs deserve a second look in many businesses. Real customers rarely browse from a server.
  • Group noisy traffic. A thousand "different" IPs in your logs may be one hosting provider. Grouping by ASN shows the real sources.
  • Rate limit per network instead of per IP, so a scraper rotating through one provider's addresses still hits a limit.
  • Debug connectivity. "Only customers on one ISP report the problem" is a common pattern. The ASN identifies the ISP precisely.
  • Enrich security logs so analysts see "AS64500 Example Hosting" instead of a bare IP.

Looking up an ASN by hand

Team Cymru whois

Team Cymru runs a free IP-to-ASN mapping service that answers over whois:

bash
whois -h whois.cymru.com " -v 8.8.8.8"

The answer is one pipe-separated line per address with the columns AS | IP | BGP Prefix | CC | Registry | Allocated | AS Name. For 8.8.8.8 the AS column is 15169 and the AS name is Google's. The leading space inside the quotes is what turns on the verbose columns.

RDAP

RDAP is the modern, JSON-based replacement for whois run by the regional internet registries. It tells you who the address is registered to, which isn't always the network that announces it, but is often enough:

bash
curl -s https://rdap.arin.net/registry/ip/8.8.8.8 | jq '.name, .handle'

ARIN redirects queries for addresses managed by other registries (RIPE, APNIC, LACNIC, AFRINIC) to the right server, so curl -L works for any address.

Looking up ASNs in code

For anything beyond a one-off check you want structured data in one call, together with the location. The IPAPI.GR lookup returns asn, isp and organization on every plan:

bash
curl "https://fast.ipapi.gr/api/lookup/8.8.8.8?key=YOUR_API_KEY"
json
{
  "ip": "8.8.8.8",
  "country_code": "US",
  "isp": "Google LLC",
  "organization": "Google LLC",
  "asn": "15169"
}

The response above is trimmed. The full field list is in the docs. Note that asn is a string of digits without an AS prefix. Normalise your own data the same way before you compare.

isp and organization are often the same. They differ when an address block is assigned to a customer of the network, for example a company that gets its addresses from a hosting provider.

Node.js: enrich a list of IPs

js
const KEY = process.env.IPAPI_KEY;

const known = (v) => (v === undefined || v === null || v === '' || v === 'No Data' ? null : v); // missing fields are "No Data"

async function asnFor(ip) {
  const res = await fetch(`https://fast.ipapi.gr/api/lookup/${encodeURIComponent(ip)}?key=${KEY}`,
    { signal: AbortSignal.timeout(5000) });
  const data = await res.json();
  if (!res.ok) throw new Error(`${ip}: ${data.message}`);
  return { ip, asn: known(data.asn), org: known(data.organization) ?? known(data.isp) };
}

// Small concurrency pool: polite to the API, fast enough for thousands of IPs.
async function enrich(ips, concurrency = 8) {
  const unique = [...new Set(ips)];
  const out = new Map();
  let i = 0;
  async function worker() {
    while (i < unique.length) {
      const ip = unique[i++];
      try { out.set(ip, await asnFor(ip)); } catch (e) { out.set(ip, { ip, error: e.message }); }
    }
  }
  await Promise.all(Array.from({ length: concurrency }, worker));
  return out;
}

Deduplicating first matters: logs repeat the same addresses constantly, and every lookup counts against your daily limit.

Python: top networks in an access log

python
import collections
import os

import requests

KEY = os.environ["IPAPI_KEY"]
session = requests.Session()
cache = {}

def asn_for(ip):
    if ip not in cache:
        r = session.get(f"https://fast.ipapi.gr/api/lookup/{ip}", params={"key": KEY}, timeout=5)
        data = r.json() if r.ok else {}
        known = lambda v: None if v in (None, "", "No Data") else v  # missing fields are "No Data"
        cache[ip] = (known(data.get("asn")), known(data.get("organization")) or known(data.get("isp")))
    return cache[ip]

counts = collections.Counter()
with open("/var/log/nginx/access.log") as log:
    for line in log:
        ip = line.split(" ", 1)[0]
        counts[asn_for(ip)] += 1

for (asn, org), n in counts.most_common(15):
    print(f"{n:>8}  AS{asn or '?':<8} {org or 'unknown'}")

The result is often surprising. On many public sites, a few cloud networks send a large share of the requests.

Rate limiting per network in Express

Per-IP rate limits are easy to sidestep when a scraper rotates through hundreds of addresses at one provider. Keying a second, looser limit on the ASN catches that without hurting normal visitors:

js
import express from 'express';

const app = express();
app.set('trust proxy', 1);

const asnCache = new Map();    // ip -> { asn, at }
const windows = new Map();     // asn -> { count, start }
const WINDOW_MS = 60 * 1000;
const MAX_PER_ASN = 600;       // tune to your traffic

async function asnOf(ip) {
  const hit = asnCache.get(ip);
  if (hit && Date.now() - hit.at < 3600 * 1000) return hit.asn;
  try {
    const res = await fetch(`https://fast.ipapi.gr/api/lookup/${encodeURIComponent(ip)}?key=${process.env.IPAPI_KEY}`,
      { signal: AbortSignal.timeout(1500) });
    const asn = res.ok ? known((await res.json()).asn) : null; // known() from the first example
    asnCache.set(ip, { asn, at: Date.now() });
    return asn;
  } catch {
    return null;
  }
}

app.use('/api/search', async (req, res, next) => {
  const asn = await asnOf(req.ip);
  if (!asn) return next();                       // unknown: fall back to per-IP limits only
  const now = Date.now();
  const w = windows.get(asn);
  if (!w || now - w.start > WINDOW_MS) windows.set(asn, { count: 1, start: now });
  else if (++w.count > MAX_PER_ASN) return res.status(429).json({ error: 'Too many requests from your network' });
  next();
});

Set the per-ASN limit well above what a busy office or a mobile carrier's shared addresses produce. Large consumer ISPs carry millions of users, so apply the limit to expensive endpoints only, or exempt the big consumer networks you see in your own traffic.

Telling hosting from residential traffic

There's no field that says "data centre", but you can get close with your own data:

  1. Run the top-networks report above on a week of traffic.
  2. Mark the ASNs you recognise as cloud or hosting providers. Their organization names usually make it obvious.
  3. Store that list with a review date and use it as one input to risk scoring.

Keep it as a soft signal. Legitimate services such as uptime monitors, payment webhooks and your own integrations also run in data centres.

Using ASNs carefully

  • An ASN isn't a verdict. Cloud ASNs carry VPNs, corporate proxies and privacy relays used by real people, as well as bots. Use the ASN as one signal, for example to require a CAPTCHA, not to block outright.
  • Large networks are mixed. Some providers announce consumer, business and data-centre space from the same ASN.
  • Keep lists current. If you maintain your own list of "hosting ASNs", review it. Networks are bought, merged and repurposed.

ASN vs bot verification

An ASN tells you a request came from, say, a major cloud provider. It doesn't tell you which customer of that provider sent it. GPTBot, a hobbyist's scraper and a company VPN can all sit in the same cloud ASN. To know whether an address belongs to a specific bot operator, you need the operator's own published ranges. That's what the risk.is_ai, risk.is_crawler and risk.is_scanner flags check. See how to verify AI crawler IP addresses.

FAQ

What's the difference between ISP, organization and ASN?

The ASN identifies the network that routes the address. isp is the operator of that network. organization is who holds the address block, which can be the ISP itself or one of its customers.

Can an IP belong to more than one ASN?

At a given moment an address is normally announced by one origin AS, but some prefixes are announced by several (anycast, multi-homing), and announcements change over time. Treat ASN data as a snapshot.

Is ASN data available on the free plan?

Yes. asn, isp and organization are part of every lookup. Only the risk flags require Pro.

More code for the other fields: get a visitor's country from their IP.