├── LICENSE ├── README.md ├── leakcheck ├── leakcheck.py └── setup.py /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018-2024 LeakCheck Security Services LTD 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LeakCheck API Python Wrapper v2.0.0 2 | 3 | This Python wrapper allows you to interact with the LeakCheck API for checking leaked data using the official API. It includes support for both the private (authenticated) API and the public (unauthenticated) API endpoints. This wrapper has been updated to work with API v2. 4 |

5 | Discord 6 | PyPI - Downloads 7 | PyPI 8 | Uptime Robot ratio (30 days) 9 | GitHub 10 |

11 | 12 | ## Features 13 | 14 | - Lookup email addresses, usernames, and other identifiers against leaked databases. 15 | - Supports both the **private API v2** (authenticated via API key) and the **public API**. 16 | - HTTP/SOCKS proxy support. 17 | - Customizable request limits and offsets for paginated queries. 18 | 19 | ## Installation 20 | 21 | You can install the wrapper using `pip`: 22 | 23 | ```bash 24 | pip install leakcheck 25 | ``` 26 | 27 | ## Usage 28 | 29 | ### Private API (Authenticated) - `LeakCheckAPI_v2` 30 | 31 | To use the private API, you need an API key from LeakCheck. You can pass the API key directly or set it via an environment variable. 32 | 33 | #### Example: 34 | 35 | ```python 36 | from leakcheck import LeakCheckAPI_v2 37 | 38 | # Initialize with API key (or set LEAKCHECK_APIKEY in environment variables) 39 | api = LeakCheckAPI_v2(api_key='your_api_key_here') 40 | 41 | # Perform a lookup 42 | result = api.lookup(query="example@example.com", query_type="email", limit=100) 43 | 44 | print(result) 45 | ``` 46 | 47 | #### Environment Variables 48 | 49 | You can set the following environment variables for better flexibility: 50 | - `LEAKCHECK_APIKEY`: Your API key for authentication (must be at least 40 characters long). 51 | - `LEAKCHECK_PROXY`: Optional, to route your requests through a proxy. 52 | 53 | #### Parameters for `lookup()`: 54 | 55 | - `query`: The identifier to look up (email, username, etc.). 56 | - `query_type`: (Optional) Specify the type of query (e.g., "email", "username"). If not provided, it will be auto-detected. 57 | - `limit`: (Optional) Limit the number of results (maximum 1000, default is 100). 58 | - `offset`: (Optional) Offset for the results (maximum 2500, default is 0). 59 | 60 | #### Error Handling 61 | 62 | - If the API key is invalid or not provided, an error will be raised. 63 | - The method checks for valid `limit` and `offset` parameters. 64 | - Handles exceptions related to network or request issues. 65 | 66 | ### Public API (Unauthenticated) - `LeakCheckAPI_Public` 67 | 68 | The public API does not require authentication but offers limited access. You can use this for simple email or username queries. 69 | 70 | #### Example: 71 | 72 | ```python 73 | from leakcheck import LeakCheckAPI_Public 74 | 75 | # Initialize without an API key 76 | public_api = LeakCheckAPI_Public() 77 | 78 | # Perform a public lookup 79 | result = public_api.lookup(query="example@example.com") 80 | 81 | print(result) 82 | ``` 83 | 84 | #### Parameters for `lookup()`: 85 | 86 | - `query`: The identifier to look up (email, email hash, or username). 87 | 88 | ### Proxy Support 89 | 90 | Both the private and public API wrappers support proxy configurations. You can set the proxy by calling `set_proxy()`: 91 | 92 | ```python 93 | # Set proxy for private API 94 | api.set_proxy("http://proxy.example.com:8080") 95 | 96 | # Set proxy for public API 97 | public_api.set_proxy("http://proxy.example.com:8080") 98 | ``` 99 | 100 | ## CLI Usage 101 | 102 | This package also includes a command-line interface (CLI) tool for querying the LeakCheck API directly from your terminal. 103 | 104 | ### Example CLI Usage: 105 | 106 | ```bash 107 | leakcheck "example@example.com" --type email --limit 50 --api-key your_api_key_here 108 | ``` 109 | 110 | #### CLI Help Menu 111 | 112 | ```bash 113 | usage: leakcheck [-h] [--type TYPE] [--limit LIMIT] [--offset OFFSET] [--public] [--api-key API_KEY] [--proxy PROXY] [--pretty] query 114 | 115 | LeakCheck CLI Tool 116 | 117 | positional arguments: 118 | query The value to search for (email, username, etc.) 119 | 120 | options: 121 | -h, --help show this help message and exit 122 | --type TYPE, -t TYPE Type of query (email, username, etc.). Will be auto-detected if not provided. 123 | --limit LIMIT, -l LIMIT 124 | Limit the number of results (max 1000, default 100) 125 | --offset OFFSET, -o OFFSET 126 | Offset the results (max 2500, default 0) 127 | --public, -p Use the public API instead of the authenticated API. 128 | --api-key API_KEY API key to authenticate with the LeakCheck service. If not provided, will attempt to read from environment variable. 129 | --proxy PROXY Optional proxy to use for the requests (HTTP, HTTPS, SOCKS5 supported). If not provided, will attempt to read from environment variable. 130 | --pretty Display prettified JSON output instead of a table. 131 | ``` 132 | 133 | ## Accepted Data Types for Lookup Queries 134 | 135 | The **LeakCheck API v2** accepts the following data types for lookups. Some data types can be automatically detected, while others must be explicitly specified. 136 | 137 | | **Query Type** | **Sample** | **Notes** | 138 | |----------------|--------------------------------------------|--------------------------------------------------------------------------------------------| 139 | | **auto** | `example@example.com`, `example`, `12345678`, `31c5543c1734d25c7206f5fd` | Automatically detects email, username, phone number, and hash. Other types must be explicit.| 140 | | **email** | `example@example.com` | | 141 | | **domain** | `gmail.com` | | 142 | | **keyword** | `example` | | 143 | | **username** | `example` | | 144 | | **phone** | `12063428631` | | 145 | | **hash** | `31c5543c1734d25c7206f5fd` | SHA256 hash of lower-cased email, can be truncated to 24 characters. | 146 | | **phash** | `31c5543c1734d25c7206f5fd` | SHA256 hash of password, can be truncated to 24 characters (Enterprise only). | 147 | | **origin** | `example.com` | For Enterprise accounts only. | 148 | | **password** | `example` | For Enterprise accounts only. | 149 | 150 | ### Example Queries: 151 | 152 | ```python 153 | # Auto-detect type 154 | result = api.lookup(query="example@example.com") 155 | 156 | # Lookup by email 157 | result = api.lookup(query="example@example.com", query_type="email") 158 | 159 | # Lookup by domain 160 | result = api.lookup(query="gmail.com", query_type="domain") 161 | 162 | # Lookup by phone 163 | result = api.lookup(query="12063428631", query_type="phone") 164 | 165 | # Lookup by SHA256 hash 166 | result = api.lookup(query="31c5543c1734d25c7206f5fd", query_type="hash") 167 | ``` 168 | 169 | ### Auto-Detection of Query Types 170 | 171 | If the `query_type` parameter is not provided, the API will attempt to auto-detect the type of query based on the input format. For instance, if the query looks like an email, the API will treat it as such. 172 | 173 | ## Error Handling and Returned Errors 174 | 175 | The **LeakCheck API v2** provides detailed error messages in case something goes wrong with your query. These error messages are based on specific conditions. Below are common error codes and their corresponding descriptions: 176 | 177 | | **Error Code** | **Description** | **Notes** | 178 | |----------------|---------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------| 179 | | **401** | Missing X-API-Key | No API key provided in the request header. | 180 | | **400** | Invalid X-API-Key | The API key provided is invalid. | 181 | | **400** | Invalid type | The `query_type` parameter is not valid. | 182 | | **400** | Invalid email | The email format is incorrect. | 183 | | **400** | Invalid query | The query format is invalid. | 184 | | **400** | Invalid domain | The domain format is invalid. | 185 | | **400** | Too short query (< 3 characters) | The query must be at least 3 characters long. | 186 | | **400** | Invalid characters in query | The query contains invalid characters. | 187 | | **429** | Too many requests | You have exceeded the rate limit. | 188 | | **403** | Active plan required | A paid plan is required to make this request. | 189 | | **403** | Limit reached | You have reached your plan’s usage limit. | 190 | | **422** | Could not determine search type automatically | The system was unable to automatically detect the query type, requiring an explicit type. | 191 | 192 | ### Example of Error Handling in Code: 193 | 194 | ```python 195 | try: 196 | result = api.lookup(query="example@example.com", query_type="email", limit=100) 197 | print(result) 198 | except ValueError as e: 199 | print(f"An error occurred: {str(e)}") 200 | ``` 201 | 202 | The `lookup()` function raises a `ValueError` when the API returns an error. This makes it easy to handle and debug any issues that arise from invalid requests or API responses. 203 | 204 | ## API Endpoints 205 | 206 | - **Private API Base URL (v2):** `https://leakcheck.io/api/v2` 207 | - **Public API Base URL:** `https://leakcheck.io/api/public` 208 | 209 | ## Version 210 | 211 | This wrapper supports **LeakCheck API v2**. 212 | 213 | ## License 214 | 215 | This project is licensed under the MIT License. 216 | 217 | ## Sponsors 218 | 219 |

220 | 221 | Aeza Hosting 222 | 223 |

Aeza Hosting - For providing powerful dedicated servers

224 |

225 | -------------------------------------------------------------------------------- /leakcheck: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ 3 | Copyright (c) 2018-2024 LeakCheck Security Services LTD 4 | Licensed under MIT license 5 | Github: https://github.com/LeakCheck/leakcheck-api 6 | Created with <3 7 | """ 8 | 9 | import argparse 10 | import sys 11 | import os 12 | import json 13 | from leakcheck import LeakCheckAPI_v2, LeakCheckAPI_Public 14 | from tabulate import tabulate 15 | 16 | version = "2.0.0" 17 | 18 | def main(): 19 | parser = argparse.ArgumentParser(description="LeakCheck CLI Tool") 20 | parser.add_argument("query", help="The value to search for (email, username, etc.)") 21 | parser.add_argument("--type", "-t", help="Type of query (email, username, etc.). Will be auto-detected if not provided.") 22 | parser.add_argument("--limit", "-l", type=int, default=100, help="Limit the number of results (max 1000, default 100)") 23 | parser.add_argument("--offset", "-o", type=int, default=0, help="Offset the results (max 2500, default 0)") 24 | parser.add_argument("--public", "-p", action="store_true", help="Use the public API instead of the authenticated API.") 25 | parser.add_argument("--api-key", help="API key to authenticate with the LeakCheck service. If not provided, will attempt to read from environment variable.") 26 | parser.add_argument("--proxy", help="Optional proxy to use for the requests (HTTP, HTTPS, SOCKS5 supported). If not provided, will attempt to read from environment variable.") 27 | parser.add_argument("--pretty", action="store_true", help="Display prettified JSON output instead of a table.") 28 | 29 | args = parser.parse_args() 30 | 31 | # Load API key from environment variable if not provided as argument 32 | api_key = args.api_key or os.getenv("LEAKCHECK_APIKEY") 33 | 34 | # Check if public API or private API should be used 35 | if args.public: 36 | api = LeakCheckAPI_Public() 37 | else: 38 | try: 39 | api = LeakCheckAPI_v2(api_key=api_key) 40 | except ValueError as e: 41 | print(f"Error: {str(e)}") 42 | sys.exit(1) 43 | 44 | # Set proxy if provided or from environment variable 45 | proxy = args.proxy or os.getenv("LEAKCHECK_PROXY") 46 | if proxy: 47 | api.set_proxy(proxy) 48 | 49 | # Perform the lookup query 50 | try: 51 | if args.public: 52 | # For public API, only the query is needed 53 | result = api.lookup(args.query) 54 | else: 55 | # For authenticated API, more parameters can be provided 56 | result = api.lookup(query=args.query, query_type=args.type, limit=args.limit, offset=args.offset) 57 | except ValueError as e: 58 | print(f"Error: {str(e)}") 59 | sys.exit(1) 60 | 61 | # Print the results 62 | if result: 63 | if args.public and isinstance(result, dict) and result.get("success"): 64 | if not args.pretty and "fields" in result and result["fields"]: 65 | print(f"Sensitive data found: {', '.join(result['fields'])}") 66 | if "sources" in result and isinstance(result["sources"], list) and len(result["sources"]) > 0: 67 | if args.pretty: 68 | print(json.dumps(result, indent=4)) 69 | else: 70 | headers = ["name", "date"] 71 | rows = [[source.get("name", "N/A"), source.get("date", "N/A")] for source in result["sources"]] 72 | print(tabulate(rows, headers=headers, tablefmt="grid")) 73 | else: 74 | print("No results found.") 75 | elif isinstance(result, list) and len(result) > 0: 76 | if args.pretty: 77 | print(json.dumps(result, indent=4)) 78 | else: 79 | headers = list(result[0].keys()) 80 | headers.remove("fields") 81 | rows = [] 82 | for item in result: 83 | source_name = item["source"]["name"] if isinstance(item["source"], dict) else item["source"] 84 | rows.append([source_name if key == 'source' else item.get(key, "N/A") for key in headers]) 85 | # Append extra fields if available 86 | extra_fields = item.get('fields') 87 | if extra_fields and isinstance(extra_fields, list): 88 | for field in extra_fields: 89 | if field not in headers: 90 | headers.append(field) 91 | rows[-1].append(item.get(field, "N/A")) 92 | print(tabulate(rows, headers=headers, tablefmt="grid")) 93 | else: 94 | print("No results found.") 95 | else: 96 | print("No results found.") 97 | 98 | if __name__ == "__main__": 99 | main() -------------------------------------------------------------------------------- /leakcheck.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2018-2024 LeakCheck Security Services LTD 3 | Licensed under MIT license 4 | Github: https://github.com/LeakCheck/leakcheck-api 5 | Created with <3 6 | """ 7 | import requests 8 | import json 9 | import os 10 | import sys 11 | import platform 12 | 13 | version = "2.0.0" 14 | 15 | class LeakCheckAPI_v2: 16 | def __init__(self, api_key=None, base_url='https://leakcheck.io/api/v2'): # Updated base URL for V2 17 | # Load API key and proxy from configuration file in the home directory 18 | self.api_key = os.getenv('LEAKCHECK_APIKEY') or api_key 19 | self.proxy = os.getenv('LEAKCHECK_PROXY') 20 | 21 | if not self.api_key or len(self.api_key) < 40: 22 | raise ValueError("API key is missing, empty, or invalid (must be at least 40 characters long) in the configuration file or provided parameter.") 23 | 24 | self.base_url = base_url 25 | self.session = requests.Session() 26 | self.session.headers.update({ 27 | 'X-API-Key': self.api_key, # API key is now required in the header 28 | "User-Agent": "PyLCAPI/{}, Python {} on {}".format(version, sys.version.split(" ")[0], platform.version()) 29 | }) 30 | # Set proxy if provided 31 | if self.proxy: 32 | self.set_proxy(self.proxy) 33 | 34 | def set_proxy(self, proxy): 35 | """ 36 | Set a proxy for the session. 37 | 38 | :param proxy: Proxy URL (can be HTTP, HTTPS, or SOCKS5). 39 | """ 40 | self.session.proxies.update({'http': proxy, 'https': proxy}) 41 | 42 | def lookup(self, query, query_type=None, limit=100, offset=0): 43 | """ 44 | Perform a lookup query. 45 | 46 | :param query: The main value to search (email, username, etc.). 47 | :param query_type: Type of query ('email', 'username', etc.). If missing, it will be detected automatically. 48 | :param limit: Limit number of results (maximum 1000). 49 | :param offset: Offset for the results (maximum 2500). 50 | :return: Parsed result from API. 51 | """ 52 | if limit > 1000: 53 | raise ValueError("Limit cannot be greater than 1000.") 54 | if offset > 2500: 55 | raise ValueError("Offset cannot be greater than 2500.") 56 | 57 | endpoint = f"{self.base_url}/query/{query}" 58 | params = { 59 | 'limit': limit, 60 | 'offset': offset 61 | } 62 | # Adding optional parameters if provided 63 | if query_type: 64 | params['type'] = query_type 65 | 66 | try: 67 | response = self.session.get(endpoint, params=params) 68 | except requests.exceptions.RequestException as e: 69 | # Handle any request-related exceptions, including client and server errors 70 | raise ValueError(f"API responded with an error: {str(e)}") from e 71 | 72 | result = response.json() 73 | if not result.get('success', False): 74 | raise ValueError(f"API responded with an error: {result.get('error', 'Unknown error')}") 75 | 76 | return result.get('result') 77 | 78 | class LeakCheckAPI_Public: 79 | def __init__(self, base_url='https://leakcheck.io/api/public'): # Base URL for the public API 80 | self.base_url = base_url 81 | self.session = requests.Session() 82 | self.session.headers.update({ 83 | "User-Agent": "PyLCAPI/{}, Python {} on {}".format(version, sys.version.split(" ")[0], platform.version()) 84 | }) 85 | # Set proxy if provided 86 | self.proxy = None 87 | 88 | def set_proxy(self, proxy): 89 | """ 90 | Set a proxy for the session. 91 | 92 | :param proxy: Proxy URL (can be HTTP, HTTPS, or SOCKS5). 93 | """ 94 | self.session.proxies.update({'http': proxy, 'https': proxy}) 95 | self.proxy = proxy 96 | 97 | def lookup(self, query): 98 | """ 99 | Perform a public lookup query. 100 | 101 | :param query: The main value to search (email, email hash, or username). 102 | :return: Parsed result from API. 103 | """ 104 | try: 105 | endpoint = f"{self.base_url}?check={query}" 106 | response = self.session.get(endpoint) 107 | except requests.exceptions.RequestException as e: 108 | # Handle any request-related exceptions, including client and server errors 109 | raise ValueError(f"API responded with an error: {str(e)}") from e 110 | 111 | result = response.json() 112 | if not result.get('success', False): 113 | raise ValueError(f"API responded with an error: {result.get('error', 'Unknown error')}") 114 | 115 | return result -------------------------------------------------------------------------------- /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="leakcheck", 8 | version="2.0.0", 9 | py_modules = ('leakcheck',), 10 | scripts=['leakcheck'], 11 | author="LeakCheck", 12 | author_email="the@leakcheck.net", 13 | description="Python wrapper for LeakCheck API & also a CLI tool", 14 | long_description=long_description, 15 | long_description_content_type="text/markdown", 16 | url="https://github.com/LeakCheck/leakcheck-api", 17 | install_requires=[ 18 | 'requests', 19 | 'pysocks', 20 | 'tabulate' 21 | ], 22 | classifiers=[ 23 | "Programming Language :: Python :: 3", 24 | "License :: OSI Approved :: MIT License", 25 | "Operating System :: OS Independent", 26 | ], 27 | python_requires='>=3.5', 28 | ) 29 | --------------------------------------------------------------------------------