├── .editorconfig ├── .npmrc ├── .travis.yml ├── LICENSE ├── README.md ├── package.json ├── source └── index.ts ├── test.ts └── tsconfig.json /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | indent_style = tab 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | package-lock=false 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | 3 | node_js: 4 | - "12" 5 | - "10" 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 - 2019 Rory Bradford , 2020 Richie Bendall and contributors. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is furnished 10 | to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # iplocation [![Travis CI Build Status](https://img.shields.io/travis/com/Richienb/iplocation/master.svg?style=for-the-badge)](https://travis-ci.com/Richienb/iplocation) 2 | 3 | Get ip location information. 4 | 5 | [![NPM Badge](https://nodei.co/npm/iplocation.png)](https://npmjs.com/package/iplocation) 6 | 7 | ## Install 8 | 9 | ```sh 10 | npm install iplocation 11 | ``` 12 | 13 | ## Usage 14 | 15 | ```js 16 | const ipLocation = require("iplocation"); 17 | 18 | (async () => { 19 | await ipLocation("172.217.167.78"); 20 | //=> { latitude: -33.8591, longitude: 151.2002, region: { name: "New South Wales" ... } ... } 21 | })(); 22 | ``` 23 | 24 | ## API 25 | 26 | ### ipLocation(ip, options?) 27 | 28 | #### ip 29 | 30 | Type: `string` 31 | 32 | The ipv4 address to get the information for. 33 | 34 | #### options 35 | 36 | Type: `object` 37 | 38 | #### apiKey 39 | 40 | Type: `string` 41 | 42 | An optional [ipapi](https://ipapi.co/) API key to use. 43 | 44 | ```js 45 | const ipLocation = require("iplocation"); 46 | 47 | (async () => { 48 | await ipLocation("172.217.167.78", { apiKey: 'YOUR_API_KEY' }); 49 | //=> { latitude: -33.8591, longitude: 151.2002, region: { name: "New South Wales" ... } ... } 50 | })(); 51 | ``` 52 | 53 | ## Providers 54 | 55 | iplocation currently uses [ipapi](https://ipapi.co/) for IP lookups. Their free API is limited to 1000 requests per day. 56 | 57 | ## Related 58 | 59 | - [iplocation-cli](https://github.com/Richienb/iplocation-cli) - CLI for this module. 60 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "iplocation", 3 | "version": "7.2.0", 4 | "description": "Get ip location information.", 5 | "repository": "https://github.com/Richienb/iplocation.git", 6 | "author": "Richie Bendall ", 7 | "contributors": [ 8 | "Rory Bradford (https://roryrjb.com)", 9 | "Chris Dyson", 10 | "Ahmed Tarek", 11 | "Jacques L. Chereau" 12 | ], 13 | "license": "MIT", 14 | "main": "dist/index.js", 15 | "files": [ 16 | "dist" 17 | ], 18 | "engines": { 19 | "node": ">=10" 20 | }, 21 | "scripts": { 22 | "build": "tsc", 23 | "lint": "xo", 24 | "test": "xo && ava", 25 | "prepublishOnly": "tsc" 26 | }, 27 | "keywords": [ 28 | "ip", 29 | "location", 30 | "coordinates", 31 | "locate", 32 | "find", 33 | "address", 34 | "ip-location", 35 | "geolocation" 36 | ], 37 | "dependencies": { 38 | "is-ip": "^3.1.0", 39 | "ky": "^0.19.1", 40 | "ky-universal": "^0.6.0" 41 | }, 42 | "devDependencies": { 43 | "@richienb/tsconfig": "^0.1.1", 44 | "@types/node": "^13.13.4", 45 | "ava": "^3.8.1", 46 | "eslint-config-richienb": "^0.4.2", 47 | "ts-node": "^8.9.1", 48 | "typescript": "^3.8.3", 49 | "xo": "^0.30.0" 50 | }, 51 | "resolutions": { 52 | "eslint": "^6.8.0" 53 | }, 54 | "xo": { 55 | "extends": "richienb/typescript", 56 | "overrides": [ 57 | { 58 | "files": "test.ts", 59 | "rules": { 60 | "node/no-missing-import": 0 61 | } 62 | } 63 | ] 64 | }, 65 | "ava": { 66 | "extensions": [ 67 | "ts" 68 | ], 69 | "require": [ 70 | "ts-node/register" 71 | ] 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /source/index.ts: -------------------------------------------------------------------------------- 1 | import ky from "ky-universal" 2 | import isIp from "is-ip" 3 | 4 | interface IpApiData { 5 | ip: string 6 | city: string 7 | reserved: boolean 8 | region: string 9 | region_code: string 10 | country: string 11 | country_code: string 12 | country_code_iso3: string 13 | country_capital: string 14 | country_tld: string 15 | country_name: string 16 | continent_code: string 17 | in_eu: boolean 18 | postal: string 19 | latitude: number 20 | longitude: number 21 | timezone: string 22 | utc_offset: string 23 | country_calling_code: string 24 | currency: string 25 | currency_name: string 26 | languages: string 27 | country_area: number 28 | country_population: number 29 | } 30 | 31 | declare namespace ipLocation { 32 | export interface LocationData { 33 | latitude: number 34 | longitude: number 35 | city: string 36 | region: { 37 | name: string 38 | code: string 39 | } 40 | country: { 41 | name: string 42 | code: string 43 | iso3: string 44 | capital: string 45 | tld: string 46 | population: number 47 | area: number 48 | callingCode: string 49 | postalCode: string 50 | timezone: { 51 | code: string 52 | offset: string 53 | } 54 | currency: { 55 | name: string 56 | code: string 57 | } 58 | languages: string[] 59 | } 60 | continent: { 61 | code: string 62 | inEu: boolean 63 | } 64 | } 65 | 66 | export interface ReservedData { 67 | reserved: boolean 68 | } 69 | 70 | export interface Options { 71 | /** 72 | An optional [ipapi](https://ipapi.co/) API key to use. 73 | 74 | @example 75 | ``` 76 | const ipLocation = require("ip-location"); 77 | 78 | (async () => { 79 | await ipLocation("172.217.167.78", { apiKey: 'YOUR_API_KEY' }); 80 | //=> { latitude: -33.8591, longitude: 151.2002, region: { name: "New South Wales" ... } ... } 81 | })(); 82 | ``` 83 | */ 84 | apiKey?: string 85 | } 86 | 87 | export type ReturnType = (LocationData & ReservedData) | ReservedData 88 | } 89 | 90 | function composeSearchParameters(options?: ipLocation.Options): {[key: string]: string | number | boolean} { 91 | return options?.apiKey ? { key: options.apiKey } : {} 92 | } 93 | 94 | /** 95 | Get ip location information. 96 | @param ip The ipv4 address to get the information for. 97 | @example 98 | ``` 99 | const ipLocation = require("ip-location"); 100 | 101 | (async () => { 102 | await ipLocation("172.217.167.78"); 103 | //=> { latitude: -33.8591, longitude: 151.2002, region: { name: "New South Wales" ... } ... } 104 | })(); 105 | ``` 106 | */ 107 | async function ipLocation(ip: string, options?: ipLocation.Options): Promise { 108 | if (typeof ip !== "string" || !isIp.v4(ip)) { 109 | throw new TypeError("A valid ipv4 address must be provided!") 110 | } 111 | 112 | const { latitude, longitude, city, reserved, region, region_code, country_name, country_code, country_code_iso3, country_capital, country_tld, country_population, country_calling_code, continent_code, in_eu, postal, timezone, utc_offset, currency, currency_name, languages, country_area }: IpApiData = await ky(`https://ipapi.co/${ip}/json/`, { searchParams: composeSearchParameters(options) }).json() 113 | 114 | return reserved ? { 115 | reserved 116 | } : { 117 | latitude, 118 | longitude, 119 | city, 120 | reserved: Boolean(reserved), 121 | region: { 122 | name: region, 123 | code: region_code 124 | }, 125 | country: { 126 | name: country_name, 127 | code: country_code, 128 | iso3: country_code_iso3, 129 | capital: country_capital, 130 | tld: country_tld, 131 | population: country_population, 132 | area: country_area, 133 | callingCode: country_calling_code, 134 | postalCode: postal, 135 | timezone: { 136 | code: timezone, 137 | offset: utc_offset 138 | }, 139 | currency: { 140 | name: currency_name, 141 | code: currency 142 | }, 143 | languages: languages ? languages.split(",") : [] 144 | }, 145 | continent: { 146 | code: continent_code, 147 | inEu: in_eu 148 | } 149 | } 150 | } 151 | 152 | export default ipLocation 153 | 154 | module.exports = ipLocation 155 | module.exports.default = ipLocation // eslint-disable-line @typescript-eslint/no-unsafe-member-access 156 | -------------------------------------------------------------------------------- /test.ts: -------------------------------------------------------------------------------- 1 | import test from "ava" 2 | import ipLocation from "./source" 3 | 4 | test("main", async t => { 5 | t.deepEqual(await ipLocation("172.217.167.78"), { 6 | latitude: -33.8591, 7 | longitude: 151.2002, 8 | city: "Sydney", 9 | reserved: false, 10 | region: { name: "New South Wales", code: "NSW" }, 11 | country: { 12 | name: "Australia", 13 | code: "AU", 14 | iso3: "AUS", 15 | capital: "Canberra", 16 | tld: ".au", 17 | population: 21515754, 18 | area: 7686850, 19 | callingCode: "+61", 20 | postalCode: "2000", 21 | timezone: { code: "Australia/Sydney", offset: "+1000" }, 22 | currency: { name: "Dollar", code: "AUD" }, 23 | languages: ["en-AU"] 24 | }, 25 | continent: { code: "OC", inEu: false } 26 | }) 27 | }) 28 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@richienb/tsconfig", 3 | "compilerOptions": { 4 | "outDir": "dist" 5 | }, 6 | "include": [ 7 | "source" 8 | ] 9 | } 10 | --------------------------------------------------------------------------------