Quickstart#

Dependencies#

This module requires API key to function. You may sign up for a free API key at https://www.ip2location.io/pricing.

Compilation#

cabal install ip2location-io

Sample Codes#

Lookup IP Address Geolocation Data#

You can make a geolocation data lookup for an IP address as below:

import Configuration
import qualified IPGeolocation as IPG
import qualified IPGeolocation as IPAS (ASInfo(..))
import qualified IPGeolocation as IPConti (Continent(..))
import qualified IPGeolocation as IPCntry (Country(..))
import qualified IPGeolocation as IPCurr (Currency(..))
import qualified IPGeolocation as IPLng (Language(..))
import qualified IPGeolocation as IPRgn (Region(..))
import qualified IPGeolocation as IPCty (City(..))

main :: IO ()
main = do
    let apikey = "YOUR_API_KEY"
    let ipadd = "8.8.8.8"
    let language = "" -- language param only supported in Plus and Security plans, put blank if not needed
    config <- open apikey
    result <- IPG.lookUpIP config ipadd language

    case result of
        IPG.IPError err -> putStrLn $ "ERROR: " ++ IPG.error_message (IPG.error err)
        IPG.IPResponse response -> do
            putStrLn $ "ip: " ++ IPG.ip response
            putStrLn $ "country_code: " ++ IPG.country_code response
            putStrLn $ "country_name: " ++ IPG.country_name response
            putStrLn $ "region_name: " ++ IPG.region_name response
            putStrLn $ "city_name: " ++ IPG.city_name response
            putStrLn $ "latitude: " ++ show (IPG.latitude response)
            putStrLn $ "longitude: " ++ show (IPG.longitude response)
            putStrLn $ "zip_code: " ++ IPG.zip_code response
            putStrLn $ "time_zone: " ++ IPG.time_zone response
            putStrLn $ "asn: " ++ IPG.asn response
            putStrLn $ "as: " ++ IPG.as response
            case IPG.as_info response of
                Nothing -> pure ()
                Just asi -> do
                    putStrLn $ "as_info => as_number: " ++ IPAS.as_number asi
                    putStrLn $ "as_info => as_name: " ++ IPAS.as_name asi
                    putStrLn $ "as_info => as_domain: " ++ IPAS.as_domain asi
                    putStrLn $ "as_info => as_usage_type: " ++ IPAS.as_usage_type asi
                    putStrLn $ "as_info => as_cidr: " ++ IPAS.as_cidr asi
            putStrLn $ "isp: " ++ maybe "NOT_SUPPORTED" id (IPG.isp response)
            putStrLn $ "domain: " ++ maybe "NOT_SUPPORTED" id (IPG.domain response)
            putStrLn $ "net_speed: " ++ maybe "NOT_SUPPORTED" id (IPG.net_speed response)
            putStrLn $ "idd_code: " ++ maybe "NOT_SUPPORTED" id (IPG.idd_code response)
            putStrLn $ "area_code: " ++ maybe "NOT_SUPPORTED" id (IPG.area_code response)
            putStrLn $ "weather_station_code: " ++ maybe "NOT_SUPPORTED" id (IPG.weather_station_code response)
            putStrLn $ "weather_station_name: " ++ maybe "NOT_SUPPORTED" id (IPG.weather_station_name response)
            putStrLn $ "mcc: " ++ maybe "NOT_SUPPORTED" id (IPG.mcc response)
            putStrLn $ "mnc: " ++ maybe "NOT_SUPPORTED" id (IPG.mnc response)
            putStrLn $ "mobile_brand: " ++ maybe "NOT_SUPPORTED" id (IPG.mobile_brand response)
            putStrLn $ "elevation: " ++ maybe "NOT_SUPPORTED" (show) (IPG.elevation response)
            putStrLn $ "usage_type: " ++ maybe "NOT_SUPPORTED" id (IPG.usage_type response)
            putStrLn $ "address_type: " ++ maybe "NOT_SUPPORTED" id (IPG.address_type response)
            putStrLn $ "ads_category: " ++ maybe "NOT_SUPPORTED" id (IPG.ads_category response)
            putStrLn $ "ads_category_name: " ++ maybe "NOT_SUPPORTED" id (IPG.ads_category_name response)
            putStrLn $ "district: " ++ maybe "NOT_SUPPORTED" id (IPG.district response)
            putStrLn $ "is_proxy: " ++ show (IPG.is_proxy response)
            putStrLn $ "fraud_score: " ++ maybe "NOT_SUPPORTED" (show) (IPG.fraud_score response)
            case IPG.continent response of
                Nothing -> pure ()
                Just conti -> do
                    putStrLn $ "continent => name: " ++ IPConti.name conti
                    putStrLn $ "continent => code: " ++ IPConti.code conti
                    putStrLn $ "continent => hemispshere: " ++ (show) (IPConti.hemisphere conti)
                    let tran = IPConti.translation conti
                    putStrLn $ "continent => translation => lang: " ++ maybe "NOT_SUPPORTED" id (IPG.lang tran)
                    putStrLn $ "continent => translation => value: " ++ maybe "NOT_SUPPORTED" id (IPG.value tran)
            case IPG.country response of
                Nothing -> pure ()
                Just cntry -> do
                    putStrLn $ "country => name: " ++ IPCntry.name cntry
                    putStrLn $ "country => alpha3_code: " ++ IPCntry.alpha3_code cntry
                    putStrLn $ "country => numeric_code: " ++ show (IPCntry.numeric_code cntry)
                    putStrLn $ "country => demonym: " ++ IPCntry.demonym cntry
                    putStrLn $ "country => flag: " ++ IPCntry.flag cntry
                    putStrLn $ "country => capital: " ++ IPCntry.capital cntry
                    putStrLn $ "country => total_area: " ++ show (IPCntry.total_area cntry)
                    putStrLn $ "country => population: " ++ show (IPCntry.population cntry)
                    putStrLn $ "country => tld: " ++ IPCntry.tld cntry
                    let curr = IPCntry.currency cntry
                    putStrLn $ "country => currency => code: " ++ IPCurr.code curr
                    putStrLn $ "country => currency => name: " ++ IPCurr.name curr
                    putStrLn $ "country => currency => symbol: " ++ IPCurr.symbol curr
                    let lng = IPCntry.language cntry
                    putStrLn $ "country => language => code: " ++ IPLng.code lng
                    putStrLn $ "country => language => name: " ++ IPLng.name lng
                    let tran = IPCntry.translation cntry
                    putStrLn $ "country => translation => lang: " ++ maybe "NOT_SUPPORTED" id (IPG.lang tran)
                    putStrLn $ "country => translation => value: " ++ maybe "NOT_SUPPORTED" id (IPG.value tran)
            case IPG.region response of
                Nothing -> pure ()
                Just rgn -> do
                    putStrLn $ "region => name: " ++ IPRgn.name rgn
                    putStrLn $ "region => code: " ++ IPRgn.code rgn
                    let tran = IPRgn.translation rgn
                    putStrLn $ "region => translation => lang: " ++ maybe "NOT_SUPPORTED" id (IPG.lang tran)
                    putStrLn $ "region => translation => value: " ++ maybe "NOT_SUPPORTED" id (IPG.value tran)
            case IPG.city response of
                Nothing -> pure ()
                Just cty -> do
                    putStrLn $ "city => name: " ++ IPCty.name cty
                    let tran = IPCty.translation cty
                    putStrLn $ "city => translation => lang: " ++ maybe "NOT_SUPPORTED" id (IPG.lang tran)
                    putStrLn $ "city => translation => value: " ++ maybe "NOT_SUPPORTED" id (IPG.value tran)
            case IPG.time_zone_info response of
                Nothing -> pure ()
                Just tzi -> do
                    putStrLn $ "time_zone_info => olson: " ++ IPG.olson tzi
                    putStrLn $ "time_zone_info => current_time: " ++ IPG.current_time tzi
                    putStrLn $ "time_zone_info => gmt_offset: " ++ show (IPG.gmt_offset tzi)
                    putStrLn $ "time_zone_info => is_dst: " ++ show (IPG.is_dst tzi)
                    putStrLn $ "time_zone_info => abbreviation: " ++ IPG.abbreviation tzi
                    putStrLn $ "time_zone_info => dst_start_date: " ++ IPG.dst_start_date tzi
                    putStrLn $ "time_zone_info => dst_end_date: " ++ IPG.dst_end_date tzi
                    putStrLn $ "time_zone_info => sunrise: " ++ IPG.sunrise tzi
                    putStrLn $ "time_zone_info => sunset: " ++ IPG.sunset tzi
            case IPG.geotargeting response of
                Nothing -> pure ()
                Just gtg -> do
                    putStrLn $ "geotargeting => metro: " ++ maybe "NOT_SUPPORTED" id (IPG.metro gtg)
            case IPG.proxy response of
                Nothing -> pure ()
                Just prx -> do
                    putStrLn $ "proxy => last_seen: " ++ show (IPG.last_seen prx)
                    putStrLn $ "proxy => proxy_type: " ++ IPG.proxy_type prx
                    putStrLn $ "proxy => threat: " ++ IPG.threat prx
                    putStrLn $ "proxy => provider: " ++ IPG.provider prx
                    putStrLn $ "proxy => is_vpn: " ++ show (IPG.is_vpn prx)
                    putStrLn $ "proxy => is_tor: " ++ show (IPG.is_tor prx)
                    putStrLn $ "proxy => is_data_center: " ++ show (IPG.is_data_center prx)
                    putStrLn $ "proxy => is_public_proxy: " ++ show (IPG.is_public_proxy prx)
                    putStrLn $ "proxy => is_web_proxy: " ++ show (IPG.is_web_proxy prx)
                    putStrLn $ "proxy => is_web_crawler: " ++ show (IPG.is_web_crawler prx)
                    putStrLn $ "proxy => is_ai_crawler: " ++ show (IPG.is_ai_crawler prx)
                    putStrLn $ "proxy => is_residential_proxy: " ++ show (IPG.is_residential_proxy prx)
                    putStrLn $ "proxy => is_consumer_privacy_network: " ++ show (IPG.is_consumer_privacy_network prx)
                    putStrLn $ "proxy => is_enterprise_private_network: " ++ show (IPG.is_enterprise_private_network prx)
                    putStrLn $ "proxy => is_spammer: " ++ show (IPG.is_spammer prx)
                    putStrLn $ "proxy => is_scanner: " ++ show (IPG.is_scanner prx)
                    putStrLn $ "proxy => is_botnet: " ++ show (IPG.is_botnet prx)
                    putStrLn $ "proxy => is_bogon: " ++ show (IPG.is_bogon prx)

Lookup Domain Information#

You can lookup domain information as below:

import Configuration
import qualified DomainWhois as DW
import qualified DomainWhois as Regist (Registrar(..))
import qualified DomainWhois as Contac (Contact(..))

main :: IO ()
main = do
    let apikey = "YOUR_API_KEY"
    let mydomain = "locaproxy.com"
    config <- open apikey
    result <- DW.lookUpDomain config mydomain

    case result of
        DW.WhoisError err -> putStrLn $ "ERROR: " ++ DW.error_message (DW.error err)
        DW.WhoisResponse response -> do
            putStrLn $ "domain: " ++ DW.domain response
            putStrLn $ "domain_id: " ++ DW.domain_id response
            putStrLn $ "status: " ++ DW.status response
            putStrLn $ "create_date: " ++ DW.create_date response
            putStrLn $ "update_date: " ++ DW.update_date response
            putStrLn $ "expire_date: " ++ DW.expire_date response
            putStrLn $ "domain_age: " ++ show (DW.domain_age response)
            putStrLn $ "whois_server: " ++ DW.whois_server response

            let registrarObj = DW.registrar response
            putStrLn $ "registrar => iana_id: " ++ Regist.iana_id registrarObj
            putStrLn $ "registrar => name: " ++ Regist.name registrarObj
            putStrLn $ "registrar => url: " ++ Regist.url registrarObj

            let registrantObj = DW.registrant response
            putStrLn $ "registrant => name: " ++ Contac.name registrantObj
            putStrLn $ "registrant => organization: " ++ Contac.organization registrantObj
            putStrLn $ "registrant => street_address: " ++ Contac.street_address registrantObj
            putStrLn $ "registrant => city: " ++ Contac.city registrantObj
            putStrLn $ "registrant => region: " ++ Contac.region registrantObj
            putStrLn $ "registrant => zip_code: " ++ Contac.zip_code registrantObj
            putStrLn $ "registrant => country: " ++ Contac.country registrantObj
            putStrLn $ "registrant => phone: " ++ Contac.phone registrantObj
            putStrLn $ "registrant => fax: " ++ Contac.fax registrantObj
            putStrLn $ "registrant => email: " ++ Contac.email registrantObj

            let adminObj = DW.admin response
            putStrLn $ "admin => name: " ++ Contac.name adminObj
            putStrLn $ "admin => organization: " ++ Contac.organization adminObj
            putStrLn $ "admin => street_address: " ++ Contac.street_address adminObj
            putStrLn $ "admin => city: " ++ Contac.city adminObj
            putStrLn $ "admin => region: " ++ Contac.region adminObj
            putStrLn $ "admin => zip_code: " ++ Contac.zip_code adminObj
            putStrLn $ "admin => country: " ++ Contac.country adminObj
            putStrLn $ "admin => phone: " ++ Contac.phone adminObj
            putStrLn $ "admin => fax: " ++ Contac.fax adminObj
            putStrLn $ "admin => email: " ++ Contac.email adminObj

            let techObj = DW.tech response
            putStrLn $ "tech => name: " ++ Contac.name techObj
            putStrLn $ "tech => organization: " ++ Contac.organization techObj
            putStrLn $ "tech => street_address: " ++ Contac.street_address techObj
            putStrLn $ "tech => city: " ++ Contac.city techObj
            putStrLn $ "tech => region: " ++ Contac.region techObj
            putStrLn $ "tech => zip_code: " ++ Contac.zip_code techObj
            putStrLn $ "tech => country: " ++ Contac.country techObj
            putStrLn $ "tech => phone: " ++ Contac.phone techObj
            putStrLn $ "tech => fax: " ++ Contac.fax techObj
            putStrLn $ "tech => email: " ++ Contac.email techObj

            let billingObj = DW.billing response
            putStrLn $ "billing => name: " ++ Contac.name billingObj
            putStrLn $ "billing => organization: " ++ Contac.organization billingObj
            putStrLn $ "billing => street_address: " ++ Contac.street_address billingObj
            putStrLn $ "billing => city: " ++ Contac.city billingObj
            putStrLn $ "billing => region: " ++ Contac.region billingObj
            putStrLn $ "billing => zip_code: " ++ Contac.zip_code billingObj
            putStrLn $ "billing => country: " ++ Contac.country billingObj
            putStrLn $ "billing => phone: " ++ Contac.phone billingObj
            putStrLn $ "billing => fax: " ++ Contac.fax billingObj
            putStrLn $ "billing => email: " ++ Contac.email billingObj

            putStrLn $ "nameservers: " ++ (show) (DW.nameservers response)

Get Domain Name#

You can extract the domain name from an url as below:

import qualified DomainWhois as DW

main :: IO ()
main = do
    let domainName = DW.getDomainName "https://www.example.com/exe"
    putStrLn $ "domainName: " ++ domainName

Get Domain Extension#

You can extract the domain extension from a domain name or url as below:

import qualified DomainWhois as DW

main :: IO ()
main = do
    let domainExtension = DW.getDomainExtension "example.com"
    putStrLn $ "domainExtension: " ++ domainExtension

Lookup IP Address Hosted Domains Data#

You can lookup hosted domains information as below:

import Configuration
import qualified HostedDomain as HD

main :: IO ()
main = do
    let apikey = "YOUR_API_KEY"
    let ipadd = "8.8.8.8"
    let page = 1
    config <- open apikey
    result <- HD.lookUpHosted config ipadd page

    case result of
        HD.HostedError err -> putStrLn $ "ERROR: " ++ HD.error_message (HD.error err)
        HD.HostedResponse response -> do
            putStrLn $ "ip: " ++ HD.ip response
            putStrLn $ "total_domains: " ++ (show) (HD.total_domains response)
            putStrLn $ "page: " ++ (show) (HD.page response)
            putStrLn $ "per_page: " ++ (show) (HD.per_page response)
            putStrLn $ "total_pages: " ++ (show) (HD.total_pages response)
            putStrLn $ "domains: " ++ (show) (HD.domains response)