IP Lookup API — геолокация, данные RDAP, ASN и безопасность
IP lookUp — бесплатный REST API, который превращает любой IP-адрес в данные геолокации, RDAP-реестра, ASN/сети и VPN/прокси/threat-intel. Вызовите GET /api/v1/ip, чтобы получить базовый результат без регистрации, или добавьте ?include=geo,network,security для полного набора полей, описанного ниже.
Введение
IP lookUp превращает IP-адрес вызывающего (или любой запрошенный адрес) в сигналы доверия и безопасности, геолокацию и сетевую/ASN-идентификацию — получаемые в реальном времени из RDAP, гео- и threat-intel данных, а не из статических таблиц.
Базовый URL:
/api/v1
Для базового запроса не нужны ни регистрация, ни API-ключ — группы обогащения и более высокие лимиты открываются с бесплатным токеном.
Быстрый старт
1. Базовый запрос — без ключа
curl /api/v1/ip
2. Добавьте группы обогащения
curl "/api/v1/ip?include=geo,network,security"
3. Авторизуйтесь токеном для более высоких лимитов
curl -H "Authorization: Bearer <token>" "/api/v1/ip?include=all"
Попробовать
Сформируйте настоящий запрос к этому API и посмотрите ответ в реальном времени.
Эндпоинт
GET /api/v1/ip
Включаемые группы
Статус: · Время:
Какие данные вы получаете
Каждое поле ниже входит в JSON-конверт ответа v2, сформированный из актуальной схемы API.
Гео
| Поле | Тип | Описание |
|---|---|---|
| geo.alternatives | web.geoAltV2[] | Alternatives are the losing geo sources' readings for this IP: each is that source's most-specific covering location plus its own source name and date. Omitted when only one source covers the IP. |
| geo.city | string | City is the city name from the winning source; "geo" group. |
| geo.cityNameLocal | string | CityNameLocal is the city's Russian name from the offline GeoNames gazetteer — resolved from the winner's (countryCode, region, city) text. Empty when the gazetteer has no match, no ru altname exists for the matched city, or there was nothing to resolve (no country/city on the winner). Part of the "geo" group like City itself — omitted on a baseline country-only response. |
| geo.confidence | string | Confidence flags city-level geo precision as "low" for network types where the city reading is unreliable (by default, mobile/carrier ranges, where the registered location often differs from the subscriber's). |
| geo.continent | string | Continent is the two-letter continent code, re-derived alongside CountryName from the country table; baseline. |
| geo.countryCode | string | CountryCode is the ISO 3166-1 alpha-2 country code from the winning geo source (DB-IP City Lite or an RFC 8805 geofeed); baseline (always present whenever any geo data exists for the IP). |
| geo.countryName | string | CountryName is the country's display name, re-derived from the country table for CountryCode (so a country-only override never carries a stale name); baseline. |
| geo.date | string | Date is the winning geo source's last-seen date, RFC3339 UTC date-time — the same format as the top-level cachedAt. Omitted when unknown. |
| geo.geonameId | integer | GeonameID is the matched GeoNames gazetteer entry's id — a stable cross-source city identifier distinct from City's raw text. Nilable: nil (JSON null/absent) means a resolve miss, never a fabricated 0. Part of the "geo" group like City itself. |
| geo.isEu | boolean | IsEu reports whether CountryCode is an EU member state, re-derived from the country table like CountryName/Continent; baseline. |
| geo.lat | number | Lat is the latitude in decimal degrees; nil means genuinely unknown, distinct from a real 0.0 reading at the equator. "geo" group. |
| geo.license | string | License is the winning source's data license (e.g. "CC BY 4.0" for dbip-city) — provenance/attribution detail, not baseline. Present only alongside the extended geo fields above, on a verbose request. Omitted when the source has no recorded license. |
| geo.lon | number | Lon is the longitude in decimal degrees; same nil-vs-0.0 semantics as Lat. "geo" group. |
| geo.matchConfidence | string | MatchConfidence is the match-quality signal for the cityNameLocal/geonameId resolve: "high" when country+admin1+name all matched, "low" when it fell back to a country+name-only homonym pick. Omitted (not "unknown") on a resolve miss — a consumer must not read absence as low confidence, only as "no match at all". Deliberately a SEPARATE field from Confidence above: Confidence is net-type-driven geo precision (mobile/MVNO carrier heuristic), MatchConfidence is gazetteer string-match quality — unrelated signals, never merged. |
| geo.postal | string | Postal is the postal/ZIP code; always empty today (DB-IP City Lite carries no postal data) — reserved for a future source. "geo" group. |
| geo.region | string | Region is the state/province/administrative-region name from the winning source; part of the "geo" group (entitlement.SetGeo) — empty on a baseline country-only response. |
| geo.regionMatchConfidence | string | RegionMatchConfidence reports the stored raw-region to GeoNames admin1 resolution quality. Omitted when the raw fallback is used. |
| geo.retrievedDate | string | RetrievedDate is when the continuous RIR crawler retrieved the winning source observation, RFC3339 UTC. Verbose-only and omitted for non-RIR or legacy unmarked RIR rows; this is deliberately distinct from Date (SCD-2 last_seen). |
| geo.source | string | Source is geo provenance: the name of the trust-ranked winning geo source (e.g. "dbip-city" or "aws-geofeed"). Always populated when geo is present (the winner is whichever source the merge picked); omitempty is kept only for the degenerate case of an unnamed source. |
| geo.timezone | string | Timezone is the IANA zone name (e.g. "Europe/Moscow") for the resolved location; "geo" group. |
| geo.url | string | URL is the winning geo source's own reference link (its dataset homepage or download page, e.g. "https://db-ip.com/db/lite.php" for dbip-city) — attribution/provenance detail alongside License, not a per-IP resource link. Same gating and omission rule as License. |
Сеть
| Поле | Тип | Описание |
|---|---|---|
| network.allAsns | string[] | AllASNs lists every ASN Team Cymru reports announcing this prefix (multi-origin); always a non-nil array, empty when there's only one/none. |
| network.allocated | string | Allocated is Prefix's allocation date from Team Cymru — an allocation TIMESTAMP, not a usage-type flag (see UsageHint for that). |
| network.asName | string | ASName is the Team Cymru AS holder name — the coarse registered name, distinct from the refined network.classification.provider. |
| network.asn | string | ASN is the announcing Autonomous System number from Team Cymru (e.g. "AS15169"); baseline (always present for a routable IP with ASN data). |
| network.asnDomain | string | AsnDomain is the offline iplocate org's domain, sibling to AsnOrg; nil under the same conditions. |
| network.asnFetchedAt | string | ASNFetchedAt is the fetch time of the Team Cymru ASN facts above (asn/ allAsns/asName/prefix/registry/allocated/usageHint); see RDAPFetchedAt's doc above for the nil-vs-empty-string rule. Verbose-only. |
| network.asnOrg | string | AsnOrg/AsnDomain carry the offline iplocate org name/domain, populated from the MariaDB data resolver. nil/null when the resolver is off or the IP has no matching ASN block. These are distinct from the live Cymru facts above (asn/asName/prefix/registry/allocated/usageHint). |
| network.classification | netinfo.Result | Classification is the synthesized IP-type verdict (hosting/datacenter/ residential/mobile/…); always populated for a routable IP. |
| network.prefix | string | Prefix is the announced CIDR block covering the IP, from Team Cymru. |
| network.rdap | rdap.Info | RDAP is a pointer so the block is JSON null when there is no RDAP data at all; when the "network" group isn't included in the response it instead carries a trimmed {country, handle, name} subset (always present at baseline). asnOrg/asnDomain above are nullable for the same not-included reason. |
| network.rdapFetchedAt | string | RDAPFetchedAt/ASNFetchedAt are the fetch times of the RDAP registry record and the Team Cymru ASN facts above, RFC3339 (same format as the top-level cachedAt). Verbose-only: nil (omitted) on a non-verbose request. On a verbose request the pointer distinguishes two states that both stringify to "": nil means the source was never resolved (disabled, or genuinely no data), while a non-nil pointer to "" means the sibling data (rdap/asn) IS present but the store that served it can't report a fetch time (e.g. a MariaDB-only deployment). Without this, a consumer can't tell "no data" from "data, unknown age". |
| network.registry | string | Registry is the RIR that allocated Prefix (e.g. "ripencc", "arin"), from Team Cymru. |
| network.usageHint | string | UsageHint is Team Cymru's coarse allocation type (e.g. "DIRECT ALLOCATION", "ASSIGNED PA"), not a usage-type classification of the IP itself. |
Безопасность
| Поле | Тип | Описание |
|---|---|---|
| privacy.isAnonymous | boolean | IsAnonymous is derived as IsTor || IsVPN || IsProxy; inherits IsTor's degraded-false posture when the cloudtor matcher didn't run, and IsProxy's when the net-flags resolver didn't run/match. |
| privacy.isProxy | boolean | IsProxy is the IPFire libloc "is-anonymous-proxy" network flag: false when the underlying resolver is disabled, has no covering data for the address, or errored — same best-effort posture as IsVPN's rules signal. No other proxy data source is wired. |
| privacy.isRelay | boolean | IsRelay always reports false — no adopted data source (unused today). |
| privacy.isResidentialProxy | boolean | IsResidentialProxy always reports false — no free data source exists (known gap). |
| privacy.isTor | boolean | IsTor reuses the cloudtor Tor-exit match (flags.isTor); degraded to false (not an authoritative negative) when Tor detection isn't enabled server-side. |
| privacy.isVpn | boolean | IsVPN is the coarse VPN/hosting-posture signal: true only when network.classification.source is "rule" (X4BNet-derived hosting/ datacenter rows) AND type is hosting or datacenter — excludes the weaker cloud- and heuristic-sourced hosting matches. |
| threat.isMalicious | boolean | IsMalicious is the aggregate malicious-IP verdict across the loaded threat-intelligence feeds; only present when the security group was evaluated. |
| threat.reports | web.threatReportV2[] | Reports is the verbose evidence-API payload: one entry per persisted MISP event backing this IP's match. Omitted (nil) for a non-verbose caller, an unmatched/unevaluated IP, or when the evidence lookup errored. |
| threat.sources | string[] | Sources lists which loaded threat-intel feeds flagged the IP; always a non-nil array, empty ([]) for a clean IP. |
| threat.threatLevel | integer | ThreatLevel is the aggregated (most-severe/min) MISP threat_level_id across every matching entry that carries one: 1=High, 2=Medium, 3=Low, 4=Undefined. Nil (omitted) when no matching entry carries a level — e.g. a clean IP, or a match backed only by thin/index-only (non-MISP) sources. Gated identically to isMalicious/sources (the security group only) — independent of verbose, unlike Reports below. |
| recon.isScanner | boolean | IsScanner is the advisory active-recon/brute-force verdict from the Dataplane.org matcher; only present when recon was actually evaluated (this whole block is null otherwise). NOT threat.isMalicious. |
| recon.lastSeen | string | LastSeen is the most recent contributing signal's own observation timestamp (RFC3339, same format as cachedAt/geo.date) — lets a consumer judge how fresh the scanning activity is, since Dataplane's recon feeds age out via a configured decay window rather than staying "hot" forever between refreshes. Omitted when unknown (e.g. IsScanner false, or every contributing row carried an unparseable timestamp). |
| recon.sources | string[] | Sources lists which Dataplane.org signal(s) recently observed the IP (e.g. "sshpwauth", "telnetlogin"); always a non-nil array, empty ([]) for a clean IP — mirrors threat.sources' convention. |
| censorship.confirmedRate | number | ConfirmedRate is the fraction of OONI measurements classified as confirmed blocking over the rolling window, for the caller's ASN+country. |
| censorship.isCensored | boolean | IsCensored reports whether ConfirmedRate exceeds the configured blocking threshold for the caller's ASN+country (OONI-derived). |
| censorship.sampleSize | integer | SampleSize is the number of OONI measurements aggregated into ConfirmedRate. |
| fraud.level | string | Level buckets Score into low/medium/high against the service's configured thresholds. |
| fraud.score | integer | Score is the 0-100 risk-score rollup: a weighted sum of the fired Signals, saturating at 100. |
| fraud.signals | string[] | Signals names every weighted input that fired (e.g. "hosting", "vpn", "tor", "malicious", "censored", "ptrMissing", "bulkMail"), so Score is explainable; empty ([]) for a clean IP. |
Тариф и лимиты
| Поле | Тип | Описание |
|---|---|---|
| plan.groups | map<web.groupPlanV2> | Groups is keyed by metered group name (geo/network/security); request-scoped like limited[]/gated[] — a group this request's metering pipeline never reached (not requested, gated, or concurrent-duplicate withheld) has no entry, since there is no live-peek primitive for an unrequested group's cardinality without mutating its SET. |
| plan.servedFromTopup | string[] | ServedFromTopup lists metered groups whose per-day budget was exhausted this request and were served from the persistent top-up bucket instead. |
| plan.tier | string | Tier duplicates the top-level Tier field (self-contained for a consumer reading only the plan section, same as GET /api/v1/usage's own "tier"). |
| plan.tokenName | string | TokenName is the API token's name, present when the caller authenticated via an opaque API token; omitted for a session-JWT-authed or anonymous caller. |
Эндпоинты
| Эндпоинт | Тарифицируемая группа | Поддержка ?include= | Описание |
|---|---|---|---|
| GET /api/v1/ip | geo, network, security (opt-in) | да — geo, network, security, all |
Базовая классификация, возвращается всегда; группы geo/network/security подключаются через ?include=. |
| GET /api | geo, network, security (opt-in) | да — geo, network, security, all |
Алиас без версии — всегда отражает текущий последний базовый эндпоинт (сейчас это /api/v1/ip). |
Примеры кода
Готовые к использованию примеры вызова API на популярных языках.
Аутентификация и лимиты
Аутентификация и токены
Создавайте и управляйте API-токенами в личном кабинете — просто войдите, отдельной заявки не нужно.
Передавайте его в заголовке запроса:
Authorization: Bearer <token>
Базовый запрос вообще не требует ключа. Токен даёт более высокие лимиты по группам, чем анонимный уровень — сравнение ниже.
Получить токенЛимиты и учёт
Обогащение учитывается по уникальному IP вызывающего, отдельно для каждой группы — geo, network, security — как по суточному, так и по минутному бюджету. Базовые поля /api/v1/ip возвращаются всегда; бюджетируются только группы обогащения.
Превышение бюджета никогда не приводит к отказу в запросе. Ответ по-прежнему возвращается с HTTP 200, status: "partial", а удержанная группа перечисляется в limited[] — поля этой группы для данного вызова просто null.
Раздел plan в ответе показывает ваш уровень, остаток суточного/минутного бюджета по каждой запрошенной группе и остаток топ-апа — так видно, сколько осталось, без отдельного запроса.
| Параметр | Анонимно | С API-токеном |
|---|---|---|
| Базовый запрос | Всегда доступен, без регистрации | Всегда доступен |
| Обогащённые группы (geo/network/security) | Учитывается по суточному/минутному бюджету анонимного уровня | Учитывается по суточному/минутному бюджету вашего уровня (обычно выше) |
| Точные значения лимитов | См. /pricing.html или GET /api/v1/usage — всегда читается вживую из вашего аккаунта | |
| При превышении бюджета | HTTP 200 со status: "partial", группа перечислена в limited[] — никогда не жёсткая ошибка | |
Открытые проекты могут запросить бесплатный уровень Pro или Business на один год — по запросу.
Смотреть тарифы и уровниЧасто задаваемые вопросы
- Бесплатен ли IP lookup API?
- Да. GET /api/v1/ip не требует регистрации или API-ключа и бесплатно возвращает базовую классификацию, сетевые и DNS-данные, а также геолокацию на уровне страны. Группы обогащения geo, network и security тарифицируются по уникальному IP в сутки; регистрация бесплатного токена переводит тарификацию на собственный (обычно более высокий) лимит вашего аккаунта, а open-source проекты могут бесплатно получить тариф Pro или Business на год.
- Какие данные возвращает IP lookup API?
- Каждый ответ включает классификацию IP, данные ASN/сети, DNS (PTR/hostname) и геолокацию на уровне страны. Добавьте ?include=geo,network,security, чтобы получить расширенные гео-поля, полную запись RDAP-реестра и сигналы privacy/threat/fraud — полный справочник полей приведён в документации на https://ip.xakki.pro/docs/.
- Определяет ли API использование VPN, прокси или Tor?
- Отчасти, и вот точная формулировка: isVpn — это вывод по классификации сети, а не поиск по списку VPN-провайдеров — флаг true только тогда, когда сеть адреса классифицирована как хостинг/дата-центр (по курируемым правилам определения хостинговых сетей) — тип сетевой инфраструктуры, на которой обычно работают VPN-сервисы. isProxy берётся из отдельного сетевого флага анонимного прокси (IPFire libloc) — тоже по инфраструктуре, а не по базе прокси-сервисов. isTor сверяется со списком известных Tor exit-узлов. isAnonymous — это просто isTor || isVpn || isProxy. Два смежных поля, isResidentialProxy и isRelay, зарезервированы в схеме, но сейчас всегда возвращают false — источник данных для них не подключён, поэтому не считайте их рабочими сигналами. Блок threat отдельно сообщает об известных источниках угроз, а блок fraud объединяет все сигналы в единую оценку риска от 0 до 100.
- Как устроена аутентификация и лимиты запросов API?
- Создайте токен в личном кабинете и передавайте его как Authorization: Bearer <token>. Обогащение тарифицируется по числу уникальных IP-адресов, которые вы запрашиваете, — в сутки и в минуту, отдельно для каждой группы, — поэтому повторные запросы одного и того же адреса в пределах окна ничего не стоят. Превышение бюджета никогда не приводит к отказу в запросе: ответ приходит с HTTP 200, status: "partial", а удержанная группа перечислена в limited[].
- Можно ли получить ASN и данные RDAP-реестра для IP?
- Да. Группа network возвращает полную запись RDAP-реестра (организация, контакты, примечания, статус) и данные ASN от Team Cymru — анонсирующий ASN, название AS, префикс, реестр и дату выделения.
Полный справочник
Изучите весь набор API в Swagger UI или скачайте необработанную спецификацию OpenAPI.