API Armor LogoAPI Armor
API Reference

Check IP Intelligence

Get IP address intelligence including reputation scoring and detailed geolocation information.

IP Intelligence Endpoint

GEThttps://bifrost.api-armor.com/v1/ip-reputation-check

Checks an IP address for reputation risk and returns detailed geolocation information. If no IP parameter is provided, the request will check the client's own IP address.

Features

  • Real-time reputation scoring from threat intelligence databases
  • Detailed geolocation data (country, city, coordinates, timezone)
  • ISP and organization information
  • Network classification (hosting, VPN, residential, etc.)
  • Bot and attack report statistics

Private IP Handling

Private IP addresses (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, etc.) are automatically detected and return a clean reputation without external lookups.

Parameters

Query Parameters

ParameterTypeRequiredDescription
ipstringNoThe IPv4 address to check. If not provided, checks the client's IP address automatically.

Request Examples

curl "https://bifrost.api-armor.com/v1/ip-reputation-check?ip=159.89.165.46" \
  -H "Authorization: Bearer aa_abc123xyz789"

Response

Success Response

200 OK

Returns comprehensive IP intelligence including geolocation and reputation data.

{
  "ip": "164.92.87.190",
  "country": "United States",
  "country_code": "US",
  "flag": "πŸ‡ΊπŸ‡Έ",
  "region": "CA",
  "region_name": "California",
  "city": "Santa Clara",
  "subdivisions": "Santa Clara",
  "connection_type": "Corporate",
  "is_anycast": false,
  "zip": "95054",
  "latitude": 37.3986,
  "longitude": -121.964,
  "timezone": "America/Los_Angeles",
  "isp": "DigitalOcean, LLC",
  "organization": "DigitalOcean, LLC",
  "asn": "AS14061 DigitalOcean, LLC",
  "reputation": {
    "risky": true,
    "reputation": "suspicious",
    "bot": 1,
    "probe": 27,
    "rate": 0,
    "attack": 0,
    "crawler": 0,
    "sum": 28,
    "kind": ["hosting"]
  }
}

Response Fields

FieldTypeDescription
ipstringThe IP address that was checked
countrystringCountry name
country_codestringISO 3166-1 alpha-2 country code
flagstringCountry flag emoji
regionstringRegion or state code
region_namestringFull region or state name
citystringCity name
subdivisionsstringAdministrative subdivisions
connection_typestringType of internet connection (e.g., "Corporate", "Residential")
is_anycastbooleanWhether the IP is an anycast address
zipstringPostal/ZIP code
latitudenumberGeographic latitude coordinate
longitudenumberGeographic longitude coordinate
timezonestringIANA timezone identifier
ispstringInternet Service Provider name
organizationstringOrganization name
asnstringAutonomous System Number and organization
reputationobjectReputation details (see below)

Reputation Object

FieldTypeDescription
riskybooleanWhether the IP is considered risky based on threat intelligence
reputationstringReputation level: "bad", "warning", "suspicious", "informative", or "ok"
botintegerNumber of bot activity reports
probeintegerNumber of network probing reports
rateintegerNumber of rate limiting/abuse reports
attackintegerNumber of attack reports
crawlerintegerNumber of crawler/scraping reports
sumintegerTotal sum of all reports
kindarrayNetwork classification types (e.g., "hosting", "vpn", "scanner", "crawler", "isp", "education", "dynamic")

Example Responses

Risky IP from Hosting Provider:

{
  "ip": "164.92.87.190",
  "country": "United States",
  "country_code": "US",
  "flag": "πŸ‡ΊπŸ‡Έ",
  "region": "CA",
  "region_name": "California",
  "city": "Santa Clara",
  "subdivisions": "Santa Clara",
  "connection_type": "Corporate",
  "is_anycast": false,
  "zip": "95054",
  "latitude": 37.3986,
  "longitude": -121.964,
  "timezone": "America/Los_Angeles",
  "isp": "DigitalOcean, LLC",
  "organization": "DigitalOcean, LLC",
  "asn": "AS14061 DigitalOcean, LLC",
  "reputation": {
    "risky": true,
    "reputation": "suspicious",
    "bot": 1,
    "probe": 27,
    "rate": 0,
    "attack": 0,
    "crawler": 0,
    "sum": 28,
    "kind": ["hosting"]
  }
}

Clean IP Address:

{
  "ip": "8.8.8.8",
  "country": "United States",
  "country_code": "US",
  "flag": "πŸ‡ΊπŸ‡Έ",
  "region": "CA",
  "region_name": "California",
  "city": "Mountain View",
  "subdivisions": "",
  "connection_type": "Corporate",
  "is_anycast": true,
  "zip": "94035",
  "latitude": 37.386,
  "longitude": -122.0838,
  "timezone": "America/Los_Angeles",
  "isp": "Google LLC",
  "organization": "Google LLC",
  "asn": "AS15169 Google LLC",
  "reputation": {
    "risky": false,
    "reputation": "ok",
    "bot": 0,
    "probe": 0,
    "rate": 0,
    "attack": 0,
    "crawler": 0,
    "sum": 0,
    "kind": []
  }
}

Private IP Address:

{
  "ip": "192.168.1.1",
  "country": "",
  "country_code": "",
  "region": "",
  "region_name": "",
  "city": "",
  "subdivisions": "",
  "connection_type": "",
  "is_anycast": false,
  "zip": "",
  "latitude": 0,
  "longitude": 0,
  "timezone": "",
  "isp": "",
  "organization": "",
  "asn": "",
  "reputation": {
    "risky": false,
    "reputation": "ok",
    "bot": 0,
    "probe": 0,
    "rate": 0,
    "attack": 0,
    "crawler": 0,
    "sum": 0,
    "kind": []
  }
}

Error Responses

Invalid IP Format

400 Bad Request
{
  "error": "invalid_ip",
  "message": "invalid IP address format"
}

Unauthorized

401 Unauthorized
{
  "error": "invalid_api_key",
  "message": "The provided API key is not valid"
}

Rate Limit Exceeded

429 Too Many Requests
{
  "error": "rate_limit_exceeded",
  "message": "Rate limit exceeded. Please try again later.",
  "retry_after": 60
}

Quota Exceeded

429 Too Many Requests
{
  "error": "quota_exceeded",
  "message": "Monthly quota exceeded. Please upgrade your plan or wait until next month.",
  "retry_after": 86400
}

Rate Limit Headers

When you receive a 429 error, check the X-RateLimit-Reset header to see when you can make requests again. The response also includes quota information in X-Quota-Limit, X-Quota-Remaining, and X-Quota-Reset headers.

Understanding IP Intelligence Scores

The reputation field indicates the overall risk level:

LevelDescriptionAction
badConfirmed malicious activityBlock immediately
warningHigh risk, multiple reportsBlock or require additional verification
suspiciousModerate risk, some reportsConsider additional verification
informativeLow risk, minimal reportsMonitor but allow
okClean, no significant reportsAllow

Network Classification Types

The kind array provides network classification:

TypeDescription
hostingData center or hosting provider
vpnVPN service endpoint
scannerKnown scanning/probing source
crawlerWeb crawler or bot
ispInternet Service Provider
educationEducational institution
dynamicDynamic IP range

Integration Examples

User Signup Protection

import express from 'express';

const app = express();
const API_KEY = process.env.API_ARMOR_KEY;

app.post('/api/signup', async (req, res) => {
  // Get client IP (handle proxies)
  const clientIP = req.headers['x-forwarded-for']?.split(',')[0] || 
                   req.socket.remoteAddress;

  try {
    // Check IP reputation
    const response = await fetch(
      `https://bifrost.api-armor.com/v1/ip-reputation-check?ip=${clientIP}`,
      {
        headers: { 'Authorization': `Bearer ${API_KEY}` }
      }
    );

    const ipData = await response.json();

    // Block if risky
    if (ipData.reputation.risky) {
      return res.status(403).json({
        error: 'signup_blocked',
        message: 'Signup from suspicious IP address blocked'
      });
    }

    // Flag for review if hosting/VPN
    if (ipData.reputation.kind.includes('hosting') || 
        ipData.reputation.kind.includes('vpn')) {
      // Mark account for manual review
      await flagAccountForReview(req.body.email, ipData);
    }

    // Continue with signup
    // ...

    res.json({ success: true });
  } catch (error) {
    // Fail open - don't block users due to API errors
    console.error('IP check failed:', error);
    // Continue with signup
  }
});

Rate Limiting Enhancement

import rateLimit from 'express-rate-limit';

// Dynamic rate limiting based on IP reputation
async function getIPReputation(ip) {
  try {
    const response = await fetch(
      `https://bifrost.api-armor.com/v1/ip-reputation-check?ip=${ip}`,
      {
        headers: { 'Authorization': `Bearer ${process.env.API_ARMOR_KEY}` }
      }
    );
    return await response.json();
  } catch (error) {
    return null;
  }
}

// Create adaptive rate limiter
const adaptiveRateLimit = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: async (req) => {
    const clientIP = req.headers['x-forwarded-for']?.split(',')[0] || 
                     req.socket.remoteAddress;
    
    const ipData = await getIPReputation(clientIP);
    
    if (!ipData) return 100; // Default if check fails
    
    // Adjust limits based on reputation
    if (ipData.reputation.reputation === 'bad') return 10;
    if (ipData.reputation.reputation === 'suspicious') return 50;
    if (ipData.reputation.kind.includes('hosting')) return 30;
    
    return 100; // Normal limit for clean IPs
  },
  message: 'Too many requests from this IP'
});

app.use('/api/', adaptiveRateLimit);

Login Protection

from django.contrib.auth import authenticate, login
from django.http import JsonResponse
import requests
import os

API_KEY = os.environ.get('API_ARMOR_KEY')

def check_ip_reputation(ip):
    """Check IP reputation"""
    try:
        response = requests.get(
            'https://bifrost.api-armor.com/v1/ip-reputation-check',
            params={'ip': ip},
            headers={'Authorization': f'Bearer {API_KEY}'},
            timeout=5
        )
        response.raise_for_status()
        return response.json()
    except Exception as e:
        print(f"IP check error: {e}")
        return None

def get_client_ip(request):
    """Extract client IP from request"""
    x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
    if x_forwarded_for:
        return x_forwarded_for.split(',')[0]
    return request.META.get('REMOTE_ADDR')

def login_view(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        client_ip = get_client_ip(request)
        
        # Check IP reputation
        ip_data = check_ip_reputation(client_ip)
        
        if ip_data and ip_data['reputation']['risky']:
            # Require 2FA for risky IPs
            return JsonResponse({
                'requires_2fa': True,
                'message': 'Additional verification required'
            })
        
        # Check for attack patterns
        if ip_data and ip_data['reputation']['attack'] > 5:
            # Block or require captcha
            return JsonResponse({
                'error': 'verification_required',
                'message': 'Please complete verification'
            }, status=403)
        
        # Normal login flow
        user = authenticate(request, username=username, password=password)
        if user:
            login(request, user)
            return JsonResponse({'success': True})
        
        return JsonResponse({'error': 'Invalid credentials'}, status=401)

Best Practices

1. Fail Open for Availability

Always fail open if the API is unavailable to avoid blocking legitimate users:

async function checkIPSafety(ip) {
  try {
    const response = await fetch(
      `https://bifrost.api-armor.com/v1/ip-reputation-check?ip=${ip}`,
      {
        headers: { 'Authorization': `Bearer ${process.env.API_ARMOR_KEY}` },
        timeout: 5000 // 5 second timeout
      }
    );
    return await response.json();
  } catch (error) {
    console.error('IP check failed:', error);
    // Return safe default - don't block users
    return { reputation: { risky: false, reputation: 'ok' } };
  }
}

2. Implement Risk-Based Actions

Don't just block - use reputation data for smart decisions:

function getRiskAction(ipData) {
  const { reputation } = ipData.reputation;
  
  switch (reputation) {
    case 'bad':
      return 'block';
    case 'warning':
      return 'require_2fa';
    case 'suspicious':
      return 'require_captcha';
    default:
      return 'allow';
  }
}

3. Cache Results

Cache IP reputation data to reduce API calls and improve performance:

import NodeCache from 'node-cache';

const ipCache = new NodeCache({ stdTTL: 3600 }); // 1 hour cache

async function getCachedIPReputation(ip) {
  // Check cache first
  const cached = ipCache.get(ip);
  if (cached) return cached;
  
  // Fetch if not cached
  const response = await fetch(
    `https://bifrost.api-armor.com/v1/ip-reputation-check?ip=${ip}`,
    {
      headers: { 'Authorization': `Bearer ${process.env.API_ARMOR_KEY}` }
    }
  );
  
  const data = await response.json();
  ipCache.set(ip, data);
  
  return data;
}

4. Handle Proxies Correctly

Extract the real client IP when behind proxies:

function getClientIP(request) {
  // Check X-Forwarded-For header (common with proxies/load balancers)
  const forwardedFor = request.headers['x-forwarded-for'];
  if (forwardedFor) {
    // Take first IP in the chain (client IP)
    return forwardedFor.split(',')[0].trim();
  }
  
  // Check X-Real-IP header (Nginx)
  const realIP = request.headers['x-real-ip'];
  if (realIP) return realIP;
  
  // Fall back to direct connection
  return request.socket.remoteAddress;
}

5. Log and Monitor

Log reputation checks for analysis and monitoring:

async function checkAndLogIP(ip, context) {
  const ipData = await checkIPReputation(ip);
  
  // Log the check
  await logEvent({
    type: 'ip_reputation_check',
    ip: ip,
    context: context,
    reputation: ipData.reputation,
    location: {
      country: ipData.country,
      city: ipData.city,
      isp: ipData.isp
    },
    timestamp: new Date()
  });
  
  return ipData;
}

Use Cases

Content Access Control

Block access to premium content from known VPN/proxy services:

if (ipData.reputation.kind.includes('vpn') || 
    ipData.reputation.kind.includes('hosting')) {
  return res.status(403).json({
    error: 'vpn_detected',
    message: 'Premium content not available via VPN/proxy'
  });
}

Geographic Restrictions

Enforce geo-restrictions based on IP location:

const allowedCountries = ['US', 'CA', 'GB'];

if (!allowedCountries.includes(ipData.country_code)) {
  return res.status(451).json({
    error: 'geo_restricted',
    message: 'Service not available in your country'
  });
}

Bot Detection

Identify and handle bot traffic:

if (ipData.reputation.bot > 0 || 
    ipData.reputation.crawler > 0) {
  // Serve cached/simplified version to bots
  return serveStaticContent(req, res);
}

Next Steps

On this page