← ifconfig.rs

API reference

How to talk to ifconfig.rs from scripts, services, and CLIs.

Overview #

ifconfig.rs serves the visitor's own public IP plus optional geolocation and network enrichment data. The same payload is exposed in three flavors – text/plain, application/json, application/xml – over plain HTTP GET.

The machine-readable OpenAPI 3 spec lives at /api/openapi.json.

Endpoints #

PathContent typeNotes
GET /text/plain · text/htmlContent-negotiates by User-Agent. curl, wget, httpie get plain IP; browsers get the landing page.
GET /plaintext/plainAlways plain text. Best IP (IPv4 preferred) followed by a newline.
GET /jsonapplication/jsonFull payload. Optional ?ip=<addr> looks up an arbitrary IPv4 / IPv6 literal instead of the caller's own address (try it in the browser).
GET /xmlapplication/xmlSame payload as /json, formatted as XML. Optional ?ip=<addr> looks up an arbitrary IPv4 / IPv6 literal instead of the caller's own address.

Family-specific hosts #

The bare ifconfig.rs is dual-stack (it has both A and AAAA records). To force a single family at the transport layer, use the family-specific subdomains – they expose the same endpoints but resolve to one address family only:

HostDNSWhat you get
v4.ifconfig.rsA onlyConnection is forced over IPv4; the returned query is your IPv4.
v6.ifconfig.rsAAAA onlyConnection is forced over IPv6; the returned query is your IPv6.

Examples #

Quick CLI invocations:

$ curl ifconfig.rs
$ curl ifconfig.rs/plain
$ curl ifconfig.rs/json
$ curl v4.ifconfig.rs/plain
$ curl v6.ifconfig.rs/plain
$ curl ifconfig.rs/json?ip=1.1.1.1
$ curl ifconfig.rs/json?ip=2606:4700:4700::1111
$ curl ifconfig.rs/xml
$ curl ifconfig.rs/xml?ip=1.1.1.1

Look-up mode #

When ?ip= is set, /json and /xml both run the supplied IPv4 or IPv6 literal through the same enrichment pipeline used for the caller's own address. Every response carries a status envelope: success when the address is publicly routable, fail when it is not (with a message explaining why – invalid query, private range, reserved range, or not in database). The supplied input is echoed back as query (absent when the input was empty or whitespace-only).

Sample JSON response (successful lookup):

{
    "status": "success",
    "query": "203.0.113.42",
    "continent": "Europe",
    "continentCode": "EU",
    "country": "Serbia",
    "countryCode": "RS",
    "region": "VO",
    "regionName": "Vojvodina",
    "city": "Novi Sad",
    "zip": "21000",
    "lat": 45.2671,
    "lon": 19.8335,
    "timezone": "Europe/Belgrade",
    "offset": 7200,
    "currency": "RSD",
    "isp": "Telekom Srbija",
    "org": "Telekom Srbija a.d.",
    "as": "AS8400 TELEKOM SRBIJA a.d.",
    "asname": "TELEKOM-AS",
    "reverse": "static-203-0-113-42.telekom.rs",
    "mobile": false,
    "proxy": false,
    "hosting": false
}

Sample JSON response (failed lookup – private address):

{
    "status": "fail",
    "message": "private range",
    "query": "10.0.0.1"
}

Sample XML response:

<?xml version="1.0" encoding="UTF-8"?>
<Info>
    <status>success</status>
    <query>203.0.113.42</query>
    <continent>Europe</continent>
    <continentCode>EU</continentCode>
    <country>Serbia</country>
    <countryCode>RS</countryCode>
    <region>VO</region>
    <regionName>Vojvodina</regionName>
    <city>Novi Sad</city>
    <zip>21000</zip>
    <lat>45.2671</lat>
    <lon>19.8335</lon>
    <timezone>Europe/Belgrade</timezone>
    <offset>7200</offset>
    <currency>RSD</currency>
    <isp>Telekom Srbija</isp>
    <org>Telekom Srbija a.d.</org>
    <as>AS8400 TELEKOM SRBIJA a.d.</as>
    <asname>TELEKOM-AS</asname>
    <reverse>static-203-0-113-42.telekom.rs</reverse>
    <mobile>false</mobile>
    <proxy>false</proxy>
    <hosting>false</hosting>
</Info>

Response shape #

All /json and /xml responses are a single flat key-value object – every field at the top level, no nested wrappers. Missing fields are omitted from the response.

Tick the boxes to build the corresponding ?fields= URL. With every box checked, the URL is the bare endpoint (no filter); unticking any field switches to an explicit whitelist. Two equivalent forms are shown: a comma-separated list and a numeric bitmask – each field's bit value (1, 2, 4, 8, …) is published at /api/fields, OR them together to build the integer. The numeric form is just shorter on the wire.

$ curl
$ curl
FieldDescriptionExampleType
statusLookup outcome – success when the IP is publicly routable, fail otherwise.successstring
messageReason when status=fail: one of invalid query, private range, reserved range, not in database (valid public address we have no data for). Absent on success.private rangestring
queryEcho of the input: the caller's IP in client mode, the ?ip= value in lookup mode, the per-item address in batch mode.203.0.113.42string
continentContinent name.Europestring
continentCodeTwo-letter continent code.EUstring
countryCountry name.Serbiastring
countryCodeTwo-letter country code (ISO 3166-1 alpha-2).RSstring
regionRegion / state short code (FIPS or ISO).VOstring
regionNameRegion / state full name.Vojvodinastring
cityCity name.Novi Sadstring
districtDistrict (subdivision of a city). Not available for every address.Limanstring
zipPostal / ZIP code.21000string
latLatitude.45.2671float
lonLongitude.19.8335float
timezoneTimezone identifier (tz database).Europe/Belgradestring
offsetTimezone UTC offset, in seconds (includes DST).7200int
currencyNational currency code.RSDstring
ispISP name.Telekom Srbijastring
orgOrganization name (may differ from ISP).Telekom Srbija a.d.string
asAS number and organization, separated by space (RIR). Empty for IP blocks not announced in BGP.AS8400 TELEKOM SRBIJA a.d.string
asnameAS name (RIR).TELEKOM-ASstring
reverseReverse DNS (PTR) of the IP.static-203-0-113-42.telekom.rsstring
mobileMobile (cellular) connection.falsebool
proxyProxy, VPN, or Tor exit address.falsebool
hostingHosting / co-located / data-center IP.falsebool
disputedNeutrality marker. Present and true only when the country lies in an internationally contested territory (e.g., Crimea, Western Sahara, Kosovo). The country is our geolocation provider's attribution, not a position of ifconfig.rs. Absent otherwise.truebool

Not every field is available for every address. When data is missing, it is dropped from the response – clients should treat the absence of a key as "unknown", not as an empty string or zero.

Authentication (API keys) #

Anonymous use is free and unauthenticated. For higher rate limits, contact us to be provisioned an API key. Once issued, you have two equivalent ways to send it:

  • Header (preferred): Authorization: Bearer YOUR_KEY
  • Query param: ?api_key=YOUR_KEY

If both are present, the header wins. A key may be restricted to a list of source IP ranges; calls from outside the allowlist are rejected with 403.

$ curl -H "Authorization: Bearer YOUR_API_KEY" ifconfig.rs/json
$ curl "ifconfig.rs/json?api_key=YOUR_API_KEY"

Rate limiting #

Two layers run in parallel:

  • Per-IP – anonymous traffic is limited to 60 requests per minute per source IP.
  • Per-key – authenticated traffic uses the key's own per-minute and per-day quotas.

When a key is presented, the per-key limiter takes over for that request; the per-IP limit is not also counted.

Every IP-limited response carries the current budget in its headers (X-RateLimit-* convention popularized by GitHub / Twitter / Stripe):

  • X-RateLimit-Limit – the ceiling for the window (always 60 on the per-IP path).
  • X-RateLimit-Remaining – requests left in the current 60-second window (zero once the window is exhausted).
  • X-RateLimit-Reset – seconds until the window resets and the budget refills.

When the budget is exhausted the server returns 429 Too Many Requests and adds Retry-After with the same seconds-until-reset value. A well-behaved client reads X-RateLimit-Remaining and stops sending when it reaches 0 rather than hammering until it sees a 429. The headers are not emitted on the per-key path – authenticated callers track their quotas against the budget published in the key contract.

Batch endpoint #

POST /batch resolves up to 100 addresses in a single call. API key required – anonymous callers receive 401 (there is no per-IP path for batch).

Body is a JSON array of items; each carries the address to look up and an optional per-item fields whitelist (same syntax as ?fields= on /json). The response is a JSON array of the same length, in the same order, each entry being a flat FlatInfo object. The mapping is positional and guaranteed: the i-th result is the answer for the i-th input item (never reordered or deduplicated). Each entry also echoes its query, so you can match by index or by value.

Quota cost equals the number of items: a batch of 100 against a 60/min key returns 429 for the whole call (no partial consumption).

$ curl -X POST -H "Authorization: Bearer YOUR_API_KEY" \
       -H "Content-Type: application/json" \
       -d '[
             {"query": "8.8.8.8"},
             {"query": "1.1.1.1", "fields": "country,city,isp"},
             {"query": "10.0.0.1"}
           ]' \
       ifconfig.rs/batch
[
    { "status": "success", "query": "8.8.8.8",  "country": "United States", "city": "Mountain View", "isp": "Google LLC", ... },
    { "status": "success", "query": "1.1.1.1",  "country": "Australia",     "city": "South Brisbane", "isp": "Cloudflare, Inc." },
    { "status": "fail",    "message": "private range", "query": "10.0.0.1" }
]

HTTP status codes #

CodeMeaning
200Success.
400 Bad RequestUnknown name in ?fields=, all-empty ?fields=, malformed /batch body, empty batch, or batch larger than 100 items.
401 UnauthorizedAn Authorization: Bearer header or ?api_key= was supplied but the key is unknown / revoked. Also returned by /batch when no key is sent at all.
403 ForbiddenKey is valid, but the source IP is outside its allowlist.
429 Too Many RequestsPer-IP, per-minute, or per-day quota exhausted. Retry after the window resets.
503 Service Unavailable/batch only – no API keys are configured server-side, so the endpoint is disabled.

Java client #

An official Java client is published to Maven Central – a thin wrapper over the JDK HttpClient with Jackson, no other HTTP dependency. Requires JDK 21+. Source: github.com/adsdevdoo/ifconfig-java.

<dependency>
    <groupId>rs.adsdev</groupId>
    <artifactId>ifconfig-java</artifactId>
    <version>1.0.1</version>
</dependency>
IfconfigClient client = IfconfigClient.builder()
        .apiKey("alpha-prod-secret-xxx") // required only for /batch
        .build();

IpInfo me = client.myIp();                    // GET /json
IpInfo ip = client.lookup("8.8.8.8");         // GET /json?ip=8.8.8.8
IpInfo c  = client.lookup("8.8.8.8",          // GET /json?ip=8.8.8.8&fields=country,city
        EnumSet.of(Field.COUNTRY, Field.CITY));

List<IpInfo> hits = client.batch(List.of(     // POST /batch
        new BatchQuery("1.1.1.1"),
        new BatchQuery("8.8.8.8")));

Non-2xx responses surface as IfconfigException, which carries the HTTP status code and the raw body so callers can branch on rate-limit (429), bad request (400), etc.

Stability #

The fields documented here are stable. We may add new optional fields without notice; we will not remove or rename existing ones without a deprecation note posted on this page first.

Contact #

For API keys, abuse reports, or integration help, reach us at .

← ifconfig.rs

API referenca

Kako komunicirati sa ifconfig.rs iz skripti, servisa i komandne linije.

Pregled #

ifconfig.rs vraća sopstvenu javnu IP adresu posetioca uz opcione podatke o geolokaciji i mreži. Isti payload je dostupan u tri formata – text/plain, application/json, application/xml – preko običnog HTTP GET-a.

Mašinski čitljiv OpenAPI 3 spec se nalazi na /api/openapi.json.

Endpoint-i #

PutanjaContent typeNapomene
GET /text/plain · text/htmlContent-negocijacija po User-Agent-u. curl, wget, httpie dobijaju plain IP; pregledači dobijaju landing stranicu.
GET /plaintext/plainUvek plain tekst. Najbolja IP (IPv4 preferred) i znak nove linije.
GET /jsonapplication/jsonPun payload. Opcioni ?ip=<addr> obrađuje proizvoljan IPv4 / IPv6 literal umesto adrese pozivaoca (isprobajte u browseru).
GET /xmlapplication/xmlIsti payload kao /json, u XML formatu. Opcioni ?ip=<addr> obrađuje proizvoljan IPv4 / IPv6 literal umesto adrese pozivaoca.

Hostovi za određenu familiju #

Sam domen ifconfig.rs je dual-stack (ima i A i AAAA zapise). Da bi se transport prinudno odredio na jednu familiju, koristi subdomene specifične za familiju – iste endpoint-e, ali DNS samo jedne familije:

HostDNSŠta dobijaš
v4.ifconfig.rssamo AKonekcija ide preko IPv4; vraćeni query je tvoj IPv4.
v6.ifconfig.rssamo AAAAKonekcija ide preko IPv6; vraćeni query je tvoj IPv6.

Primeri #

Brze CLI invokacije:

$ curl ifconfig.rs
$ curl ifconfig.rs/plain
$ curl ifconfig.rs/json
$ curl v4.ifconfig.rs/plain
$ curl v6.ifconfig.rs/plain
$ curl ifconfig.rs/json?ip=1.1.1.1
$ curl ifconfig.rs/json?ip=2606:4700:4700::1111
$ curl ifconfig.rs/xml
$ curl ifconfig.rs/xml?ip=1.1.1.1

Look-up režim #

Kada je ?ip= postavljen, /json i /xml propuštaju navedenu IPv4 / IPv6 adresu kroz isti pipeline koji se koristi za sopstvenu adresu klijenta. Svaki odgovor nosi status omotač: success ako je adresa javno rutabilna, fail u suprotnom (uz message sa razlogom – invalid query, private range, reserved range, ili not in database). Originalni unos dolazi natrag kao query (odsutan kada je unos prazan ili samo razmaci).

Primer JSON odgovora (uspešno):

{
    "status": "success",
    "query": "203.0.113.42",
    "continent": "Europe",
    "continentCode": "EU",
    "country": "Serbia",
    "countryCode": "RS",
    "region": "VO",
    "regionName": "Vojvodina",
    "city": "Novi Sad",
    "zip": "21000",
    "lat": 45.2671,
    "lon": 19.8335,
    "timezone": "Europe/Belgrade",
    "offset": 7200,
    "currency": "RSD",
    "isp": "Telekom Srbija",
    "org": "Telekom Srbija a.d.",
    "as": "AS8400 TELEKOM SRBIJA a.d.",
    "asname": "TELEKOM-AS",
    "reverse": "static-203-0-113-42.telekom.rs",
    "mobile": false,
    "proxy": false,
    "hosting": false
}

Primer JSON odgovora (neuspešno – privatna adresa):

{
    "status": "fail",
    "message": "private range",
    "query": "10.0.0.1"
}

Primer XML odgovora:

<?xml version="1.0" encoding="UTF-8"?>
<Info>
    <status>success</status>
    <query>203.0.113.42</query>
    <continent>Europe</continent>
    <continentCode>EU</continentCode>
    <country>Serbia</country>
    <countryCode>RS</countryCode>
    <region>VO</region>
    <regionName>Vojvodina</regionName>
    <city>Novi Sad</city>
    <zip>21000</zip>
    <lat>45.2671</lat>
    <lon>19.8335</lon>
    <timezone>Europe/Belgrade</timezone>
    <offset>7200</offset>
    <currency>RSD</currency>
    <isp>Telekom Srbija</isp>
    <org>Telekom Srbija a.d.</org>
    <as>AS8400 TELEKOM SRBIJA a.d.</as>
    <asname>TELEKOM-AS</asname>
    <reverse>static-203-0-113-42.telekom.rs</reverse>
    <mobile>false</mobile>
    <proxy>false</proxy>
    <hosting>false</hosting>
</Info>

Struktura odgovora #

Svi /json i /xml odgovori su jedan ravan key-value objekat – sva polja na najvišem nivou, bez ugnježdenih omotača. Polja kojih nema u izlazu se jednostavno izostavljaju.

Označi polja koja te zanimaju da bi dobio odgovarajući ?fields= URL. Sa svim štikliranim – URL je goli endpoint (bez filtera); čim skineš bilo koje polje, prebacuje se na eksplicitnu listu. Prikazana su dva ekvivalentna oblika: lista imena razdvojenih zarezom i numerička bitmaska – bit svakog polja (1, 2, 4, 8, …) objavljen je na /api/fields, a integer za URL dobiješ bitovnim OR-om izabranih vrednosti. Numerički oblik je samo kraći u URL-u.

$ curl
$ curl
PoljeOpisPrimerTip
statusIshod pretrage – success kada je IP javno rutabilna, fail u suprotnom.successstring
messageRazlog kada status=fail: jedan od invalid query, private range, reserved range, not in database (validna javna adresa za koju nemamo podatke). Odsutno kada je success.private rangestring
queryEcho unosa: IP pozivaoca u client modu, vrednost ?ip= u lookup modu, adresa stavke u batch modu.203.0.113.42string
continentNaziv kontinenta.Europestring
continentCodeDvoslovni kod kontinenta.EUstring
countryNaziv države.Serbiastring
countryCodeDvoslovni kod države (ISO 3166-1 alpha-2).RSstring
regionKratki kod regije / okruga (FIPS ili ISO).VOstring
regionNamePun naziv regije / okruga.Vojvodinastring
cityNaziv grada.Novi Sadstring
districtDistrikt (deo grada). Nije dostupan za sve adrese.Limanstring
zipPoštanski broj.21000string
latGeografska širina.45.2671float
lonGeografska dužina.19.8335float
timezoneVremenska zona (tz database).Europe/Belgradestring
offsetUTC offset vremenske zone u sekundama (uključuje DST).7200int
currencyKod nacionalne valute.RSDstring
ispNaziv ISP-a.Telekom Srbijastring
orgNaziv organizacije (može se razlikovati od ISP-a).Telekom Srbija a.d.string
asAS broj i organizacija razdvojeni razmakom (RIR). Prazno za IP blokove koji nisu u BGP-u.AS8400 TELEKOM SRBIJA a.d.string
asnameNaziv AS-a (RIR).TELEKOM-ASstring
reverseReverse DNS (PTR) IP-a.static-203-0-113-42.telekom.rsstring
mobileMobilna (celularna) veza.falsebool
proxyProxy, VPN ili Tor izlazna adresa.falsebool
hostingHosting / data-centar IP.falsebool
disputedOznaka neutralnosti. Prisutno i true samo kada zemlja pripada međunarodno spornoj teritoriji (npr. Krim, Zapadna Sahara, Kosovo). Zemlja je atribucija našeg geo-provajdera, a ne stav ifconfig.rs. Inače izostaje.truebool

Nije svako polje dostupno za svaku adresu. Kada podataka nema, polje se ispušta iz odgovora – klijenti treba da tretiraju izostanak ključa kao „nepoznato", a ne kao prazan string ili nulu.

Autentifikacija (API ključevi) #

Anonimna upotreba je besplatna i bez autentifikacije. Za veće rate limite, kontaktirajte nas radi izdavanja API ključa. Kada je izdat, postoje dva ekvivalentna načina da ga pošaljete:

  • Header (preferirano): Authorization: Bearer YOUR_KEY
  • Query param: ?api_key=YOUR_KEY

Ako su prisutna oba, header ima prednost. Ključ može biti ograničen na listu izvornih IP opsega; pozivi van liste se odbijaju sa 403.

$ curl -H "Authorization: Bearer YOUR_API_KEY" ifconfig.rs/json
$ curl "ifconfig.rs/json?api_key=YOUR_API_KEY"

Rate limiting #

Dva sloja rade paralelno:

  • Per-IP – anoniman saobraćaj je ograničen na 60 zahteva po minutu po izvornoj IP.
  • Per-key – autentifikovan saobraćaj koristi sopstvene per-minute i per-day kvote ključa.

Kada je ključ predstavljen, per-key limiter preuzima taj zahtev; per-IP limit se ne broji dodatno.

Svaki odgovor pod per-IP limiterom nosi trenutni budžet u zaglavljima (X-RateLimit-* konvencija koju koriste GitHub / Twitter / Stripe):

  • X-RateLimit-Limit – plafon za prozor (uvek 60 na per-IP putanji).
  • X-RateLimit-Remaining – broj preostalih zahteva u tekućem 60-sekundnom prozoru (nula kada je prozor iscrpljen).
  • X-RateLimit-Reset – sekunde do reseta prozora i obnove budžeta.

Kada se budžet iscrpe, server vraća 429 Too Many Requests i dodaje Retry-After sa istom vrednošću sekundi do reseta. Pristojan klijent čita X-RateLimit-Remaining i prestaje da šalje kada dođe do 0, umesto da nastavi dok ne dobije 429. Zaglavlja se ne emituju na per-key putanji – autentifikovani pozivaoci prate sopstvene kvote po budžetu iz ugovora za ključ.

Batch endpoint #

POST /batch rešava do 100 adresa u jednom pozivu. Neophodan je API ključ – anonimnim pozivaocima se vraća 401 (za batch ne postoji per-IP putanja).

Telo je JSON niz stavki; svaka nosi adresu za pretragu i opcioni per-item fields filter (ista sintaksa kao ?fields= na /json). Odgovor je JSON niz iste dužine, istog redosleda, gde je svaka stavka ravan FlatInfo objekat. Mapiranje je poziciono i garantovano: i-ti rezultat je odgovor za i-tu ulaznu stavku (nikad se ne preuređuje niti deduplikuje). Svaka stavka takođe vraća svoj query, pa možete uparivati po indeksu ili po vrednosti.

Kvota se troši po broju stavki: batch od 100 protiv ključa sa 60/min vraća 429 za ceo poziv (bez delimičnog trošenja).

$ curl -X POST -H "Authorization: Bearer YOUR_API_KEY" \
       -H "Content-Type: application/json" \
       -d '[
             {"query": "8.8.8.8"},
             {"query": "1.1.1.1", "fields": "country,city,isp"},
             {"query": "10.0.0.1"}
           ]' \
       ifconfig.rs/batch
[
    { "status": "success", "query": "8.8.8.8",  "country": "United States", "city": "Mountain View", "isp": "Google LLC", ... },
    { "status": "success", "query": "1.1.1.1",  "country": "Australia",     "city": "South Brisbane", "isp": "Cloudflare, Inc." },
    { "status": "fail",    "message": "private range", "query": "10.0.0.1" }
]

HTTP status kodovi #

KodZnačenje
200Uspeh.
400 Bad RequestNepoznato ime u ?fields=, prazan ?fields=, neispravno telo za /batch, prazan batch ili batch veći od 100 stavki.
401 UnauthorizedPoslat je Authorization: Bearer header ili ?api_key=, ali ključ nije poznat / opozvan je. Takođe se vraća na /batch kada ključ uopšte nije poslat.
403 ForbiddenKljuč je važeći ali izvorna IP nije u allowlist-i.
429 Too Many RequestsPer-IP, per-minute ili per-day kvota je iscrpljena. Pokušajte ponovo nakon resetovanja prozora.
503 Service UnavailableSamo za /batch – nema konfigurisanih API ključeva na server-strani, endpoint je onemogućen.

Java klijent #

Zvanični Java klijent je objavljen na Maven Central – tanki omotač nad JDK HttpClient-om sa Jackson-om, bez ostalih HTTP zavisnosti. Zahteva JDK 21+. Izvor: github.com/adsdevdoo/ifconfig-java.

<dependency>
    <groupId>rs.adsdev</groupId>
    <artifactId>ifconfig-java</artifactId>
    <version>1.0.1</version>
</dependency>
IfconfigClient client = IfconfigClient.builder()
        .apiKey("alpha-prod-secret-xxx") // obavezno samo za /batch
        .build();

IpInfo me = client.myIp();                    // GET /json
IpInfo ip = client.lookup("8.8.8.8");         // GET /json?ip=8.8.8.8
IpInfo c  = client.lookup("8.8.8.8",          // GET /json?ip=8.8.8.8&fields=country,city
        EnumSet.of(Field.COUNTRY, Field.CITY));

List<IpInfo> hits = client.batch(List.of(     // POST /batch
        new BatchQuery("1.1.1.1"),
        new BatchQuery("8.8.8.8")));

Ne-2xx odgovori dolaze kao IfconfigException koji nosi HTTP status kod i sirovo telo, tako da pozivalac može da grana ponašanje na rate-limit (429), bad request (400), itd.

Stabilnost #

Ovde dokumentovana polja su stabilna. Možemo dodavati nova opcionalna polja bez najave; nećemo uklanjati ili preimenovati postojeća bez prethodne najave o deprecaciji na ovoj stranici.

Kontakt #

Za API ključeve, prijave zloupotreba ili pomoć sa integracijom pišite na .

← ifconfig.rs

Документация API

Как обращаться к ifconfig.rs из скриптов, сервисов и командной строки.

Обзор #

ifconfig.rs возвращает посетителю его собственный публичный IP-адрес плюс опциональные данные о геолокации и сетевом окружении. Один и тот же payload доступен в трёх форматах – text/plain, application/json, application/xml – через обычный HTTP GET.

Полное описание API в формате OpenAPI 3 – /api/openapi.json.

Endpoint'ы #

ПутьContent typeПримечания
GET /text/plain · text/htmlContent-negotiation по User-Agent. curl, wget, httpie получают plain IP; браузеры – лендинг.
GET /plaintext/plainВсегда plain text. Лучший IP (IPv4 preferred) + перенос строки.
GET /jsonapplication/jsonПолный payload. Опциональный ?ip=<addr> возвращает данные для произвольного IPv4 / IPv6 литерала вместо адреса вызывающего (попробовать в браузере).
GET /xmlapplication/xmlТот же payload, что и /json, в XML. Опциональный ?ip=<addr> возвращает данные для произвольного IPv4 / IPv6 литерала вместо адреса вызывающего.

Хосты для конкретного протокола #

По умолчанию ifconfig.rs доступен и через IPv4, и через IPv6 – в DNS есть как A, так и AAAA записи. Если нужно гарантированно соединиться по конкретному протоколу (IPv4 или IPv6), используй subdomain'ы – endpoint'ы те же, но DNS отдаёт записи только одной версии:

ХостDNSЧто получишь
v4.ifconfig.rsтолько AСоединение принудительно по IPv4; возвращаемый query – твой IPv4.
v6.ifconfig.rsтолько AAAAСоединение принудительно по IPv6; возвращаемый query – твой IPv6.

Примеры #

Быстрые CLI-вызовы:

$ curl ifconfig.rs
$ curl ifconfig.rs/plain
$ curl ifconfig.rs/json
$ curl v4.ifconfig.rs/plain
$ curl v6.ifconfig.rs/plain
$ curl ifconfig.rs/json?ip=1.1.1.1
$ curl ifconfig.rs/json?ip=2606:4700:4700::1111
$ curl ifconfig.rs/xml
$ curl ifconfig.rs/xml?ip=1.1.1.1

Look-up режим #

Если передан ?ip=, оба эндпоинта (/json и /xml) ищут геоданные для указанного IPv4 / IPv6 адреса так же, как делают это для адреса вызывающего клиента. Каждый ответ несёт служебный конверт status: success если адрес публично маршрутизируемый, fail в остальных случаях (плюс поле message с причиной – invalid query, private range, reserved range или not in database). Поданный ввод возвращается в поле query (отсутствует, если ввод был пустым или из одних пробелов).

Пример JSON-ответа (успех):

{
    "status": "success",
    "query": "203.0.113.42",
    "continent": "Europe",
    "continentCode": "EU",
    "country": "Serbia",
    "countryCode": "RS",
    "region": "VO",
    "regionName": "Vojvodina",
    "city": "Novi Sad",
    "zip": "21000",
    "lat": 45.2671,
    "lon": 19.8335,
    "timezone": "Europe/Belgrade",
    "offset": 7200,
    "currency": "RSD",
    "isp": "Telekom Srbija",
    "org": "Telekom Srbija a.d.",
    "as": "AS8400 TELEKOM SRBIJA a.d.",
    "asname": "TELEKOM-AS",
    "reverse": "static-203-0-113-42.telekom.rs",
    "mobile": false,
    "proxy": false,
    "hosting": false
}

Пример JSON-ответа (неудача – приватный адрес):

{
    "status": "fail",
    "message": "private range",
    "query": "10.0.0.1"
}

Пример XML-ответа:

<?xml version="1.0" encoding="UTF-8"?>
<Info>
    <status>success</status>
    <query>203.0.113.42</query>
    <continent>Europe</continent>
    <continentCode>EU</continentCode>
    <country>Serbia</country>
    <countryCode>RS</countryCode>
    <region>VO</region>
    <regionName>Vojvodina</regionName>
    <city>Novi Sad</city>
    <zip>21000</zip>
    <lat>45.2671</lat>
    <lon>19.8335</lon>
    <timezone>Europe/Belgrade</timezone>
    <offset>7200</offset>
    <currency>RSD</currency>
    <isp>Telekom Srbija</isp>
    <org>Telekom Srbija a.d.</org>
    <as>AS8400 TELEKOM SRBIJA a.d.</as>
    <asname>TELEKOM-AS</asname>
    <reverse>static-203-0-113-42.telekom.rs</reverse>
    <mobile>false</mobile>
    <proxy>false</proxy>
    <hosting>false</hosting>
</Info>

Структура ответа #

Ответы /json и /xml приходят одним плоским набором полей – все значения лежат рядом, без вложенных групп. Если данных для какого-то поля нет, оно просто не попадает в ответ.

Отметь нужные поля, чтобы собрать соответствующий URL с ?fields=. Если выбраны все – URL остаётся «голым» (без фильтра); снятие любой галочки переключает на явный whitelist. Показаны две эквивалентные формы: список имён через запятую и числовая битовая маска – bit-значения каждого поля (1, 2, 4, 8, …) публикуются на /api/fields, а integer для URL получается побитовым OR выбранных значений. Числовая форма просто короче в URL.

$ curl
$ curl
ПолеОписаниеПримерТип
statusРезультат поиска – success если IP публично маршрутизируемый, fail в остальных случаях.successstring
messageПричина при status=fail: одно из invalid query, private range, reserved range, not in database (валидный публичный адрес, для которого нет данных). На успехе отсутствует.private rangestring
queryЭхо ввода: IP вызывающего в client-режиме, значение ?ip= в lookup-режиме, адрес из элемента в batch-режиме.203.0.113.42string
continentНазвание континента.Europestring
continentCodeДвухбуквенный код континента.EUstring
countryНазвание страны.Serbiastring
countryCodeДвухбуквенный код страны (ISO 3166-1 alpha-2).RSstring
regionКороткий код региона / штата (FIPS или ISO).VOstring
regionNameПолное название региона / штата.Vojvodinastring
cityНазвание города.Novi Sadstring
districtРайон (часть города). Доступен не для всех адресов.Limanstring
zipПочтовый индекс.21000string
latШирота.45.2671float
lonДолгота.19.8335float
timezoneВременная зона (tz database).Europe/Belgradestring
offsetСмещение зоны от UTC в секундах (включая DST).7200int
currencyКод национальной валюты.RSDstring
ispНазвание ISP.Telekom Srbijastring
orgНазвание организации (может отличаться от ISP).Telekom Srbija a.d.string
asНомер AS и организация, разделённые пробелом (RIR). Пусто, если IP-блок не анонсируется в BGP.AS8400 TELEKOM SRBIJA a.d.string
asnameИмя AS (RIR).TELEKOM-ASstring
reverseReverse DNS (PTR) IP-а.static-203-0-113-42.telekom.rsstring
mobileМобильное (сотовое) подключение.falsebool
proxyПрокси, VPN или Tor-exit.falsebool
hostingХостинг / дата-центр IP.falsebool
disputedМаркер нейтральности. Присутствует и равно true только когда страна относится к международно спорной территории (напр. Крым, Зап. Сахара, Косово). Страна — это атрибуция нашего geo-провайдера, а не позиция ifconfig.rs. Иначе отсутствует.truebool

Не все поля доступны для каждого адреса. Если данных нет, поле просто опускается – клиенты должны трактовать отсутствие ключа как «не известно», а не как пустую строку или ноль.

Аутентификация (API-ключи) #

Анонимное использование бесплатное и без аутентификации. Для повышенных лимитов свяжитесь с нами – мы выдадим API-ключ. После выдачи есть два равнозначных способа его передавать:

  • Header (предпочтительно): Authorization: Bearer YOUR_KEY
  • Query param: ?api_key=YOUR_KEY

Если присутствуют оба – header в приоритете. Ключ может быть ограничен списком исходных IP-диапазонов; вызовы извне allowlist'а отклоняются с 403.

$ curl -H "Authorization: Bearer YOUR_API_KEY" ifconfig.rs/json
$ curl "ifconfig.rs/json?api_key=YOUR_API_KEY"

Rate limiting #

Параллельно работают два слоя:

  • Per-IP – анонимный трафик ограничен 60 запросами в минуту на исходный IP.
  • Per-key – аутентифицированный трафик использует собственные per-minute и per-day квоты ключа.

Когда ключ предъявлен, per-key лимитер забирает запрос на себя; per-IP лимит дополнительно не считается.

В каждом ответе под per-IP лимитером сервер отдаёт текущий бюджет в заголовках (конвенция X-RateLimit-*, как у GitHub / Twitter / Stripe):

  • X-RateLimit-Limit – потолок окна (на per-IP пути всегда 60).
  • X-RateLimit-Remaining – сколько запросов осталось в текущем 60-секундном окне (ноль, когда окно исчерпано).
  • X-RateLimit-Reset – секунды до сброса окна и обновления бюджета.

Когда бюджет исчерпан, сервер возвращает 429 Too Many Requests и добавляет Retry-After с тем же количеством секунд до сброса. Аккуратный клиент читает X-RateLimit-Remaining и прекращает отправлять запросы, дойдя до 0, а не ждёт первого 429. На per-key пути эти заголовки не отдаются – авторизованные клиенты сверяются с квотой, прописанной в контракте ключа.

Batch endpoint #

POST /batch резолвит до 100 адресов одним вызовом. API-ключ обязателен – запросы без ключа отклоняются с 401 (per-IP-пути для batch'а нет).

Тело – JSON-массив элементов; каждый несёт адрес для поиска и опциональный per-item фильтр fields (синтаксис тот же, что у ?fields= на /json). Ответ – JSON-массив той же длины и в том же порядке, каждый элемент – плоский объект FlatInfo. Соответствие позиционное и гарантированное: i-й результат – это ответ для i-го элемента запроса (порядок не меняется, дубликаты не схлопываются). Каждый элемент также эхает свой query, так что сопоставлять можно по индексу или по значению.

Стоимость по квоте равна числу элементов: батч на 100 при ключе с 60/min вернёт 429 для всего вызова (без частичного списания).

$ curl -X POST -H "Authorization: Bearer YOUR_API_KEY" \
       -H "Content-Type: application/json" \
       -d '[
             {"query": "8.8.8.8"},
             {"query": "1.1.1.1", "fields": "country,city,isp"},
             {"query": "10.0.0.1"}
           ]' \
       ifconfig.rs/batch
[
    { "status": "success", "query": "8.8.8.8",  "country": "United States", "city": "Mountain View", "isp": "Google LLC", ... },
    { "status": "success", "query": "1.1.1.1",  "country": "Australia",     "city": "South Brisbane", "isp": "Cloudflare, Inc." },
    { "status": "fail",    "message": "private range", "query": "10.0.0.1" }
]

HTTP-коды #

КодЗначение
200Успех.
400 Bad RequestНеизвестное имя в ?fields=, пустой ?fields=, некорректное тело для /batch, пустой batch или batch больше 100 элементов.
401 UnauthorizedПередан Authorization: Bearer или ?api_key=, но ключ неизвестен / отозван. Также возвращается на /batch, когда ключ вообще не отправлен.
403 ForbiddenКлюч валиден, но исходный IP вне его allowlist'а.
429 Too Many RequestsИсчерпана квота per-IP / per-minute / per-day. Повторите после сброса окна.
503 Service UnavailableТолько для /batch – на сервере не настроены API-ключи, эндпоинт отключён.

Java-клиент #

Официальный Java-клиент опубликован на Maven Central – тонкая обёртка над JDK HttpClient с Jackson'ом, без других HTTP-зависимостей. Требует JDK 21+. Исходники: github.com/adsdevdoo/ifconfig-java.

<dependency>
    <groupId>rs.adsdev</groupId>
    <artifactId>ifconfig-java</artifactId>
    <version>1.0.1</version>
</dependency>
IfconfigClient client = IfconfigClient.builder()
        .apiKey("alpha-prod-secret-xxx") // обязателен только для /batch
        .build();

IpInfo me = client.myIp();                    // GET /json
IpInfo ip = client.lookup("8.8.8.8");         // GET /json?ip=8.8.8.8
IpInfo c  = client.lookup("8.8.8.8",          // GET /json?ip=8.8.8.8&fields=country,city
        EnumSet.of(Field.COUNTRY, Field.CITY));

List<IpInfo> hits = client.batch(List.of(     // POST /batch
        new BatchQuery("1.1.1.1"),
        new BatchQuery("8.8.8.8")));

Ответы со статусом не 2xx превращаются в IfconfigException, который несёт HTTP-код и сырое тело – вызывающий код может ветвиться на rate-limit (429), bad request (400) и т.д.

Стабильность #

Документированные здесь поля стабильны. Новые опциональные поля можем добавлять без уведомления; не будем удалять или переименовывать существующие без предварительного уведомления о deprecation на этой странице.

Контакт #

За API-ключами, отчётами о злоупотреблениях или помощью с интеграцией пишите на .

API · Demo · Privacy Policy · Terms of Use
© 2026 by adsdev.rs. All rights reserved.