Todo lo que necesita para integrar OpenIPApi en su aplicación. URL base: https://api.openipapi.com (versionada como /v1).
threat_score y los indicadores VPN/proxy/Tor son entradas para su lógica de decisión. Combínelos con señales de cuenta, pago, dispositivo y comportamiento; nunca los use como única base para bloquear. Consulte la Metodología de datos para más detalles.
Todas las solicitudes a la API deben incluir su clave API en la cabecera X-API-Key Puede encontrar su clave API en la consola.
X-API-Key: oip_your_api_key_here
Todas las solicitudes a la API se realizan a la siguiente URL base a través de HTTPS:
https://api.openipapi.com
Especificación legible por máquina (OpenAPI 3.1): /openapi.yaml.
Todas las respuestas son JSON. Las respuestas exitosas devuelven HTTP 200.
Las respuestas de error devuelven un código de estado 4xx o 5xx apropiado con un campo error .
{
"error": "invalid_api_key",
"message": "The provided API key is invalid or has been revoked.",
"status": 401
}
Consulte datos de geolocalización, red y amenaza para una única dirección IP.
https://api.openipapi.com/v1/lookup/{ip}
| Parámetro | Tipo | Descripción |
|---|---|---|
| ip | path | Dirección IPv4 o IPv6 a consultar. |
| fields | query (optional) | Lista separada por comas de campos de nivel superior a devolver: geo,network,threat,abuse. |
| date | query (optional) | Consulta histórica — devuelve la instantánea de esta IP en la fecha indicada (YYYY-MM-DD). Hasta 365 días atrás. Requiere Pro+. Devuelve un error no_snapshot si no hay datos disponibles para esa fecha. |
| Campo | Descripción | Plan |
|---|---|---|
| ip | The queried IP address. | All |
| type | IPv4 or IPv6. | All |
| geo.country_code | 2-letter ISO 3166-1 country code. | All |
| geo.country | Full country name. | All |
| geo.region | Region / state name. | All |
| geo.region_code | Region / state code. | All |
| geo.city | City name. | All |
| geo.postal_code | Postal / ZIP code. | All |
| geo.latitude | Latitude (decimal degrees). | All |
| geo.longitude | Longitude (decimal degrees). | All |
| geo.timezone | IANA timezone identifier (e.g. Europe/Berlin). | All |
| geo.is_sanctioned | True if the country is on OFAC, EU, or UN sanction lists. | All |
| geo.sanction_lists | Array of applicable sanction programs, e.g. ["OFAC","EU"]. | All |
| network.asn | Autonomous System Number. | Starter+ |
| network.as_name | AS organisation name. | Starter+ |
| network.as_domain | AS organisation domain. | Starter+ |
| network.isp | Internet Service Provider name. | All |
| network.organization | Network organisation name. | All |
| network.connection_type | residential, datacenter, mobile, education, or government. | All |
| threat.is_vpn | True if the IP is a known VPN endpoint. | Pro+ |
| threat.is_proxy | True if the IP is a known open proxy. | Pro+ |
| threat.is_tor | True if the IP is a Tor exit node. | Pro+ |
| threat.is_relay | True if the IP is an anonymous relay. | Pro+ |
| threat.is_hosting | True if the IP belongs to a hosting provider. | Pro+ |
| threat.threat_score | Composite risk score 0–100. A signal, not a final verdict — combine with account, payment, device and behavior data. | Pro+ |
| threat.threat_categories | Array of threat category strings. | Pro+ |
| threat.bot_type | Verified bot identifier (e.g. "googlebot", "bingbot") or null. Verified via reverse-DNS + forward confirmation. | All |
| abuse.contact_email | Abuse contact email from WHOIS data. | Pro+ |
$ curl https://api.openipapi.com/v1/lookup/185.220.101.45 \
-H "X-API-Key: oip_your_api_key_here"
{
"ip": "185.220.101.45",
"type": "IPv4",
"geo": {
"country_code": "DE",
"country": "Germany",
"region": "Hessen",
"region_code": "HE",
"city": "Frankfurt am Main",
"postal_code": "60313",
"latitude": 50.1109,
"longitude": 8.6821,
"timezone": "Europe/Berlin",
"is_sanctioned": false,
"sanction_lists": []
},
"network": {
"asn": 205100,
"as_name": "F3 Netze e.V.",
"as_domain": "f3netze.de",
"isp": "F3 Netze",
"organization": "F3 Netze e.V.",
"connection_type": "datacenter"
},
"threat": {
"is_vpn": true,
"is_proxy": false,
"is_tor": true,
"is_relay": false,
"is_hosting": true,
"threat_score": 85,
"threat_categories": ["tor_exit_node", "known_abuser"],
"bot_type": null
},
"abuse": {
"contact_email": "abuse@f3netze.de"
}
}
Consulte múltiples direcciones IP en una sola solicitud. Los límites de tamaño de lote dependen de su plan.
https://api.openipapi.com/v1/lookup/batch
plan_required . | Plan | Máx. IP por solicitud |
|---|---|
| Starter | 100 |
| Pro | 500 |
| Business | 1,000 |
| Enterprise | 5,000 |
{
"ips": [
"185.220.101.45",
"8.8.8.8",
"1.1.1.1"
]
}
Devuelve un array envuelto de objetos de consulta completos, en el mismo orden que la solicitud.
{
"results": [
{ "ip": "185.220.101.45", /* full lookup object */ },
{ "ip": "8.8.8.8", /* full lookup object */ },
{ "ip": "1.1.1.1", /* full lookup object */ }
],
"count": 3
}
Devuelve datos de geolocalización y amenaza para la dirección IP que realiza la solicitud. Útil para funciones de "¿Cuál es mi IP?".
https://api.openipapi.com/v1/me
La respuesta es idéntica a GET /v1/lookup/{ip} con la IP del solicitante precargada.
$ curl https://api.openipapi.com/v1/me \
-H "X-API-Key: oip_your_api_key_here"
Recupera información detallada sobre un Número de Sistema Autónomo. Requiere plan Starter o superior.
https://api.openipapi.com/v1/asn/{asn}
El parámetro asn acepta tanto el formato 13335 como AS13335 .
$ curl https://api.openipapi.com/v1/asn/13335 \
-H "X-API-Key: oip_your_api_key_here"
{
"asn": 13335,
"as_name": "Cloudflare, Inc.",
"as_domain": "cloudflare.com",
"organization": "Cloudflare, Inc.",
"country_code": "US",
"ip_ranges_count": 1284,
"total_ips": 2359296
}
Valida una dirección IP y determina su tipo. No consume cuota de consultas.
https://api.openipapi.com/v1/validate/{ip}
{
"ip": "185.220.101.45",
"valid": true,
"type": "IPv4",
"private": false,
"bogon": false
}
Puntuación de fraude compuesta (0–100) con nivel de riesgo y recomendación accionable. Combina señales de VPN, proxy, Tor, centro de datos y abuso histórico. Plan Starter o superior
https://api.openipapi.com/v1/fraud/{ip}
{
"ip": "185.220.101.45",
"fraud_score": 92,
"risk_level": "critical",
"signals": {
"is_vpn": true,
"is_proxy": false,
"is_tor": true,
"is_datacenter": true,
"is_known_attacker": true,
"high_risk_country": false
},
"recommendation": "block"
}
| Puntuación | Nivel de riesgo | Recomendación | Acción típica |
|---|---|---|---|
| 0–30 | low | allow | Permitir la solicitud |
| 31–60 | medium | review | Registrar para revisión manual |
| 61–85 | high | challenge | Requerir CAPTCHA / 2FA / autenticación adicional |
| 86–100 | critical | block | Rechazar y alertar |
Datos de sondeo de red en tiempo real desde nuestros más de 60 nodos de sondeo activos: puertos TCP abiertos, banners de servicio, DNS inverso, detalle completo del certificado TLS (sujeto, emisor, SANs, validez) y categorías de servicio detectadas. Plan Pro o superior
https://api.openipapi.com/v1/probe/{ip}
"stale": true.{
"ip": "185.220.101.45",
"reachable": true,
"last_probed": "2026-04-18T14:23:11+00:00",
"age_hours": 2.3,
"stale": false,
"refresh_queued": false,
"probe_count_24h": 14,
"probed_from_nodes": 8,
"open_ports": [
{ "port": 22, "service": "ssh", "banner": "SSH-2.0-OpenSSH_8.9p1" },
{ "port": 80, "service": "http", "banner": "nginx/1.24.0" },
{ "port": 443, "service": "https", "banner": null },
{ "port": 9001, "service": "tor-relay", "banner": null }
],
"reverse_dns": "tor-exit.f3netze.de",
"tls": {
"subject_cn": "*.f3netze.de",
"issuer": "Let's Encrypt",
"valid_from": "2026-02-10T00:00:00Z",
"valid_to": "2026-05-10T00:00:00Z",
"sans": ["f3netze.de", "*.f3netze.de"],
"fingerprint": "7e:4f:...:b2:e1"
},
"banners": {
"22": "SSH-2.0-OpenSSH_8.9p1",
"80": "nginx/1.24.0"
},
"detected_services": {
"is_tor_relay": true,
"is_ssh_open": true,
"is_web_server": true,
"is_vpn": false,
"is_proxy": false
}
}
22 (ssh), 80 / 8080 (http), 443 / 8443 (https), 1080 (socks5), 3128 / 8888 (http-proxy), 9001 / 9030 (tor-relay / tor-dir), 9050 / 9150 (tor-socks), 1194 (openvpn), 4500 (ipsec-nat-t), 51820 (wireguard).
Identifica si una IP pertenece a un pool de proxy residencial conocido, VPN comercial o rango de centro de datos. A diferencia de los indicadores genéricos is_proxy este endpoint atribuye la IP al proveedor específico (Bright Data, Oxylabs, NordVPN, etc.) — fundamental para equipos de fraude que necesitan permitir algunos proveedores y bloquear otros. Complemento Proxy Intel
https://api.openipapi.com/v1/proxy-attribution/{ip}
{
"ip": "2.56.16.42",
"detected": true,
"primary_provider": {
"provider": "unknown_vpn",
"display_name": "Unknown VPN",
"network_type": "vpn",
"confidence": 0.75
},
"networks": [
{
"provider": "unknown_vpn",
"network_type": "vpn",
"confidence": 0.75,
"source": "x4bnet-vpn",
"cidr": "2.56.16.0/22"
},
{
"provider": "unknown_datacenter",
"network_type": "datacenter",
"confidence": 0.75,
"source": "x4bnet-datacenter"
}
],
"recommendation": "treat_as_vpn"
}
residential — pools de proxy residencial (Bright Data, Oxylabs, Smartproxy, IPRoyal, Hola, Honeygain, EarnApp, Peer2Profit, SOAX)vpn — proveedores de VPN comerciales (NordVPN, ExpressVPN, Surfshark, Mullvad, ProtonVPN, PIA, IPVanish, CyberGhost)datacenter — proveedores de hosting usados frecuentemente como salida de proxy comercial (AWS, DigitalOcean, OVH, Hetzner, etc.)tor — nodos de salida / relay Tormobile — pools de proxy de operadores móviles| Recomendación | Significado |
|---|---|
| no_proxy_detected | IP no coincide con ningún pool conocido — trátela como tráfico normal. |
| treat_as_commercial_proxy | La IP está en un pool de proxy residencial — probablemente maliciosa en sitios que no son de scraping. |
| treat_as_vpn | La IP está en un rango de VPN comercial — aplique la política de VPN. |
| treat_as_datacenter | La IP proviene de un rango de centro de datos — no es un usuario residencial real. |
| block_or_challenge | Salida Tor — bloquear o requerir autenticación fuerte. |
Devuelve estadísticas de uso del período de facturación actual para su cuenta.
https://api.openipapi.com/v1/account/usage
{
"plan": "Pro",
"period_start": "2026-03-01",
"period_end": "2026-03-31",
"lookups_used": 184320,
"lookups_limit": 500000,
"lookups_remaining": 315680,
"reset_at": "2026-04-01T00:00:00Z"
}
Lista las bases de datos MMDB disponibles para su plan. Reemplazos de MaxMind .mmdb para uso fuera de línea / en el edge — funciona con cualquier lector de MaxMind DB (PHP, Go, Python, Node.js, Rust, Java).
https://api.openipapi.com/v1/database/list
{
"plan": "Business",
"sources": [
{
"source": "country",
"filename": "geo-whois-asn-country.mmdb",
"size_bytes": 8225621,
"updated_at": "2026-04-18T02:00:00+00:00",
"etag": "\"fa2b851f9155838b\"",
"download_url": "https://api.openipapi.com/v1/database/download/country"
}
]
}
Transmite el archivo MMDB sin procesar. Soporta ETag +
If-None-Match para GET condicionales (304 Not Modified cuando el archivo no ha cambiado). Límite de velocidad: 10 descargas por fuente por día.
https://api.openipapi.com/v1/database/download/{source}
| Fuente | Contenido | Licencia | Plan requerido |
|---|---|---|---|
| country | Código de país + ASN | CC0 | Pro |
| asn | ASN + organización | CC0 | Business |
| city-geolite2 | Ciudad, región, lat/lon, zona horaria (GeoLite2) | MaxMind GeoLite2 EULA | Business |
| city-dbip | Ciudad (alternativa a GeoLite2) | DB-IP Lite | Enterprise |
# Download latest MMDB
$ curl -H "X-API-Key: YOUR_KEY" \
-o asn.mmdb \
https://api.openipapi.com/v1/database/download/asn
# Use with maxmind-db/reader
$ composer require maxmind-db/reader
<?php
use MaxMind\Db\Reader;
$reader = new Reader('asn.mmdb');
$record = $reader->get('8.8.8.8');
// ['autonomous_system_number' => 15169,
// 'autonomous_system_organization' => 'Google LLC']
Cada respuesta de /v1/lookup incluye dos campos en el bloque geo que indican si el país de la IP está sujeto a sanciones internacionales.
| Campo | Descripción |
|---|---|
| geo.is_sanctioned | true si el país aparece en alguna lista de sanciones monitoreada; false en caso contrario. |
| geo.sanction_lists | Array de identificadores de programas de sanciones aplicables: OFAC, EU, UN, UK. Array vacío [] cuando no hay sanciones. |
Listas de sanciones cubiertas: OFAC (EE. UU.), UE, Consejo de Seguridad de la ONU, OFSI del Reino Unido. Los países actualmente marcados incluyen Irán, Corea del Norte, Rusia, Bielorrusia, Siria, Cuba, Venezuela, Sudán y otros. La lista se mantiene y actualiza cuando los programas cambian.
"geo": {
"country_code": "IR",
"country": "Iran",
...
"is_sanctioned": true,
"sanction_lists": ["OFAC", "EU", "UN"]
}
OpenIPApi realiza verificación de DNS inverso doble para identificar rastreadores legítimos. El resultado está disponible en threat.bot_type en cada consulta.
| Campo | Valores |
|---|---|
| threat.bot_type |
null (no es un bot verificado) o uno de: googlebot,
google_special_crawl,
bingbot,
applebot,
yandexbot,
duckduckbot,
facebookbot,
semrushbot,
ahrefsbot,
mj12bot
|
Método de verificación: (1) Consulta PTR en la IP → nombre de host. (2) El nombre de host debe coincidir con el patrón de dominio del bot (p. ej. *.googlebot.com). (3) El DNS directo del nombre de host debe resolver de vuelta a la IP original. Los resultados se almacenan en caché durante 24 horas.
"threat": {
"is_vpn": false,
"is_proxy": false,
"is_tor": false,
"threat_score": 0,
"bot_type": "googlebot"
}
Añada un parámetro ?date=YYYY-MM-DD a cualquier consulta de IP individual para recuperar la instantánea de esa fecha.
https://api.openipapi.com/v1/lookup/{ip}?date=2026-01-15
$ curl "https://api.openipapi.com/v1/lookup/185.220.101.45?date=2026-01-15" \
-H "X-API-Key: oip_your_api_key_here"
{
"ip": "185.220.101.45",
"snapshot_date": "2026-01-15",
"is_historical": true,
"data": {
/* standard lookup response */
}
}
{
"error": "No historical snapshot available for this IP on 2026-01-15",
"code": "no_snapshot"
}
| Código | Estado HTTP | Descripción |
|---|---|---|
| invalid_api_key | 401 | La clave API falta, está mal formada o ha sido revocada. |
| limit_exceeded | 429 | Ha agotado todas las consultas de su período de facturación actual. |
| plan_required | 403 | La función solicitada no está disponible en su plan actual. |
| invalid_ip | 400 | La dirección IP proporcionada no es una dirección IPv4 o IPv6 válida. |
| not_found | 404 | No se encontraron datos para el recurso solicitado (p. ej., ASN desconocido). |
| no_snapshot | 404 | No existe una instantánea histórica de esta IP para la fecha solicitada. |
| date_out_of_range | 400 | La fecha de consulta histórica es superior a 365 días en el pasado. |
| invalid_date | 400 | El parámetro de fecha falta, está mal formado o es una fecha futura. |
| plan_upgrade_required | 403 | La función solicitada requiere un plan de nivel superior. |
| rate_limited | 429 | Demasiadas solicitudes en un período corto. Retroceda y reintente. |
| internal_error | 500 | Ocurrió un error inesperado en el servidor. Contacte a soporte si persiste. |
Además de las cuotas mensuales de consultas, las solicitudes tienen límites de velocidad por clave API mediante una ventana deslizante. Cuando se excede, la API devuelve HTTP 429 con una cabecera Retry-After .
| Plan | Solicitudes / minuto | Consultas / mes |
|---|---|---|
| Free | 30 | 10,000 |
| Starter | 120 | 100,000 |
| Pro | 300 | 500,000 |
| Business | 600 | 2,000,000 |
| Enterprise | Custom | Unlimited |
Límites adicionales: /v1/validate (sin autenticar) tiene un máximo de 60 solicitudes/min por IP del solicitante; /v1/me a 30 solicitudes/min. Las descargas MMDB tienen un límite de 10/día por fuente por cuenta. Las respuestas de límite de velocidad incluyen Retry-After.
Los webhooks le permiten recibir notificaciones HTTP POST en tiempo real cuando el estado de una IP que está monitoreando cambia. Configúrelos en la consola → Webhooks, o a través de la interfaz del panel — sin necesidad de llamada a la API.
| Evento | Se activa cuando |
|---|---|
| vpn_detected | Una IP monitoreada se detecta recientemente como endpoint VPN. |
| tor_detected | Una IP monitoreada aparece en una lista de nodos de salida Tor o se sondea como relay Tor. |
| proxy_detected | Una IP monitoreada se detecta como proxy abierto o SOCKS. |
| high_threat | La puntuación de amenaza supera su umbral configurado (50–95). |
POST https://your-endpoint.example.com/webhook
Content-Type: application/json
User-Agent: OpenIPApi-Webhook/1.0
X-OpenIPApi-Event: high_threat
X-OpenIPApi-Signature: sha256=8c7f1a...b2e
{
"event": "high_threat",
"delivered_at": "2026-04-18T12:34:56Z",
"webhook_id": 142,
"data": {
"ip": "185.220.101.45",
"threat_score": 92,
"previous_score": 45,
"is_tor": true,
"is_vpn": true
}
}
Cada webhook está firmado mediante HMAC-SHA256 del cuerpo JSON sin procesar con su secreto de webhook. La firma se envía en la cabecera X-OpenIPApi-Signature como sha256=<hex>.
Siempre verifique antes de actuar sobre el payload:
PHP
$body = file_get_contents('php://input');
$hdr = $_SERVER['HTTP_X_OPENIPAPI_SIGNATURE'] ?? '';
$expected = 'sha256=' . hash_hmac(
'sha256', $body, $webhookSecret
);
if (!hash_equals($expected, $hdr)) {
http_response_code(401);
exit;
}
// Safe to process $body now
Node.js (Express)
const crypto = require('crypto');
app.post('/webhook',
express.raw({ type: 'application/json' }),
(req, res) => {
const hdr = req.headers['x-openipapi-signature'];
const expected = 'sha256=' + crypto
.createHmac('sha256', process.env.WEBHOOK_SECRET)
.update(req.body).digest('hex');
if (expected !== hdr) return res.status(401).end();
// Process JSON.parse(req.body)
});
Su endpoint debe responder dentro de 10 segundos con HTTP 2xx para confirmar la recepción. Cualquier otro estado (o tiempo de espera agotado) activa reintentos con retroceso exponencial: 1 min, 5 min, 30 min, 2 h, 12 h. Tras el último intento, el webhook se marca como fallido y se genera una alerta en el panel.
La consola → Webhooks guarda los últimos 100 intentos de entrega por cuenta, mostrando el tipo de evento, código de estado HTTP y el cuerpo de respuesta devuelto por su endpoint. Puede repetir cualquier entrega anterior para reenviar el payload firmado original, y usar el Depurador de Firmas incorporado para verificar firmas HMAC-SHA256 en el lado del cliente sin compartir su secreto con ningún servidor.
Las entregas repetidas incluyen una cabecera adicional X-OpenIPApi-Replay: 1 para que su endpoint pueda distinguirlas de los eventos en vivo.
$ curl https://api.openipapi.com/v1/lookup/8.8.8.8 \
-H "X-API-Key: oip_your_api_key_here"
$ curl -X POST https://api.openipapi.com/v1/lookup/batch \
-H "X-API-Key: oip_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{"ips": ["8.8.8.8", "1.1.1.1", "185.220.101.45"]}'
$ curl https://api.openipapi.com/v1/me \
-H "X-API-Key: oip_your_api_key_here"
const response = await fetch('https://api.openipapi.com/v1/lookup/8.8.8.8', {
headers: {
'X-API-Key': 'oip_your_api_key_here'
}
});
const data = await response.json();
console.log(data.geo.country); // "United States"
console.log(data.threat.is_vpn); // false
console.log(data.threat.threat_score); // 0
const response = await fetch('https://api.openipapi.com/v1/lookup/batch', {
method: 'POST',
headers: {
'X-API-Key': 'oip_your_api_key_here',
'Content-Type': 'application/json'
},
body: JSON.stringify({
ips: ['8.8.8.8', '1.1.1.1', '185.220.101.45']
})
});
const { results } = await response.json();
for (const info of results) {
console.log(info.ip, info.geo.city, info.threat.threat_score);
}
import requests
API_KEY = "oip_your_api_key_here"
headers = {"X-API-Key": API_KEY}
r = requests.get(
"https://api.openipapi.com/v1/lookup/8.8.8.8",
headers=headers
)
r.raise_for_status()
data = r.json()
print(data["geo"]["country"]) # United States
print(data["threat"]["is_vpn"]) # False
print(data["threat"]["threat_score"]) # 0
import requests
API_KEY = "oip_your_api_key_here"
headers = {
"X-API-Key": API_KEY,
"Content-Type": "application/json"
}
payload = {
"ips": ["8.8.8.8", "1.1.1.1", "185.220.101.45"]
}
r = requests.post(
"https://api.openipapi.com/v1/lookup/batch",
json=payload,
headers=headers
)
r.raise_for_status()
for info in r.json()["results"]:
print(info["ip"], info["geo"]["city"], info["threat"]["threat_score"])
10 000 consultas gratuitas al mes. No requiere tarjeta de crédito.
Obtenga su clave API gratuita