├── LICENSE ├── README.md ├── numinfo.py └── requirements.txt /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Bishal Singh 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 10 | furnished 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, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 🔍 NumInfo - Advanced Phone Number Intelligence Tool 2 | 3 | 📡 A powerful Python tool for gathering comprehensive information about phone numbers using multiple APIs and data sources. 4 | 5 | ## 🌟 Features 6 | 7 | - ✅ **Phone Number Validation**: Verify if a number is valid and properly formatted 8 | - 📱 **Carrier Lookup**: Identify the service provider for any phone number 9 | - 🌍 **Geolocation**: Determine the country and region associated with a number 10 | - ⏰ **Timezone Detection**: Find the timezone(s) for a phone number 11 | - 🔌 **API Integration**: Supports NumVerify and AbstractAPI (optional) 12 | - 📊 **Multiple Output Formats**: Colorful console output and JSON export 13 | - 🔒 **Privacy Focused**: Only uses publicly available information 14 | 15 | ## 🛠️ Installation 16 | 17 | 1. Clone the repository: 18 | ```bash 19 | git clone https://github.com/Anon4You/NumInfo.git 20 | cd NumInfo 21 | ``` 22 | 23 | 2. Install dependencies: 24 | ```bash 25 | pip install -r requirements.txt 26 | ``` 27 | 28 | 3. (Optional) Set up environment variables for API features: 29 | ```bash 30 | cp .env.example .env 31 | # Edit .env with your API keys 32 | ``` 33 | 34 | ## 🚀 Usage 35 | 36 | Basic usage: 37 | ```bash 38 | python numinfo.py +1234567890 39 | ``` 40 | 41 | Save results to JSON file: 42 | ```bash 43 | python numinfo.py +1234567890 -o results.json 44 | ``` 45 | 46 | ### ⚙️ Command Line Options 47 | ``` 48 | positional arguments: 49 | phone_number Phone number to investigate (include country code) 50 | 51 | optional arguments: 52 | -h, --help show this help message and exit 53 | -o OUTPUT, --output OUTPUT 54 | Output file name (JSON format) 55 | ``` 56 | 57 | ## 🔑 API Integration 58 | 59 | For enhanced features, obtain API keys from: 60 | - [NumVerify](https://numverify.com/) (for carrier details) 61 | - [AbstractAPI](https://www.abstractapi.com/phone-validation-api) (for geolocation) 62 | 63 | Add your keys to the `.env` file: 64 | ``` 65 | NUMVERIFY_API_KEY=your_key_here 66 | ABSTRACT_API_KEY=your_key_here 67 | ``` 68 | ## 🤝 Contributing 69 | 70 | We welcome contributions! Please follow these steps: 71 | 1. Fork the repository 72 | 2. Create your feature branch (`git checkout -b feature/AmazingFeature`) 73 | 3. Commit your changes (`git commit -m 'Add some AmazingFeature'`) 74 | 4. Push to the branch (`git push origin feature/AmazingFeature`) 75 | 5. Open a Pull Request 76 | 77 | ## 📜 License 78 | 79 | Distributed under the MIT License. See `LICENSE` for more information. 80 | 81 | ## 📬 Contact 82 | 83 | 👨💻 **Alienkrishn** - [GitHub](https://github.com/Anon4You) 84 | 🔗 Project Link: [https://github.com/Anon4You/NumInfo](https://github.com/Anon4You/NumInfo) 85 | -------------------------------------------------------------------------------- /numinfo.py: -------------------------------------------------------------------------------- 1 | #!/data/data/com.termux/files/usr/bin/python 2 | 3 | ## NumInfo : Advanced Phone Number Intelligence Tool 4 | ## Author : Alienkrishn [Anon4You] 5 | 6 | import re 7 | import requests 8 | import json 9 | import phonenumbers 10 | from phonenumbers import carrier, geocoder, timezone 11 | import argparse 12 | from colorama import init, Fore 13 | import os 14 | from dotenv import load_dotenv 15 | 16 | # Initialize colorama 17 | init(autoreset=True) 18 | load_dotenv() 19 | 20 | # ASCII Art Logo 21 | LOGO = f"""{Fore.GREEN} 22 | 888b 888 8888888 .d888 23 | 8888b 888 888 d88P" 24 | 88888b 888 888 888 25 | 888Y88b 888 888 888 88888b.d88b. 888 88888b. 888888 .d88b. 26 | 888 Y88b888 888 888 888 "888 "88b 888 888 "88b 888 d88""88b 27 | 888 Y88888 888 888 888 888 888 888 888 888 888 888 888 28 | 888 Y8888 Y88b 888 888 888 888 888 888 888 888 Y88..88P 29 | 888 Y888 "Y88888 888 888 888 8888888 888 888 888 "Y88P" 30 | {Fore.MAGENTA}~created by Alienkrishn 31 | {Fore.RESET}Github:Anon4You 32 | """ 33 | 34 | class PhoneNumberInfoGatherer: 35 | def __init__(self, phone_number): 36 | self.phone_number = phone_number 37 | self.valid = False 38 | self.formatted_number = None 39 | self.country_code = None 40 | self.national_number = None 41 | self.results = { 42 | 'basic_info': {}, 43 | 'carrier_info': {}, 44 | 'geolocation': {}, 45 | 'timezone_info': {}, 46 | 'additional_data': {} 47 | } 48 | 49 | def validate_and_parse(self): 50 | """Validate and parse the phone number using phonenumbers library""" 51 | try: 52 | parsed_number = phonenumbers.parse(self.phone_number, None) 53 | self.valid = phonenumbers.is_valid_number(parsed_number) 54 | self.formatted_number = phonenumbers.format_number( 55 | parsed_number, phonenumbers.PhoneNumberFormat.E164) 56 | self.country_code = parsed_number.country_code 57 | self.national_number = parsed_number.national_number 58 | self.results['basic_info'] = { 59 | 'raw_input': self.phone_number, 60 | 'formatted_e164': self.formatted_number, 61 | 'country_code': self.country_code, 62 | 'national_number': self.national_number, 63 | 'is_valid': self.valid 64 | } 65 | return True 66 | except phonenumbers.phonenumberutil.NumberParseException as e: 67 | print(Fore.RED + f"Error parsing phone number: {e}") 68 | return False 69 | 70 | def get_carrier_info(self): 71 | """Get carrier information using phonenumbers and NumVerify API""" 72 | if not self.valid: 73 | return 74 | 75 | try: 76 | parsed_number = phonenumbers.parse(self.formatted_number) 77 | carrier_name = carrier.name_for_number(parsed_number, "en") 78 | self.results['carrier_info']['phonenumbers_lib'] = { 79 | 'carrier': carrier_name 80 | } 81 | 82 | # NumVerify API (requires API key in .env) 83 | numverify_api_key = os.getenv('NUMVERIFY_API_KEY') 84 | if numverify_api_key: 85 | try: 86 | url = f"http://apilayer.net/api/validate?access_key={numverify_api_key}&number={self.formatted_number}" 87 | response = requests.get(url) 88 | if response.status_code == 200: 89 | data = response.json() 90 | self.results['carrier_info']['numverify'] = { 91 | 'carrier': data.get('carrier'), 92 | 'line_type': data.get('line_type'), 93 | 'ported': data.get('ported') 94 | } 95 | except Exception as e: 96 | print(Fore.YELLOW + f"NumVerify API error: {e}") 97 | 98 | except Exception as e: 99 | print(Fore.RED + f"Error getting carrier info: {e}") 100 | 101 | def get_geolocation(self): 102 | """Get geolocation information""" 103 | if not self.valid: 104 | return 105 | 106 | try: 107 | parsed_number = phonenumbers.parse(self.formatted_number) 108 | region = geocoder.description_for_number(parsed_number, "en") 109 | self.results['geolocation']['phonenumbers_lib'] = { 110 | 'region': region 111 | } 112 | 113 | # AbstractAPI (requires API key in .env) 114 | abstract_api_key = os.getenv('ABSTRACT_API_KEY') 115 | if abstract_api_key: 116 | try: 117 | url = f"https://phonevalidation.abstractapi.com/v1/?api_key={abstract_api_key}&phone={self.formatted_number}" 118 | response = requests.get(url) 119 | if response.status_code == 200: 120 | data = response.json() 121 | self.results['geolocation']['abstractapi'] = { 122 | 'country': data.get('country'), 123 | 'country_code': data.get('country_code'), 124 | 'location': data.get('location') 125 | } 126 | except Exception as e: 127 | print(Fore.YELLOW + f"AbstractAPI error: {e}") 128 | 129 | except Exception as e: 130 | print(Fore.RED + f"Error getting geolocation: {e}") 131 | 132 | def get_timezone(self): 133 | """Get timezone information""" 134 | if not self.valid: 135 | return 136 | 137 | try: 138 | parsed_number = phonenumbers.parse(self.formatted_number) 139 | time_zones = timezone.time_zones_for_number(parsed_number) 140 | self.results['timezone_info'] = { 141 | 'time_zones': time_zones 142 | } 143 | except Exception as e: 144 | print(Fore.RED + f"Error getting timezone: {e}") 145 | 146 | def get_additional_data(self): 147 | """Get additional data from other sources""" 148 | if not self.valid: 149 | return 150 | 151 | try: 152 | self.results['additional_data']['reputation_check'] = { 153 | 'reported_as_spam': False, 154 | 'reported_as_scam': False, 155 | 'notes': 'This would require integration with a reputation API' 156 | } 157 | except Exception as e: 158 | print(Fore.YELLOW + f"Error checking number reputation: {e}") 159 | 160 | def gather_all_info(self): 161 | """Run all information gathering methods""" 162 | if not self.validate_and_parse(): 163 | return False 164 | 165 | self.get_carrier_info() 166 | self.get_geolocation() 167 | self.get_timezone() 168 | self.get_additional_data() 169 | return True 170 | 171 | def print_results(self): 172 | """Print the gathered information in a readable format""" 173 | if not self.valid: 174 | print(Fore.RED + "Invalid phone number. Could not gather information.") 175 | return 176 | 177 | print(Fore.GREEN + "\n=== Phone Number Information ===") 178 | print(Fore.CYAN + f"\n[Basic Information]") 179 | for key, value in self.results['basic_info'].items(): 180 | print(f"{key.replace('_', ' ').title()}: {Fore.YELLOW}{value}") 181 | 182 | print(Fore.CYAN + "\n[Carrier Information]") 183 | for source, data in self.results['carrier_info'].items(): 184 | print(f"\nSource: {Fore.MAGENTA}{source}") 185 | for key, value in data.items(): 186 | print(f"{key.replace('_', ' ').title()}: {Fore.YELLOW}{value}") 187 | 188 | print(Fore.CYAN + "\n[Geolocation Information]") 189 | for source, data in self.results['geolocation'].items(): 190 | print(f"\nSource: {Fore.MAGENTA}{source}") 191 | for key, value in data.items(): 192 | print(f"{key.replace('_', ' ').title()}: {Fore.YELLOW}{value}") 193 | 194 | print(Fore.CYAN + "\n[Timezone Information]") 195 | for key, value in self.results['timezone_info'].items(): 196 | print(f"{key.replace('_', ' ').title()}: {Fore.YELLOW}{value}") 197 | 198 | print(Fore.CYAN + "\n[Additional Data]") 199 | for category, data in self.results['additional_data'].items(): 200 | print(f"\nCategory: {Fore.MAGENTA}{category.replace('_', ' ').title()}") 201 | for key, value in data.items(): 202 | print(f"{key.replace('_', ' ').title()}: {Fore.YELLOW}{value}") 203 | 204 | def save_to_file(self, filename="phone_info.json"): 205 | """Save the results to a JSON file""" 206 | with open(filename, 'w') as f: 207 | json.dump(self.results, f, indent=4) 208 | print(Fore.GREEN + f"\nResults saved to {filename}") 209 | 210 | 211 | def main(): 212 | print(LOGO) 213 | parser = argparse.ArgumentParser(description="Advanced Phone Number Information Gathering Tool") 214 | parser.add_argument("phone_number", help="Phone number to investigate (include country code)") 215 | parser.add_argument("-o", "--output", help="Output file name (JSON format)", default=None) 216 | args = parser.parse_args() 217 | 218 | print(Fore.BLUE + "Starting phone number information gathering...") 219 | 220 | gatherer = PhoneNumberInfoGatherer(args.phone_number) 221 | if gatherer.gather_all_info(): 222 | gatherer.print_results() 223 | if args.output: 224 | gatherer.save_to_file(args.output) 225 | else: 226 | print(Fore.RED + "Failed to gather information for the provided phone number.") 227 | 228 | if __name__ == "__main__": 229 | main() 230 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | certifi==2025.4.26 2 | charset-normalizer==3.4.2 3 | colorama==0.4.6 4 | idna==3.10 5 | phonenumbers==9.0.5 6 | python-dotenv==1.1.0 7 | requests==2.32.3 8 | urllib3==2.4.0 9 | --------------------------------------------------------------------------------