Check IP Intelligence
Get IP address intelligence including reputation scoring and detailed geolocation information.
IP Intelligence Endpoint
https://bifrost.api-armor.com/v1/ip-reputation-checkChecks 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
| Parameter | Type | Required | Description |
|---|---|---|---|
ip | string | No | The 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 OKReturns 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
| Field | Type | Description |
|---|---|---|
ip | string | The IP address that was checked |
country | string | Country name |
country_code | string | ISO 3166-1 alpha-2 country code |
flag | string | Country flag emoji |
region | string | Region or state code |
region_name | string | Full region or state name |
city | string | City name |
subdivisions | string | Administrative subdivisions |
connection_type | string | Type of internet connection (e.g., "Corporate", "Residential") |
is_anycast | boolean | Whether the IP is an anycast address |
zip | string | Postal/ZIP code |
latitude | number | Geographic latitude coordinate |
longitude | number | Geographic longitude coordinate |
timezone | string | IANA timezone identifier |
isp | string | Internet Service Provider name |
organization | string | Organization name |
asn | string | Autonomous System Number and organization |
reputation | object | Reputation details (see below) |
Reputation Object
| Field | Type | Description |
|---|---|---|
risky | boolean | Whether the IP is considered risky based on threat intelligence |
reputation | string | Reputation level: "bad", "warning", "suspicious", "informative", or "ok" |
bot | integer | Number of bot activity reports |
probe | integer | Number of network probing reports |
rate | integer | Number of rate limiting/abuse reports |
attack | integer | Number of attack reports |
crawler | integer | Number of crawler/scraping reports |
sum | integer | Total sum of all reports |
kind | array | Network 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:
| Level | Description | Action |
|---|---|---|
bad | Confirmed malicious activity | Block immediately |
warning | High risk, multiple reports | Block or require additional verification |
suspicious | Moderate risk, some reports | Consider additional verification |
informative | Low risk, minimal reports | Monitor but allow |
ok | Clean, no significant reports | Allow |
Network Classification Types
The kind array provides network classification:
| Type | Description |
|---|---|
hosting | Data center or hosting provider |
vpn | VPN service endpoint |
scanner | Known scanning/probing source |
crawler | Web crawler or bot |
isp | Internet Service Provider |
education | Educational institution |
dynamic | Dynamic 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);
}