├── .gitignore ├── .readthedocs.yaml ├── AUTHORS ├── ChangeLog ├── IP2Proxy.py ├── LICENSE.TXT ├── PKG-INFO ├── README.md ├── data ├── IP2PROXY-IP-PROXYTYPE-COUNTRY-REGION-CITY-ISP.SAMPLE.BIN └── PX10.SAMPLE.bin ├── docs ├── Makefile ├── make.bat ├── requirements.txt └── source │ ├── code.md │ ├── conf.py │ ├── images │ ├── favicon.ico │ └── ipl-logo-square-1200.png │ ├── index.md │ └── quickstart.md ├── example.py ├── setup.py └── tests ├── test_database.py └── test_webservice.py /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | .vscode/ 3 | .venv*/ 4 | venv*/ 5 | __pycache__/ 6 | dist/ 7 | .coverage* 8 | htmlcov/ 9 | .tox/ 10 | docs/_build/ 11 | *.egg-info -------------------------------------------------------------------------------- /.readthedocs.yaml: -------------------------------------------------------------------------------- 1 | # .readthedocs.yaml 2 | # Read the Docs configuration file 3 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 4 | 5 | # Required 6 | version: 2 7 | 8 | # Set the OS, Python version and other tools you might need 9 | build: 10 | os: ubuntu-22.04 11 | tools: 12 | python: "3.11" 13 | # You can also specify other tool versions: 14 | # nodejs: "19" 15 | # rust: "1.64" 16 | # golang: "1.19" 17 | 18 | # Build documentation in the "docs/" directory with Sphinx 19 | sphinx: 20 | configuration: docs/source/conf.py 21 | 22 | # Optionally build your docs in additional formats such as PDF and ePub 23 | # formats: 24 | # - pdf 25 | # - epub 26 | 27 | # Optional but recommended, declare the Python requirements required 28 | # to build your documentation 29 | # See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html 30 | python: 31 | install: 32 | - requirements: docs/requirements.txt -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | IP2Location -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- 1 | 3.5.1 2025-02-21 2 | * Tested with Python 3.13. 3 | 4 | 3.5.0 2025-02-18 5 | * Added new field "fraud_score" to support PX12 database. 6 | 7 | 3.4.2 2024-10-04 8 | * Tested with CPython and PyPy. 9 | 10 | 3.4.1 2024-09-27 11 | * Tested with Python 3.12. 12 | 13 | 3.4.0 2022-06-23 14 | * Reduced file I/O. 15 | 16 | 3.3.0 2021-08-18 17 | * Support IP2Proxy Web Service. 18 | 19 | 3.2.1 2021-07-19 20 | * Removed unused code. 21 | 22 | 3.2.0 2021-06-25 23 | * Added provider field and exception handling for incorrect BIN database. 24 | 25 | 3.1.2 2019-08-13 26 | * Updated version number to latest. 27 | 28 | 3.1.1 2019-08-11 29 | * Removed unwanted file. 30 | 31 | 3.1.0 2020-08-11 32 | * Fixed bug. 33 | 34 | 3.0.0 2020-07-24 35 | * Added support for 6to4 and Teredo. 36 | 37 | 2.2.0 2019-12-04 38 | * Reduce File I/O. 39 | 40 | 2.1.0 2019-07-03 41 | * Added support for 6to4 and Teredo. 42 | 43 | 2.0.0 2019-05-16 44 | * Added supports for PX5-PX8 database. 45 | 46 | 1.0.1 2016-12-16 47 | * Changed variable to match standard. 48 | 49 | 1.0.0 2016-12-15 50 | * Initial release 51 | -------------------------------------------------------------------------------- /IP2Proxy.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2002-2024 IP2Location.com 2 | # All Rights Reserved 3 | # 4 | # This library is free software: you can redistribute it and/or 5 | # modify it under the terms of the GNU Lesser General Public 6 | # License as published by the Free Software Foundation, either 7 | # version 3 of the License, or (at your option) any later version. 8 | # 9 | # This library is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public 15 | # License along with this library; If not, see . 16 | 17 | import sys 18 | import struct 19 | import socket 20 | import ipaddress 21 | import os 22 | import json 23 | import re 24 | 25 | if sys.version < '3': 26 | import urllib, httplib 27 | def urlencode(x): 28 | return urllib.urlencode(x) 29 | def httprequest(x, usessl): 30 | try: 31 | # conn = httplib.HTTPConnection("api.ip2proxy.com") 32 | if (usessl is True): 33 | conn = httplib.HTTPSConnection("api.ip2proxy.com") 34 | else: 35 | conn = httplib.HTTPConnection("api.ip2proxy.com") 36 | conn.request("GET", "/?" + x) 37 | res = conn.getresponse() 38 | return json.loads(res.read()) 39 | except: 40 | return None 41 | def u(x): 42 | return x.decode('utf-8') 43 | def b(x): 44 | return str(x) 45 | else: 46 | import urllib.parse, http.client 47 | def urlencode(x): 48 | return urllib.parse.urlencode(x) 49 | def httprequest(x, usessl): 50 | try: 51 | # conn = http.client.HTTPConnection("api.ip2proxy.com") 52 | if (usessl is True): 53 | conn = http.client.HTTPSConnection("api.ip2proxy.com") 54 | else: 55 | conn = http.client.HTTPConnection("api.ip2proxy.com") 56 | conn.request("GET", "/?" + x) 57 | res = conn.getresponse() 58 | return json.loads(res.read()) 59 | except: 60 | return None 61 | def u(x): 62 | if isinstance(x, bytes): 63 | return x.decode() 64 | return x 65 | def b(x): 66 | if isinstance(x, bytes): 67 | return x 68 | return x.encode('ascii') 69 | 70 | 71 | # Windows version of Python does not provide it 72 | # for compatibility with older versions of Windows. 73 | if not hasattr(socket, 'inet_pton'): 74 | def inet_pton(t, addr): 75 | import ctypes 76 | a = ctypes.WinDLL('ws2_32.dll') 77 | in_addr_p = ctypes.create_string_buffer(b(addr)) 78 | if t == socket.AF_INET: 79 | out_addr_p = ctypes.create_string_buffer(4) 80 | elif t == socket.AF_INET6: 81 | out_addr_p = ctypes.create_string_buffer(16) 82 | n = a.inet_pton(t, in_addr_p, out_addr_p) 83 | if n == 0: 84 | raise ValueError('Invalid address') 85 | return out_addr_p.raw 86 | socket.inet_pton = inet_pton 87 | 88 | _VERSION = '3.5.1' 89 | _NO_IP = 'MISSING IP ADDRESS' 90 | _FIELD_NOT_SUPPORTED = 'NOT SUPPORTED' 91 | _INVALID_IP_ADDRESS = 'INVALID IP ADDRESS' 92 | MAX_IPV4_RANGE = 4294967295 93 | MAX_IPV6_RANGE = 340282366920938463463374607431768211455 94 | 95 | class IP2ProxyRecord: 96 | ''' IP2Proxy record with all fields from the database ''' 97 | ip = None 98 | country_short = _FIELD_NOT_SUPPORTED 99 | country_long = _FIELD_NOT_SUPPORTED 100 | region = _FIELD_NOT_SUPPORTED 101 | city = _FIELD_NOT_SUPPORTED 102 | isp = _FIELD_NOT_SUPPORTED 103 | proxy_type = _FIELD_NOT_SUPPORTED 104 | usage_type = _FIELD_NOT_SUPPORTED 105 | as_name = _FIELD_NOT_SUPPORTED 106 | asn = _FIELD_NOT_SUPPORTED 107 | last_seen = _FIELD_NOT_SUPPORTED 108 | domain = _FIELD_NOT_SUPPORTED 109 | threat = _FIELD_NOT_SUPPORTED 110 | provider = _FIELD_NOT_SUPPORTED 111 | fraud_score = _FIELD_NOT_SUPPORTED 112 | 113 | def __str__(self): 114 | return str(self.__dict__) 115 | 116 | def __repr__(self): 117 | return repr(self.__dict__) 118 | 119 | _COUNTRY_POSITION = (0, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3) 120 | _REGION_POSITION = (0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4) 121 | _CITY_POSITION = (0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5) 122 | _ISP_POSITION = (0, 0, 0, 0, 6, 6, 6, 6, 6, 6, 6, 6, 6) 123 | _PROXYTYPE_POSITION = (0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2) 124 | _DOMAIN_POSITION = (0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 7, 7, 7) 125 | _USAGETYPE_POSITION = (0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8) 126 | _ASN_POSITION = (0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9) 127 | _AS_POSITION = (0, 0, 0, 0, 0, 0, 0, 10, 10, 10, 10, 10, 10) 128 | _LASTSEEN_POSITION = (0, 0, 0, 0, 0, 0, 0, 0, 11, 11, 11, 11, 11) 129 | _THREAT_POSITION = (0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 12, 12, 12) 130 | _PROVIDER_POSITION = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 13) 131 | _FRAUD_SCORE_POSITION = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14) 132 | 133 | class IP2Proxy(object): 134 | ''' IP2Proxy database ''' 135 | 136 | def __init__(self, filename=None): 137 | ''' Creates a database object and opens a file if filename is given ''' 138 | 139 | if filename: 140 | self.open(filename) 141 | 142 | def __enter__(self): 143 | if not hasattr(self, '_f') or self._f.closed: 144 | raise ValueError("Cannot enter context with closed file") 145 | return self 146 | 147 | def __exit__(self, exc_type, exc_value, traceback): 148 | self.close() 149 | 150 | def open(self, filename): 151 | ''' Opens a database file ''' 152 | # Ensure old file is closed before opening a new one 153 | self.close() 154 | 155 | # if filename is not None: 156 | if os.path.isfile(filename) == False: 157 | raise ValueError("The database file does not seem to exist.") 158 | 159 | self._f = open(filename, 'rb') 160 | self._f.seek(0) 161 | header_row = self._f.read(32) 162 | self._dbtype = struct.unpack('B', header_row[0:1])[0] 163 | self._dbcolumn = struct.unpack('B', header_row[1:2])[0] 164 | self._dbyear = struct.unpack('B', header_row[2:3])[0] 165 | self._dbmonth = struct.unpack('B', header_row[3:4])[0] 166 | self._dbday = struct.unpack('B', header_row[4:5])[0] 167 | self._ipv4dbcount = struct.unpack(' 20 and self._productcode != 0) : 178 | self._f.close() 179 | del self._f 180 | raise ValueError("Incorrect IP2Location BIN file format. Please make sure that you are using the latest IP2Location BIN file.") 181 | 182 | def close(self): 183 | if hasattr(self, '_f'): 184 | # If there is file close it. 185 | self._f.close() 186 | del self._f 187 | 188 | def get_module_version(self): 189 | return _VERSION 190 | 191 | def get_package_version(self): 192 | return str(self._dbtype) 193 | 194 | def get_database_version(self): 195 | return str(self._dbyear) + "." + str(self._dbmonth) + "." + str(self._dbday) 196 | 197 | def get_country_short(self, ip): 198 | ''' Get country_short ''' 199 | try: 200 | rec = self._get_record(ip) 201 | country_short = rec.country_short 202 | except: 203 | country_short = _INVALID_IP_ADDRESS 204 | return country_short 205 | 206 | def get_country_long(self, ip): 207 | ''' Get country_long ''' 208 | try: 209 | rec = self._get_record(ip) 210 | country_long = rec.country_long 211 | except: 212 | country_long = _INVALID_IP_ADDRESS 213 | return country_long 214 | 215 | def get_region(self, ip): 216 | ''' Get region ''' 217 | try: 218 | rec = self._get_record(ip) 219 | region = rec.region 220 | except: 221 | region = _INVALID_IP_ADDRESS 222 | return region 223 | 224 | def get_city(self, ip): 225 | ''' Get city ''' 226 | try: 227 | rec = self._get_record(ip) 228 | city = rec.city 229 | except: 230 | city = _INVALID_IP_ADDRESS 231 | return city 232 | 233 | def get_isp(self, ip): 234 | ''' Get isp ''' 235 | try: 236 | rec = self._get_record(ip) 237 | isp = rec.isp 238 | except: 239 | isp = _INVALID_IP_ADDRESS 240 | return isp 241 | 242 | def get_proxy_type(self, ip): 243 | ''' Get proxy_type ''' 244 | try: 245 | rec = self._get_record(ip) 246 | proxy_type = rec.proxy_type 247 | except: 248 | proxy_type = _INVALID_IP_ADDRESS 249 | return proxy_type 250 | 251 | def is_proxy(self, ip): 252 | ''' Determine whether is a proxy ''' 253 | try: 254 | rec = self._get_record(ip) 255 | if rec.country_short != _INVALID_IP_ADDRESS: 256 | if self._dbtype == 1: 257 | is_proxy = 0 if (rec.country_short == '-') else ( 2 if ((rec.proxy_type == 'DCH') | (rec.proxy_type == 'SES')) else 1) 258 | else: 259 | is_proxy = 0 if (rec.proxy_type == '-') else ( 2 if ((rec.proxy_type == 'DCH') | (rec.proxy_type == 'SES')) else 1) 260 | else: 261 | is_proxy = -1 262 | except: 263 | is_proxy = -1 264 | return is_proxy 265 | 266 | def get_domain(self, ip): 267 | ''' Get domain ''' 268 | try: 269 | rec = self._get_record(ip) 270 | domain = rec.domain 271 | except: 272 | domain = _INVALID_IP_ADDRESS 273 | return domain 274 | 275 | def get_usage_type(self, ip): 276 | ''' Get usage_type ''' 277 | try: 278 | rec = self._get_record(ip) 279 | usage_type = rec.usage_type 280 | except: 281 | usage_type = _INVALID_IP_ADDRESS 282 | return usage_type 283 | 284 | def get_asn(self, ip): 285 | ''' Get asn ''' 286 | try: 287 | rec = self._get_record(ip) 288 | asn = rec.asn 289 | except: 290 | asn = _INVALID_IP_ADDRESS 291 | return asn 292 | 293 | def get_as_name(self, ip): 294 | ''' Get as_name ''' 295 | try: 296 | rec = self._get_record(ip) 297 | as_name = rec.as_name 298 | except: 299 | as_name = _INVALID_IP_ADDRESS 300 | return as_name 301 | 302 | def get_last_seen(self, ip): 303 | ''' Get last_seen ''' 304 | try: 305 | rec = self._get_record(ip) 306 | last_seen = rec.last_seen 307 | except: 308 | last_seen = _INVALID_IP_ADDRESS 309 | return last_seen 310 | 311 | def get_threat(self, ip): 312 | ''' Get threat''' 313 | try: 314 | rec = self._get_record(ip) 315 | threat = rec.threat 316 | except: 317 | threat = _INVALID_IP_ADDRESS 318 | return threat 319 | 320 | def get_provider(self, ip): 321 | ''' Get provider''' 322 | try: 323 | rec = self._get_record(ip) 324 | provider = rec.provider 325 | except: 326 | provider = _INVALID_IP_ADDRESS 327 | return provider 328 | 329 | def get_fraud_score(self, ip): 330 | ''' Get fraud_score''' 331 | try: 332 | rec = self._get_record(ip) 333 | fraud_score = rec.fraud_score 334 | except: 335 | fraud_score = _INVALID_IP_ADDRESS 336 | return fraud_score 337 | 338 | def get_all(self, ip): 339 | ''' Get the whole record with all fields read from the file ''' 340 | try: 341 | rec = self._get_record(ip) 342 | country_short = rec.country_short 343 | country_long = rec.country_long 344 | region = rec.region 345 | city = rec.city 346 | isp = rec.isp 347 | proxy_type = rec.proxy_type 348 | domain = rec.domain 349 | usage_type = rec.usage_type 350 | asn = rec.asn 351 | as_name = rec.as_name 352 | last_seen = rec.last_seen 353 | threat = rec.threat 354 | provider = rec.provider 355 | fraud_score = rec.fraud_score 356 | if rec.country_short != _INVALID_IP_ADDRESS: 357 | if self._dbtype == 1: 358 | is_proxy = 0 if (rec.country_short == '-') else ( 2 if ((rec.proxy_type == 'DCH') | (rec.proxy_type == 'SES')) else 1) 359 | else: 360 | is_proxy = 0 if (rec.proxy_type == '-') else ( 2 if ((rec.proxy_type == 'DCH') | (rec.proxy_type == 'SES')) else 1) 361 | else: 362 | is_proxy = -1 363 | except: 364 | country_short = _INVALID_IP_ADDRESS 365 | country_long = _INVALID_IP_ADDRESS 366 | region = _INVALID_IP_ADDRESS 367 | city = _INVALID_IP_ADDRESS 368 | isp = _INVALID_IP_ADDRESS 369 | proxy_type = _INVALID_IP_ADDRESS 370 | is_proxy = -1 371 | domain = _INVALID_IP_ADDRESS 372 | usage_type = _INVALID_IP_ADDRESS 373 | asn = _INVALID_IP_ADDRESS 374 | as_name = _INVALID_IP_ADDRESS 375 | last_seen = _INVALID_IP_ADDRESS 376 | threat = _INVALID_IP_ADDRESS 377 | provider = _INVALID_IP_ADDRESS 378 | fraud_score = _INVALID_IP_ADDRESS 379 | 380 | results = {} 381 | results['is_proxy'] = is_proxy 382 | results['proxy_type'] = proxy_type 383 | results['country_short'] = country_short 384 | results['country_long'] = country_long 385 | results['region'] = region 386 | results['city'] = city 387 | results['isp'] = isp 388 | results['domain'] = domain 389 | results['usage_type'] = usage_type 390 | results['asn'] = asn 391 | results['as_name'] = as_name 392 | results['last_seen'] = last_seen 393 | results['threat'] = threat 394 | results['provider'] = provider 395 | results['fraud_score'] = fraud_score 396 | return results 397 | 398 | def _reads(self, offset): 399 | self._f.seek(offset - 1) 400 | data = self._f.read(257) 401 | char_count = struct.unpack('B', data[0:1])[0] 402 | string = data[1:char_count+1] 403 | return u(string.decode('iso-8859-1').encode('utf-8')) 404 | 405 | def _readi(self, offset): 406 | self._f.seek(offset - 1) 407 | return struct.unpack('= 281470681743360) and (ipnum <= 281474976710655)): 547 | ipv = 4 548 | ipnum = ipnum - 281470681743360 549 | else: 550 | ipv = 6 551 | else: 552 | # ipv = 6 553 | if ((ipnum >= 42545680458834377588178886921629466624) and (ipnum <= 42550872755692912415807417417958686719)): 554 | ipv = 4 555 | ipnum = ipnum >> 80 556 | ipnum = ipnum % 4294967296 557 | elif ((ipnum >= 42540488161975842760550356425300246528) and (ipnum <= 42540488241204005274814694018844196863)): 558 | ipv = 4 559 | # ipnum = ipnum % 100000000000000000000000000000000 560 | ipnum = ~ ipnum 561 | ipnum = ipnum % 4294967296 562 | else: 563 | ipv = 6 564 | except: 565 | ipnum = struct.unpack('!L', socket.inet_pton(socket.AF_INET, addr))[0] 566 | # socket.inet_pton(socket.AF_INET, addr) 567 | ipv = 4 568 | return ipv, ipnum 569 | 570 | def calc_off(self, off, baseaddr, what, mid): 571 | # return baseaddr + mid * (self._dbcolumn * 4 + off) + off + 4 * (what[self._dbtype]-1) 572 | return baseaddr + mid * (self._dbcolumn * 4 + off) + off + 4 * (what-1) 573 | 574 | def read32x2(self, offset): 575 | self._f.seek(offset - 1) 576 | data = self._f.read(8) 577 | return struct.unpack(' 0: 626 | indexpos = ((ipno >> 16) << 3) + self._ipv4indexbaseaddr 627 | low,high = self.read32x2(indexpos) 628 | 629 | elif ipv == 6: 630 | # a, b = struct.unpack('!QQ', socket.inet_pton(socket.AF_INET6, ip)) 631 | # ipnum = (a << 64) | b 632 | if (ipnum == MAX_IPV6_RANGE): 633 | ipno = ipnum - 1 634 | else: 635 | ipno = ipnum 636 | off = 12 637 | baseaddr = self._ipv6dbaddr 638 | high = self._ipv6dbcount 639 | if self._ipv6indexbaseaddr > 0: 640 | indexpos = ((ipno >> 112) << 3) + self._ipv6indexbaseaddr 641 | low,high = self.read32x2(indexpos) 642 | 643 | # elif (ipnum == '' or ipv == ): 644 | elif (ipnum == ''): 645 | rec = IP2ProxyRecord() 646 | rec.country_short = _NO_IP 647 | rec.country_long = _NO_IP 648 | rec.region = _NO_IP 649 | rec.city = _NO_IP 650 | rec.isp = _NO_IP 651 | rec.proxy_type = _NO_IP 652 | rec.domain = _NO_IP 653 | rec.usage_type = _NO_IP 654 | rec.asn = _NO_IP 655 | rec.as_name = _NO_IP 656 | rec.last_seen = _NO_IP 657 | rec.threat = _NO_IP 658 | rec.provider = _NO_IP 659 | rec.fraud_score = _NO_IP 660 | return rec 661 | else: 662 | rec = IP2ProxyRecord() 663 | rec.country_short = _INVALID_IP_ADDRESS 664 | rec.country_long = _INVALID_IP_ADDRESS 665 | rec.region = _INVALID_IP_ADDRESS 666 | rec.city = _INVALID_IP_ADDRESS 667 | rec.isp = _INVALID_IP_ADDRESS 668 | rec.proxy_type = _INVALID_IP_ADDRESS 669 | rec.domain = _INVALID_IP_ADDRESS 670 | rec.usage_type = _INVALID_IP_ADDRESS 671 | rec.asn = _INVALID_IP_ADDRESS 672 | rec.as_name = _INVALID_IP_ADDRESS 673 | rec.last_seen = _INVALID_IP_ADDRESS 674 | rec.threat = _INVALID_IP_ADDRESS 675 | rec.provider = _INVALID_IP_ADDRESS 676 | rec.fraud_score = _INVALID_IP_ADDRESS 677 | return rec 678 | 679 | while low <= high: 680 | # mid = int((low + high) / 2) 681 | mid = int((low + high) >> 1) 682 | if ipv == 4: 683 | ipfrom, ipto = self.readRow32(baseaddr + mid * self._dbcolumn * 4 ) 684 | elif ipv == 6: 685 | ipfrom, ipto = self.readRow128(baseaddr + mid * ((self._dbcolumn * 4) + 12) ) 686 | 687 | if ipfrom <= ipno < ipto: 688 | return self._read_record(mid, ipv) 689 | else: 690 | if ipno < ipfrom: 691 | high = mid - 1 692 | else: 693 | low = mid + 1 694 | 695 | class IP2ProxyWebService(object): 696 | ''' IP2Proxy web service ''' 697 | def __init__(self,apikey,package,usessl=True): 698 | if ((re.match(r"^[0-9A-Z]{10}$", apikey) == None) and (apikey != 'demo')): 699 | raise ValueError("Please provide a valid IP2Proxy web service API key.") 700 | if (re.match(r"^PX[0-9]+$", package) == None): 701 | package = 'PX1' 702 | self.apikey = apikey 703 | self.package = package 704 | self.usessl = usessl 705 | 706 | def lookup(self,ip): 707 | '''This function will look the given IP address up in IP2Proxy web service.''' 708 | parameters = urlencode((("ip", ip), ("key", self.apikey), ("package", self.package))) 709 | response = httprequest(parameters, self.usessl) 710 | if (response == None): 711 | return False 712 | if (('response' in response) and (response['response'] != "OK")): 713 | raise IP2ProxyAPIError(response['response']) 714 | return response 715 | 716 | def getcredit(self): 717 | '''Get the remaing credit in your IP2Proxy web service account.''' 718 | parameters = urlencode((("key", self.apikey), ("check", True))) 719 | response = httprequest(parameters, self.usessl) 720 | if (response == None): 721 | return 0 722 | if ('response' in response is False): 723 | return 0 724 | return response['response'] 725 | 726 | class IP2ProxyAPIError(Exception): 727 | """Raise for IP2Proxy API Error Message""" 728 | -------------------------------------------------------------------------------- /LICENSE.TXT: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 - 2025 IP2Location.com 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 | -------------------------------------------------------------------------------- /PKG-INFO: -------------------------------------------------------------------------------- 1 | Metadata-Version: 1.0 2 | Name: IP2Proxy 3 | Version: 3.5.1 4 | Summary: Python API for IP2Proxy database 5 | Home-page: http://www.ip2location.com 6 | Author: IP2Location 7 | Author-email: support@ip2location.com 8 | License: GPL 9 | Description: This is a IP2Proxy Python library that lookup IP address to detect VPN servers, open proxies, web proxies, Tor exit nodes and data center ranges. 10 | Platform: Mac OS, Linux, Windows 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # IP2Proxy Python Library 2 | 3 | ![PyPI](https://img.shields.io/pypi/v/IP2Proxy) 4 | ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/IP2Proxy) 5 | ![PyPI - Downloads](https://img.shields.io/pypi/dm/IP2Proxy) 6 | 7 | This library allows user to query an IP address if it was being used as VPN servers, open proxies, web proxies, Tor exit nodes, search engine robots, data center ranges, residential proxies, consumer privacy networks, and enterprise private networks. It lookup the proxy IP address from **IP2Proxy BIN Data** file. This data file can be downloaded at 8 | 9 | * Free IP2Proxy BIN Data: [https://lite.ip2location.com](https://lite.ip2location.com) 10 | * Commercial IP2Proxy BIN Data: [https://www.ip2location.com/proxy-database](https://www.ip2location.com/proxy-database) 11 | 12 | For more details, please visit: 13 | [https://www.ip2location.com/documentation/ip2proxy-libraries/python](https://www.ip2location.com/documentation/ip2proxy-libraries/python) 14 | 15 | ## Developer Documentation 16 | To learn more about installation, usage, and code examples, please visit the developer documentation at [https://ip2proxy-python.readthedocs.io/en/latest/index.html.](https://ip2proxy-python.readthedocs.io/en/latest/index.html) 17 | 18 | ## Proxy Type 19 | 20 | | Proxy Type | Description | 21 | | ---------- | ------------------------------ | 22 | | VPN | Anonymizing VPN services. | 23 | | TOR | Tor Exit Nodes. | 24 | | PUB | Public Proxies. | 25 | | WEB | Web Proxies. | 26 | | DCH | Hosting Providers/Data Center. | 27 | | SES | Search Engine Robots. | 28 | | RES | Residential Proxies [PX10+] | 29 | | CPN | Consumer Privacy Networks. [PX11+] | 30 | | EPN | Enterprise Private Networks. [PX11+] | 31 | 32 | ## Usage Type 33 | 34 | | Usage Type | Description | 35 | | ---------- | ------------------------------- | 36 | | COM | Commercial | 37 | | ORG | Organization | 38 | | GOV | Government | 39 | | MIL | Military | 40 | | EDU | University/College/School | 41 | | LIB | Library | 42 | | CDN | Content Delivery Network | 43 | | ISP | Fixed Line ISP | 44 | | MOB | Mobile ISP | 45 | | DCH | Data Center/Web Hosting/Transit | 46 | | SES | Search Engine Spider | 47 | | RSV | Reserved | 48 | 49 | ## Threat Type 50 | 51 | | Threat Type | Description | 52 | | ----------- | -------------------------- | 53 | | SPAM | Spammer | 54 | | SCANNER | Security Scanner or Attack | 55 | | BOTNET | Spyware or Malware | 56 | 57 | 58 | 59 | ## Support 60 | 61 | Email: support@ip2location.com. 62 | URL: [https://www.ip2location.com](https://www.ip2location.com) 63 | -------------------------------------------------------------------------------- /data/IP2PROXY-IP-PROXYTYPE-COUNTRY-REGION-CITY-ISP.SAMPLE.BIN: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ip2location/ip2proxy-python/e7a356fc37455edd71f879335895ac63fb7aee3c/data/IP2PROXY-IP-PROXYTYPE-COUNTRY-REGION-CITY-ISP.SAMPLE.BIN -------------------------------------------------------------------------------- /data/PX10.SAMPLE.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ip2location/ip2proxy-python/e7a356fc37455edd71f879335895ac63fb7aee3c/data/PX10.SAMPLE.bin -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= sphinx-build 8 | SOURCEDIR = source 9 | BUILDDIR = build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=source 11 | set BUILDDIR=build 12 | 13 | %SPHINXBUILD% >NUL 2>NUL 14 | if errorlevel 9009 ( 15 | echo. 16 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 17 | echo.installed, then set the SPHINXBUILD environment variable to point 18 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 19 | echo.may add the Sphinx directory to PATH. 20 | echo. 21 | echo.If you don't have Sphinx installed, grab it from 22 | echo.https://www.sphinx-doc.org/ 23 | exit /b 1 24 | ) 25 | 26 | if "%1" == "" goto help 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | # Defining the exact version will make sure things don't break 2 | sphinx-book-theme==1.0.1 3 | # sphinx-pdj-theme==0.4.0 4 | myst-parser==2.0.0 5 | markdown-it-py==3.0.0 6 | sphinx-copybutton==0.5.2 -------------------------------------------------------------------------------- /docs/source/code.md: -------------------------------------------------------------------------------- 1 | # IP2Proxy Python API 2 | 3 | ## IP2Proxy Class 4 | ```{py:class} IP2Proxy() 5 | Construct the IP2Location Class. 6 | ``` 7 | 8 | ```{py:function} open(binpath) 9 | Load the IP2Proxy BIN database for lookup. 10 | 11 | :param str binpath: (Required) The file path links to IP2Proxy BIN databases. 12 | ``` 13 | 14 | ```{py:function} get_package_version() 15 | Return the database's type, 1 to 10 respectively for PX1 to PX11. Please visit https://www.ip2location.com/databases/ip2proxy for details. 16 | 17 | :return: Returns the package version. 18 | :rtype: string 19 | ``` 20 | 21 | ```{py:function} get_module_version() 22 | Return the version of module. 23 | 24 | :return: Returns the module version. 25 | :rtype: string 26 | ``` 27 | 28 | ```{py:function} get_database_version() 29 | Return the database's compilation date as a string of the form 'YYYY-MM-DD'. 30 | 31 | :return: Returns the database version. 32 | :rtype: string 33 | ``` 34 | 35 | ```{py:function} get_all(ip) 36 | Retrieve geolocation information for an IP address. 37 | 38 | :param string ip: (Required) The IP address (IPv4 or IPv6). 39 | :return: Returns the geolocation information in array. Refer below table for the fields avaliable in the array 40 | :rtype: array 41 | 42 | **RETURN FIELDS** 43 | 44 | | Field Name | Description | 45 | | ---------------- | ------------------------------------------------------------ | 46 | | is_proxy | Determine whether if an IP address was a proxy or not. Returns 0 is not proxy, 1 if proxy, and 2 if it's data center IP | 47 | | country_short | Two-character country code based on ISO 3166. | 48 | | country_long | Country name based on ISO 3166. | 49 | | region | Region or state name. | 50 | | city | City name. | 51 | | isp | Internet Service Provider or company\'s name. | 52 | | domain | Internet domain name associated with IP address range. | 53 | | usage_type | Usage type classification of ISP or company. | 54 | | asn | Autonomous system number (ASN). | 55 | | as_name | Autonomous system (AS) name. | 56 | | last_seen | Proxy last seen in days. | 57 | | threat | Security threat reported. | 58 | | proxy_type | Type of proxy. | 59 | | provider | Name of VPN provider if available. | 60 | | fraud_score | Potential risk score (0 - 99) associated with IP address. | 61 | ``` -------------------------------------------------------------------------------- /docs/source/conf.py: -------------------------------------------------------------------------------- 1 | # Configuration file for the Sphinx documentation builder. 2 | # Read https://www.sphinx-doc.org/en/master/usage/configuration.html for more options available 3 | 4 | # -- Project information 5 | 6 | project = 'IP2Proxy Python' 7 | copyright = '2024, IP2Location' 8 | author = 'IP2Location' 9 | 10 | release = '0.1.0' 11 | version = '0.1.0' 12 | 13 | # -- General configuration 14 | 15 | extensions = [ 16 | 'sphinx.ext.duration', 17 | 'sphinx.ext.doctest', 18 | 'myst_parser', 19 | 'sphinx_copybutton', 20 | ] 21 | 22 | # https://myst-parser.readthedocs.io/en/latest/syntax/optional.html 23 | 24 | myst_enable_extensions = [ 25 | "colon_fence", 26 | "deflist", 27 | "fieldlist", 28 | ] 29 | 30 | # https://myst-parser.readthedocs.io/en/latest/configuration.html#setting-html-metadata 31 | myst_html_meta = { 32 | "description": "IP2Proxy Python library enables user to query an IP address if it was being used as open proxy, web proxy, VPN anonymizer and TOR exits.", 33 | "keywords": "IP2Proxy, Proxy, IP location, Python", 34 | "google-site-verification": "DeW6mXDyMnMt4i61ZJBNuoADPimo5266DKob7Z7d6i4", 35 | } 36 | 37 | # templates_path = ['_templates'] 38 | 39 | # -- Options for HTML output 40 | 41 | html_theme = 'sphinx_book_theme' 42 | 43 | html_theme_options = { 44 | "use_edit_page_button": False, 45 | "use_source_button": False, 46 | "use_issues_button": False, 47 | "use_download_button": False, 48 | "use_sidenotes": False, 49 | } 50 | 51 | # The name of an image file (relative to this directory) to place at the top 52 | # of the sidebar. 53 | html_logo = 'images/ipl-logo-square-1200.png' 54 | 55 | # Favicon 56 | html_favicon = 'images/favicon.ico' 57 | 58 | html_title = "IP2Proxy Python" 59 | 60 | # html_baseurl = "https://ip2proxy-deno.readthedocs.io/en/latest/" -------------------------------------------------------------------------------- /docs/source/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ip2location/ip2proxy-python/e7a356fc37455edd71f879335895ac63fb7aee3c/docs/source/images/favicon.ico -------------------------------------------------------------------------------- /docs/source/images/ipl-logo-square-1200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ip2location/ip2proxy-python/e7a356fc37455edd71f879335895ac63fb7aee3c/docs/source/images/ipl-logo-square-1200.png -------------------------------------------------------------------------------- /docs/source/index.md: -------------------------------------------------------------------------------- 1 | # IP2Proxy Python Library 2 | 3 | ![PyPI](https://img.shields.io/pypi/v/IP2Proxy) 4 | ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/IP2Proxy) 5 | ![PyPI - Downloads](https://img.shields.io/pypi/dm/IP2Proxy) 6 | 7 | This library allows user to query an IP address if it was being used as VPN servers, open proxies, web proxies, Tor exit nodes, search engine robots, data center ranges, residential proxies, consumer privacy networks, and enterprise private networks. It lookup the proxy IP address from **IP2Proxy BIN Data** file. This data file can be downloaded at 8 | 9 | * Free IP2Proxy BIN Data: https://lite.ip2location.com 10 | * Commercial IP2Proxy BIN Data: https://www.ip2location.com/proxy-database 11 | 12 | For more details, please visit: 13 | [https://www.ip2location.com/ip2proxy/developers/python](https://www.ip2location.com/ip2proxy/developers/python) 14 | 15 | ## Table of contents 16 | ```{eval-rst} 17 | .. toctree:: 18 | 19 | self 20 | quickstart 21 | code 22 | ``` -------------------------------------------------------------------------------- /docs/source/quickstart.md: -------------------------------------------------------------------------------- 1 | # Quickstart 2 | 3 | ## Dependencies 4 | 5 | This library requires IP2Proxy BIN database to function. You may download the BIN database at 6 | 7 | - IP2Proxy LITE BIN Data (Free): 8 | - IP2Proxy Commercial BIN Data (Comprehensive): 9 | 10 | 11 | ## Installation 12 | 13 | ### PyPI Installation 14 | 15 | You can install IP2Proxy Python library from PyPI by using this command: 16 | 17 | ```bash 18 | pip install IP2Proxy 19 | ``` 20 | 21 | ### Arch Linux 22 | 23 | For Arch Linux user, you can install the module using the following command: 24 | ```Bash 25 | git clone https://aur.archlinux.org/ip2proxy-python.git && cd ip2proxy-python 26 | makepkg -si 27 | ``` 28 | 29 | ## Sample Codes 30 | 31 | ### Query geolocation information from BIN database 32 | 33 | You can query the geolocation information from the IP2Proxy BIN database as below: 34 | 35 | ```python 36 | import IP2Proxy 37 | 38 | db = IP2Proxy.IP2Proxy() 39 | 40 | # open IP2Proxy BIN database for proxy lookup 41 | db.open("IP2PROXY-IP-PROXYTYPE-COUNTRY-REGION-CITY-ISP-DOMAIN-USAGETYPE-ASN-LASTSEEN-THREAT-RESIDENTIAL.BIN") 42 | 43 | # get versioning information 44 | print ('Module Version: ' + db.get_module_version()) 45 | print ('Package Version: ' + db.get_package_version()) 46 | print ('Database Version: ' + db.get_database_version()) 47 | 48 | # individual proxy data check 49 | print ('Is Proxy: ' + str(db.is_proxy("4.0.0.47"))) 50 | print ('Proxy Type: ' + db.get_proxy_type("4.0.0.47")) 51 | print ('Country Code: ' + db.get_country_short("4.0.0.47")) 52 | print ('Country Name: ' + db.get_country_long("4.0.0.47")) 53 | print ('Region Name: ' + db.get_region("4.0.0.47")) 54 | print ('City Name: ' + db.get_city("4.0.0.47")) 55 | print ('ISP: ' + db.get_isp("4.0.0.47")) 56 | print ('Domain: ' + db.get_domain("4.0.0.47")) 57 | print ('Usage Type: ' + db.get_usage_type("4.0.0.47")) 58 | print ('ASN: ' + db.get_asn("4.0.0.47")) 59 | print ('AS Name: ' + db.get_as_name("4.0.0.47")) 60 | print ('Last Seen: ' + db.get_last_seen("4.0.0.47")) 61 | print ('Threat: ' + db.get_threat("4.0.0.47")) 62 | print ('Provider: ' + db.get_provider("4.0.0.47")) 63 | print ('Fraud Score: ' + db.get_fraud_score("4.0.0.47")) 64 | 65 | # single function to get all proxy data returned in array 66 | record = db.get_all("4.0.0.47") 67 | 68 | print ('Is Proxy: ' + str(record['is_proxy'])) 69 | print ('Proxy Type: ' + record['proxy_type']) 70 | print ('Country Code: ' + record['country_short']) 71 | print ('Country Name: ' + record['country_long']) 72 | print ('Region Name: ' + record['region']) 73 | print ('City Name: ' + record['city']) 74 | print ('ISP: ' + record['isp']) 75 | print ('Domain: ' + record['domain']) 76 | print ('Usage Type: ' + record['usage_type']) 77 | print ('ASN: ' + record['asn']) 78 | print ('AS Name: ' + record['as_name']) 79 | print ('Last Seen: ' + record['last_seen']) 80 | print ('Threat: ' + record['threat']) 81 | print ('Provider: ' + record['provider']) 82 | print ('Fraud Score: ' + record['fraud_score']) 83 | 84 | # close IP2Proxy BIN database 85 | db.close() 86 | ``` -------------------------------------------------------------------------------- /example.py: -------------------------------------------------------------------------------- 1 | import IP2Proxy, os 2 | 3 | db = IP2Proxy.IP2Proxy() 4 | 5 | # open IP2Proxy BIN database for proxy lookup 6 | db.open(os.path.join("data", "IP2PROXY-IP-PROXYTYPE-COUNTRY-REGION-CITY-ISP.SAMPLE.BIN")) 7 | 8 | # get versioning information 9 | print ('Module Version: ' + db.get_module_version()) 10 | print ('Package Version: ' + db.get_package_version()) 11 | print ('Database Version: ' + db.get_database_version()) 12 | 13 | # individual proxy data check 14 | print ('Is Proxy: ' + str(db.is_proxy("4.0.0.47"))) 15 | print ('Proxy Type: ' + db.get_proxy_type("4.0.0.47")) 16 | print ('Country Code: ' + db.get_country_short("4.0.0.47")) 17 | print ('Country Name: ' + db.get_country_long("4.0.0.47")) 18 | print ('Region Name: ' + db.get_region("4.0.0.47")) 19 | print ('City Name: ' + db.get_city("4.0.0.47")) 20 | print ('ISP: ' + db.get_isp("4.0.0.47")) 21 | print ('Domain: ' + db.get_domain("4.0.0.47")) 22 | print ('Usage Type: ' + db.get_usage_type("4.0.0.47")) 23 | print ('ASN: ' + db.get_asn("4.0.0.47")) 24 | print ('AS Name: ' + db.get_as_name("4.0.0.47")) 25 | print ('Last Seen: ' + db.get_last_seen("4.0.0.47")) 26 | print ('Threat: ' + db.get_threat("4.0.0.47")) 27 | print ('Provider: ' + db.get_provider("4.0.0.47")) 28 | print ('Fraud Score: ' + db.get_fraud_score("4.0.0.47")) 29 | 30 | # single function to get all proxy data returned in array 31 | record = db.get_all("4.0.0.47") 32 | 33 | print ('Is Proxy: ' + str(record['is_proxy'])) 34 | print ('Proxy Type: ' + record['proxy_type']) 35 | print ('Country Code: ' + record['country_short']) 36 | print ('Country Name: ' + record['country_long']) 37 | print ('Region Name: ' + record['region']) 38 | print ('City Name: ' + record['city']) 39 | print ('ISP: ' + record['isp']) 40 | print ('Domain: ' + record['domain']) 41 | print ('Usage Type: ' + record['usage_type']) 42 | print ('ASN: ' + record['asn']) 43 | print ('AS Name: ' + record['as_name']) 44 | print ('Last Seen: ' + record['last_seen']) 45 | print ('Threat: ' + record['threat']) 46 | print ('Provider: ' + record['provider']) 47 | print ('Fraud Score: ' + record['fraud_score']) 48 | 49 | # close IP2Proxy BIN database 50 | db.close() 51 | 52 | # Web Service 53 | ws = IP2Proxy.IP2ProxyWebService("demo","PX11",True) 54 | rec = ws.lookup("8.8.8.8") 55 | print (rec) 56 | print ("\n") 57 | print ("Credit Remaining: {}\n".format(ws.getcredit())) -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import setuptools 2 | 3 | with open("README.md", "r") as fh: 4 | long_description = fh.read() 5 | 6 | setuptools.setup( 7 | name="IP2Proxy", 8 | version="3.5.1", 9 | author="IP2Location", 10 | author_email="support@ip2location.com", 11 | description="Python API for IP2Proxy database. It can be used to query an IP address if it was being used as open proxy, web proxy, VPN anonymizer and TOR exits.", 12 | long_description=long_description, 13 | long_description_content_type="text/markdown", 14 | py_modules=['IP2Proxy'], 15 | url="https://github.com/ip2location/ip2proxy-python", 16 | packages=setuptools.find_packages(), 17 | tests_require=['pytest>=3.0.6'], 18 | classifiers=( 19 | "Development Status :: 5 - Production/Stable", 20 | "Intended Audience :: Developers", 21 | "Topic :: Software Development :: Libraries :: Python Modules", 22 | "Programming Language :: Python :: 2.7", 23 | "Programming Language :: Python :: 3.5", 24 | "Programming Language :: Python :: 3.6", 25 | "Programming Language :: Python :: 3.7", 26 | "Programming Language :: Python :: 3.8", 27 | "Programming Language :: Python :: 3.9", 28 | "Programming Language :: Python :: 3.10", 29 | "Programming Language :: Python :: 3.11", 30 | "Programming Language :: Python :: 3.12", 31 | "Programming Language :: Python :: 3.13", 32 | "Programming Language :: Python :: Implementation :: CPython", 33 | "Programming Language :: Python :: Implementation :: PyPy", 34 | "License :: OSI Approved :: MIT License", 35 | "Operating System :: OS Independent", 36 | ), 37 | ) 38 | -------------------------------------------------------------------------------- /tests/test_database.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import pytest 4 | 5 | import os, sys, IP2Proxy 6 | 7 | db = IP2Proxy.IP2Proxy() 8 | 9 | def testinvaliddatabase(): 10 | try: 11 | db.open(os.path.join("data", "PX10.SAMPLE.BIN")) 12 | except ValueError as e: 13 | assert "The database file does not seem to exist." == str(e) 14 | 15 | def testfunctionexist(): 16 | errors = [] 17 | functions_list = ['open', 'close', 'get_module_version', 'get_package_version', 'get_database_version', 'get_all', 'is_proxy', 'get_proxy_type', 'get_country_short', 'get_country_long', 'get_region', 'get_city', 'get_isp', 'get_domain', 'get_usage_type', 'get_asn', 'get_as_name', 'get_last_seen', 'get_threat'] 18 | for x in range(len(functions_list)): 19 | # assert hasattr(db, functions_list[x]) == True, "Function did not exist." 20 | if (hasattr(db, functions_list[x]) == False): 21 | errors.append("Function " + functions_list[x] + " did not exist.") 22 | # assert no error message has been registered, else print messages 23 | assert not errors, "errors occured:\n{}".format("\n".join(errors)) 24 | 25 | def testinvalidip(): 26 | db.open(os.path.join("data", "PX10.SAMPLE.BIN")) 27 | rec = db.get_all("1.0.0.x") 28 | assert rec['country_short'] == "INVALID IP ADDRESS" 29 | 30 | def testipv4countrycode(): 31 | db.open(os.path.join("data", "PX10.SAMPLE.BIN")) 32 | rec = db.get_all("1.0.0.8") 33 | assert rec['country_short'] == "US", "Test failed because country code not same." 34 | 35 | def testipv4countryname(): 36 | db.open(os.path.join("data", "PX10.SAMPLE.BIN")) 37 | rec = db.get_all("1.0.0.8") 38 | assert rec['country_long'] == "United States of America", "Test failed because country name not same." 39 | 40 | def testgetcountryshort(): 41 | db.open(os.path.join("data", "PX10.SAMPLE.BIN")) 42 | rec = db.get_country_short("1.0.0.8") 43 | assert rec == "US", "Test failed because country code not same." 44 | 45 | def testgetcountrylong(): 46 | db.open(os.path.join("data", "PX10.SAMPLE.BIN")) 47 | rec = db.get_country_long("1.0.0.8") 48 | assert rec == "United States of America", "Test failed because country name not same." 49 | 50 | def testgetregion(): 51 | db.open(os.path.join("data", "PX10.SAMPLE.BIN")) 52 | rec = db.get_region("1.0.0.8") 53 | assert rec == "California" 54 | 55 | def testgetcity(): 56 | db.open(os.path.join("data", "PX10.SAMPLE.BIN")) 57 | rec = db.get_city("1.0.0.8") 58 | assert rec == "Los Angeles" 59 | 60 | def testgetisp(): 61 | db.open(os.path.join("data", "PX10.SAMPLE.BIN")) 62 | rec = db.get_isp("1.0.0.8") 63 | assert rec == "APNIC and CloudFlare DNS Resolver Project" 64 | 65 | def testgetdomain(): 66 | db.open(os.path.join("data", "PX10.SAMPLE.BIN")) 67 | rec = db.get_domain("1.0.0.8") 68 | assert rec == "cloudflare.com" 69 | 70 | def testgetusagetype(): 71 | db.open(os.path.join("data", "PX10.SAMPLE.BIN")) 72 | rec = db.get_usage_type("1.0.0.8") 73 | assert rec == "CDN" 74 | 75 | def testgetasn(): 76 | db.open(os.path.join("data", "PX10.SAMPLE.BIN")) 77 | rec = db.get_asn("1.0.0.8") 78 | assert rec == "13335" 79 | 80 | def testgetasname(): 81 | db.open(os.path.join("data", "PX10.SAMPLE.BIN")) 82 | rec = db.get_as_name("1.0.0.8") 83 | assert rec == "CLOUDFLARENET" 84 | 85 | def testgetlastseen(): 86 | db.open(os.path.join("data", "PX10.SAMPLE.BIN")) 87 | rec = db.get_last_seen("1.0.0.8") 88 | assert rec == "22" 89 | 90 | def testgetthreat(): 91 | db.open(os.path.join("data", "PX10.SAMPLE.BIN")) 92 | rec = db.get_threat("1.0.0.8") 93 | assert rec == "-" 94 | 95 | def testisproxy(): 96 | db.open(os.path.join("data", "PX10.SAMPLE.BIN")) 97 | rec = db.is_proxy("1.0.0.8") 98 | assert rec == 2 99 | 100 | def testgetproxytype(): 101 | db.open(os.path.join("data", "PX10.SAMPLE.BIN")) 102 | rec = db.get_proxy_type("1.0.0.8") 103 | assert rec == "DCH" 104 | 105 | def testipv6countrycode(): 106 | db.open(os.path.join("data", "PX10.SAMPLE.BIN")) 107 | rec = db.get_all("2c0f:ffa0::4") 108 | assert rec['country_short'] == "UG", "Test failed because country code not same." 109 | 110 | def testipv6countryname(): 111 | db.open(os.path.join("data", "PX10.SAMPLE.BIN")) 112 | rec = db.get_all("2c0f:ffa0::4") 113 | assert rec['country_long'] == "Uganda", "Test failed because country name not same." 114 | 115 | def testgetmoduleversion(): 116 | db.open(os.path.join("data", "PX10.SAMPLE.BIN")) 117 | assert db.get_module_version() == "3.1.2" 118 | 119 | def testgetpackageversion(): 120 | db.open(os.path.join("data", "PX10.SAMPLE.BIN")) 121 | assert db.get_package_version() == "10" 122 | 123 | def testgetdatabaseversion(): 124 | db.open(os.path.join("data", "PX10.SAMPLE.BIN")) 125 | assert db.get_database_version() == "2020.10.23" -------------------------------------------------------------------------------- /tests/test_webservice.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import pytest 4 | 5 | import IP2Proxy 6 | 7 | apikey = "demo" 8 | package = "PX11" 9 | usessl = True 10 | 11 | ws = IP2Proxy.IP2ProxyWebService(apikey,package,usessl) 12 | 13 | def testcountrycode(): 14 | # ws = IP2Proxy.IP2ProxyWebService(apikey,package,usessl) 15 | rec = ws.lookup("8.8.8.8") 16 | assert rec['country_code'] == "US", "Test failed because country code not same." 17 | 18 | def testgetcredit(): 19 | credit = ws.getcredit() 20 | assert str(credit).isdigit() == True, "Test failed because it is no a digit value." 21 | 22 | def testfunctionexist(): 23 | functions_list = ['lookup', 'getcredit'] 24 | for x in range(len(functions_list)): 25 | assert hasattr(ws, functions_list[x]) == True, "Function did not exist." --------------------------------------------------------------------------------