I need to somehow retrieve the client's IP address using JavaScript; no server side code, not even SSI.
However, I'm not against using a free 3rd party script/service.
ベストアンサー1
I would use a web service that can return JSON (along with jQuery to make things simpler). Below are all the active free IP lookup services I could find and the information they return. If you know of others, then please add a comment and I'll update this answer.
Abstract
let apiKey = '1be9a6884abd4c3ea143b59ca317c6b2';
$.getJSON('https://ipgeolocation.abstractapi.com/v1/?api_key=' + apiKey, function(data) {
console.log(JSON.stringify(data, null, 2));
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
Limitations:
- 10,000 requests per month
- Requires registration to get your API key
BigDataCloud
// Base
let apiKey = 'd9e53816d07345139c58d0ea733e3870';
$.getJSON('https://api.bigdatacloud.net/data/ip-geolocation?key=' + apiKey, function(data) {
console.log(JSON.stringify(data, null, 2));
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
// Base + Confidence Area
let apiKey = 'd9e53816d07345139c58d0ea733e3870';
$.getJSON('https://api.bigdatacloud.net/data/ip-geolocation-with-confidence?key=' + apiKey, function(data) {
console.log(JSON.stringify(data, null, 2));
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
// Base + Confidence Area + Hazard Report
let apiKey = 'd9e53816d07345139c58d0ea733e3870';
$.getJSON('https://api.bigdatacloud.net/data/ip-geolocation-full?key=' + apiKey, function(data) {
console.log(JSON.stringify(data, null, 2));
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
Limitations:
- 10,000 requests per month
- Requires registration to get your API key
Cloudflare
$.get('https://www.cloudflare.com/cdn-cgi/trace', function(data) {
// Convert key-value pairs to JSON
// https://stackoverflow.com/a/39284735/452587
data = data.trim().split('\n').reduce(function(obj, pair) {
pair = pair.split('=');
return obj[pair[0]] = pair[1], obj;
}, {});
console.log(data);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
Limitations:
- Returns plain text
- Returns only IPv6 address if you have that
DB-IP
Try it: https://api.db-ip.com/v2/free/self
$.getJSON('https://api.db-ip.com/v2/free/self', function(data) {
console.log(JSON.stringify(data, null, 2));
});
Returns:
{
"ipAddress": "116.12.250.1",
"continentCode": "AS",
"continentName": "Asia",
"countryCode": "SG",
"countryName": "Singapore",
"city": "Singapore (Queenstown Estate)"
}
Limitations:
- 1,000 requests per day
- Requires non-null
Origin
request header
Geobytes
Try it: http://gd.geobytes.com/GetCityDetails
$.getJSON('http://gd.geobytes.com/GetCityDetails?callback=?', function(data) {
console.log(JSON.stringify(data, null, 2));
});
Returns:
{
"geobytesforwarderfor": "",
"geobytesremoteip": "116.12.250.1",
"geobytesipaddress": "116.12.250.1",
"geobytescertainty": "99",
"geobytesinternet": "SA",
"geobytescountry": "Saudi Arabia",
"geobytesregionlocationcode": "SASH",
"geobytesregion": "Ash Sharqiyah",
"geobytescode": "SH",
"geobyteslocationcode": "SASHJUBA",
"geobytescity": "Jubail",
"geobytescityid": "13793",
"geobytesfqcn": "Jubail, SH, Saudi Arabia",
"geobyteslatitude": "27.004999",
"geobyteslongitude": "49.660999",
"geobytescapital": "Riyadh ",
"geobytestimezone": "+03:00",
"geobytesnationalitysingular": "Saudi Arabian ",
"geobytespopulation": "22757092",
"geobytesnationalityplural": "Saudis",
"geobytesmapreference": "Middle East ",
"geobytescurrency": "Saudi Riyal",
"geobytescurrencycode": "SAR",
"geobytestitle": "Saudi Arabia"
}
Limitations:
- 16,384 requests per hour
- No SSL (https) with the free plan
- Can return the wrong location
GeoIPLookup.io
$.getJSON('https://json.geoiplookup.io/?callback=?', function(data) {
console.log(JSON.stringify(data, null, 2));
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
Limitations:
- 10,000 requests per hour
- Free plan only for non-commercial use
- Returns only IPv6 address if you have that
geoPlugin
Try it: http://www.geoplugin.net/json.gp
$.getJSON('http://www.geoplugin.net/json.gp', function(data) {
console.log(JSON.stringify(data, null, 2));
});
Returns:
{
"geoplugin_request": "116.12.250.1",
"geoplugin_status": 200,
"geoplugin_credit": "Some of the returned data includes GeoLite data created by MaxMind, available from <a href=\\'http://www.maxmind.com\\'>http://www.maxmind.com</a>.",
"geoplugin_city": "Singapore",
"geoplugin_region": "Singapore (general)",
"geoplugin_areaCode": "0",
"geoplugin_dmaCode": "0",
"geoplugin_countryCode": "SG",
"geoplugin_countryName": "Singapore",
"geoplugin_continentCode": "AS",
"geoplugin_latitude": "1.2931",
"geoplugin_longitude": "103.855797",
"geoplugin_regionCode": "00",
"geoplugin_regionName": "Singapore (general)",
"geoplugin_currencyCode": "SGD",
"geoplugin_currencySymbol": "$",
"geoplugin_currencySymbol_UTF8": "$",
"geoplugin_currencyConverter": 1.4239
}
Limitations:
- 120 requests per minute
- No SSL (https) with the free plan
Hacker Target
$.get('https://api.hackertarget.com/geoip/?q=116.12.250.1', function(data) {
// Convert key-value pairs to JSON
// https://stackoverflow.com/a/39284735/452587
data = data.trim().split('\n').reduce(function(obj, pair) {
pair = pair.split(': ');
return obj[pair[0]] = pair[1], obj;
}, {});
console.log(data);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
Limitations:
- 100 requests per day
- Requires IP address parameter
- Returns plain text
ipapi
Try it: https://ipapi.co/json/
$.getJSON('https://ipapi.co/json/', function(data) {
console.log(JSON.stringify(data, null, 2));
});
Returns:
{
"ip": "116.12.250.1",
"city": "Singapore",
"region": "Central Singapore Community Development Council",
"country": "SG",
"country_name": "Singapore",
"postal": null,
"latitude": 1.2855,
"longitude": 103.8565,
"timezone": "Asia/Singapore"
}
Limitations:
- 1,000 requests per day
- Requires SSL (https)
- Requires non-null
Origin
request header - Returns only IPv6 address if you have that
IP-API
Try it: http://ip-api.com/json
$.getJSON('http://ip-api.com/json', function(data) {
console.log(JSON.stringify(data, null, 2));
});
Returns:
{
"as": "AS3758 SingNet",
"city": "Singapore",
"country": "Singapore",
"countryCode": "SG",
"isp": "SingNet Pte Ltd",
"lat": 1.2931,
"lon": 103.8558,
"org": "Singapore Telecommunications",
"query": "116.12.250.1",
"region": "01",
"regionName": "Central Singapore Community Development Council",
"status": "success",
"timezone": "Asia/Singapore",
"zip": ""
}
Limitations:
- 150 requests per minute
- No SSL (https) with the free plan
ipdata
let apiKey = 'be0f755b93290b4c100445d77533d291763a417c75524e95e07819ad';
$.getJSON('https://api.ipdata.co?api-key=' + apiKey, function(data) {
console.log(JSON.stringify(data, null, 2));
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
Limitations:
- 1,500 requests per day
- Requires registration to get your API key
- Requires SSL (https)
IP Find
let apiKey = '50e887ce-e3bb-4f00-a9b9-667597db5539';
$.getJSON('https://ipfind.co/me?auth=' + apiKey, function(data) {
console.log(JSON.stringify(data, null, 2));
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
Limitations:
- 300 requests per day
- Requires registration to get your API key
ipgeolocation
let apiKey = 'f8e0b361e8f4405c94613ab534959fdf';
$.getJSON('https://api.ipgeolocation.io/ipgeo?apiKey=' + apiKey, function(data) {
console.log(JSON.stringify(data, null, 2));
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
Limitations:
- 50,000 requests per month
- Requires registration to get your API key
- Returns only IPv6 address if you have that
ipify
$.getJSON('https://api.ipify.org?format=jsonp&callback=?', function(data) {
console.log(JSON.stringify(data, null, 2));
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
Limitations:
- None
IPInfoDB
let apiKey = '25864308b6a77fd90f8bf04b3021a48c1f2fb302a676dd3809054bc1b07f5b42';
$.getJSON('https://api.ipinfodb.com/v3/ip-city/?format=json&key=' + apiKey, function(data) {
console.log(JSON.stringify(data, null, 2));
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
Limitations:
- Two requests per second
- Requires registration to get your API key
ipinfo.io
$.getJSON('https://ipinfo.io/json', function(data) {
console.log(JSON.stringify(data, null, 2));
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
Limitations:
- 50,000 requests per month
ipregistry
$.getJSON('https://api.ipregistry.co/?key=tryout', function(data) {
console.log(JSON.stringify(data, null, 2));
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
Limitations:
- Free plan includes 100,000 requests
- Requires registration to get your API key
- Returns only IPv6 address if you have that
ipstack (formerly freegeoip.net)
Try it: http://api.ipstack.com/<ip_address>?access_key=<your_api_key>
$.getJSON('http://api.ipstack.com/<ip_address>?access_key=<your_api_key>', function(data) {
console.log(JSON.stringify(data, null, 2));
});
Returns:
{
"ip": "116.12.250.1",
"type": "ipv4",
"continent_code": "AS",
"continent_name": "Asia",
"country_code": "SG",
"country_name": "Singapore",
"region_code": "01",
"region_name": "Central Singapore Community Development Council",
"city": "Singapore",
"zip": null,
"latitude": 1.2931,
"longitude": 103.8558,
"location": {
"geoname_id": 1880252,
"capital": "Singapore",
"languages": [
{
"code": "en",
"name": "English",
"native": "English"
},
{
"code": "ms",
"name": "Malay",
"native": "Bahasa Melayu"
},
{
"code": "ta",
"name": "Tamil",
"native": "தமிழ்"
},
{
"code": "zh",
"name": "Chinese",
"native": "中文"
}
],
"country_flag": "http://assets.ipstack.com/flags/sg.svg",
"country_flag_emoji": "����",
"country_flag_emoji_unicode": "U+1F1F8 U+1F1EC",
"calling_code": "65",
"is_eu": false
}
}
Limitations:
- 10,000 requests per month
- Requires IP address parameter
- Requires registration to get your API key
- No SSL (https) with the free plan
jsonip.com
$.getJSON('https://jsonip.com/', function(data) {
console.log(JSON.stringify(data, null, 2));
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
Limitations:
- Returns only IPv6 address if you have that
JSON Test
Try it: http://ip.jsontest.com/
$.getJSON('http://ip.jsontest.com/', function(data) {
console.log(JSON.stringify(data, null, 2));
});
Returns:
{
"ip": "116.12.250.1"
}
Limitations:
- No SSL (https)
- Returns only IPv6 address if you have that
Snoopi.io
let apiKey = 'ed5ebbeba257b8f262a6a9bbc0ec678e';
$.getJSON('https://api.snoopi.io/116.12.250.1?apikey=' + apiKey, function(data) {
console.log(JSON.stringify(data, null, 2));
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
Limitations:
- 10,000 requests per month
- 1 request every 2 seconds
- Requires IP address parameter
- Requires registration to get your API key
VANILLA JAVASCRIPT
With modern browsers, you can use the native Fetch API instead of relying on jQuery's $.getJSON()
. Here's an example:
let apiKey = '1be9a6884abd4c3ea143b59ca317c6b2';
// Make the request
fetch('https://ipgeolocation.abstractapi.com/v1/?api_key=' + apiKey)
// Extract JSON body content from HTTP response
.then(response => response.json())
// Do something with the JSON data
.then(data => {
console.log(JSON.stringify(data, null, 2))
});
NOTES
- Since these are all free services, who knows when/if they will be taken offline down the road (exhibit A: Telize).
- Most of these services also offer a paid tier in case you want more features and stability.
- As @skobaljic noted in the comments below, the request quotas are mostly academic since calls are happening client-side and most end users will never exceed their quota.
- 一部のサービスでは、無料プランで SSL 接続が許可されていないか、null 以外のリクエスト ヘッダーが必要なため、実行可能なスニペットがありません
Origin
(StackOverflow スニペットは https の使用が強制され、Origin: null
リクエスト ヘッダーに が含まれます)。
アップデート
- 2016年2月1日: 削除テリゼ(無料プランは提供されなくなりました)
- 2016年4月18日: 削除フリージオIP(故障中)
- 2016年4月26日: 追加DB-IP
- 2016年4月26日: 追加ハッカーのターゲット
- 2016年7月6日: 復活フリージオIP
- 2016年7月6日: 削除ip-json.rhcloud.com(リンク切れ)
- 2016年12月21日: 削除ハッカーのターゲット(故障中)
- 2017年2月10日: 追加ネクド
- 2017年4月20日: 追加イパピ(Ahmad Awaisに感謝)
- 2017年4月24日: 復活ハッカーのターゲット
- 2017年4月24日: 削除スヌーピー(故障中)
- 2017/7/16: 「無料プランでは SSL (https) は使用できません」という制限を追加しました
- 2017年7月16日: 追加IP検索(JordanCさんありがとう)
- 2017年9月25日: 追加愚かなウェブツール(ありがとう、Cœur)
- 2018年3月16日: 追加ipdata(ありがとう、ジョナサン)
- 2018年4月14日: freegeoip.netの名前をipstack(MA-Maddinに感謝)
- 2018年4月16日: 追加ジオIPルックアップ(Rob Waaに感謝)
- 2018年6月11日: 追加ipgeolocation(Ejaz Ahmedに感謝)
- 2019年7月31日: 追加ipレジストリ(ローランありがとう)
- 2019年8月16日: 追加スマートIP.io(ありがとう、ケビン)
- 2019年8月22日: 削除愚かなウェブツール(故障中)
- 2019年12月10日: 追加クラウドフレア
- 2020年1月9日: 削除スマートIP.io(故障中)
- 2020年11月6日: 追加抽象的な
- 2020年11月13日: 追加アストロIP
- 2021 年 4 月 13 日: コードサンプルをスニペットに置き換えました (30,000 文字の制限に近づいていました)
- 2021年4月13日: プレーンテキスト応答用にキーと値のペアをJSONに変換するコードを追加しました
- 2021 年 4 月 13 日: 「null 以外の
Origin
リクエスト ヘッダーが必要」という制限を追加しました - 2021年4月13日: 追加ビッグデータクラウド
- 2021年4月13日: 復活スヌーピー
- 2021年4月13日: 削除アストロIP(故障中)
- 2021年4月13日: 削除ネクド(現在はipapiの一部)