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>
Run code snippetExpand snippet
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>
Run code snippetExpand snippet
// 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>
Run code snippetExpand snippet
// 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>
Run code snippetExpand snippet
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>
Run code snippetExpand snippet
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>
Run code snippetExpand snippet
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>
Run code snippetExpand snippet
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>
Run code snippetExpand snippet
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>
Run code snippetExpand snippet
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>
Run code snippetExpand snippet
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>
Run code snippetExpand snippet
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>
Run code snippetExpand snippet
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>
Run code snippetExpand snippet
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>
Run code snippetExpand snippet
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>
Run code snippetExpand snippet
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>
Run code snippetExpand snippet
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)) });
Run code snippetExpand snippet
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.
- Some services don’t have runnable snippets because they don’t allow SSL connections in the free plan or require a non-null
Origin
request header (StackOverflow snippets are forced to use https and haveOrigin: null
in the request headers).
UPDATES
- 2/1/2016: Removed Telize (no longer offers free plan)
- 4/18/2016: Removed freegeoip.net (out of service)
- 4/26/2016: Added DB-IP
- 4/26/2016: Added Hacker Target
- 7/6/2016: Reinstated freegeoip.net
- 7/6/2016: Removed ip-json.rhcloud.com (dead link)
- 12/21/2016: Removed Hacker Target (out of service)
- 2/10/2017: Added Nekudo
- 4/20/2017: Added ipapi (thanks Ahmad Awais)
- 4/24/2017: Reinstated Hacker Target
- 4/24/2017: Removed Snoopi.io (out of service)
- 7/16/2017: Added limitation “No SSL (https) with the free plan”
- 7/16/2017: Added IP Find (thanks JordanC)
- 9/25/2017: Added Stupid Web Tools (thanks Cœur)
- 3/16/2018: Added ipdata (thanks Jonathan)
- 4/14/2018: Renamed freegeoip.net to ipstack (thanks MA-Maddin)
- 4/16/2018: Added GeoIPLookup.io (thanks Rob Waa)
- 6/11/2018: Added ipgeolocation (thanks Ejaz Ahmed)
- 7/31/2019: Added ipregistry (thanks Laurent)
- 8/16/2019: Added SmartIP.io (thanks kevinj)
- 8/22/2019: Removed Stupid Web Tools (out of service)
- 12/10/2019: Added Cloudflare
- 1/9/2020: Removed SmartIP.io (out of service)
- 11/6/2020: Added Abstract
- 11/13/2020: Added AstroIP.co
- 4/13/2021: Replaced code samples with snippets (was getting close to 30k character limit)
- 4/13/2021: Added code to convert key-value pairs to JSON for plain text responses
- 4/13/2021: Added limitation “Requires non-null
Origin
request header” - 4/13/2021: Added BigDataCloud
- 4/13/2021: Reinstated Snoopi.io
- 4/13/2021: Removed AstroIP.co (out of service)
- 4/13/2021: Removed Nekudo (now part of ipapi)