unmaskip
IP lookup with proxy, VPN, Tor and hosting detection, powered by checkip.me.
- Geolocation, ASN, ISP, connection type (Residential / Business / Wireless / Hosting)
- Detects proxy, VPN, Tor, hosting/datacenter, compromised hosts and scrapers
- Risk score from 0 to 100
- No API key, zero dependencies, fully typed
- Built-in cache and automatic retry on rate limits
- Command-line tool included
Install
pip install unmaskip
Requires Python 3.9+.
Quick start
import unmaskip
info = unmaskip.lookup("8.8.8.8")
print(info.country, info.city, info.isp) # United States Mountain View Google LLC
print(info.type) # Business
print(info.risk) # 0-100
if info.is_vpn or info.is_proxy or info.is_tor:
print("Masked connection")
# One-liners
unmaskip.is_vpn("1.2.3.4")
unmaskip.is_proxy("1.2.3.4")
unmaskip.is_tor("1.2.3.4")
unmaskip.is_hosting("1.2.3.4")
unmaskip.risk("1.2.3.4")
# Your own IP
unmaskip.my_ip()
unmaskip.lookup()
Example: block anonymous sign-ups
import unmaskip
def is_suspicious(ip: str) -> bool:
info = unmaskip.lookup(ip)
return info.is_masked or info.is_hosting or (info.risk or 0) >= 80
The IPInfo object
| Field | Type | Description |
|---|---|---|
ip |
str |
The IP address |
hostname |
str |
Reverse DNS |
asn, isp, organisation |
str |
Network owner |
type |
str |
Residential, Business, Wireless or Hosting |
range |
str |
Network range (CIDR) |
continent, country, country_code |
str |
Location |
region, region_code |
str |
Location |
city, postal_code |
str |
Location |
latitude, longitude |
float |
Coordinates |
timezone, currency |
str |
Time zone and local currency |
proxy, vpn, tor, hosting |
bool |
Detections |
compromised, scraper, anonymous |
bool |
Detections |
risk |
int |
Risk score, 0 (clean) to 100 (very risky) |
operator |
str |
VPN/proxy operator, when known |
raw |
dict |
Full JSON response |
Every str, int and float field except ip is None when the value is unknown.
Helpers: is_proxy, is_vpn, is_tor, is_hosting, is_anonymous, and
is_masked (proxy or VPN or Tor). to_dict() returns a plain dict.
Client options
from unmaskip import Client
client = Client(
timeout=10.0, # seconds per request
cache_ttl=3600, # cache results for 1 hour (0 disables the cache)
cache_size=1024, # max cached IPs
max_retries=2, # retries on HTTP 429
max_retry_wait=60, # never sleep longer than this; raise instead
)
info = client.lookup("1.1.1.1")
The module-level functions (unmaskip.lookup, unmaskip.is_vpn, ...) share one
default client, so their results are cached too.
Rate limits
The free API allows 120 lookups of other IPs per hour per client; looking
up your own IP is unlimited and cached IPs do not count. When the limit is hit,
unmaskip waits for Retry-After and retries. If the wait is too long, it raises
unmaskip.RateLimitError, whose retry_after attribute tells you how long to wait.
Errors
All errors inherit from unmaskip.UnmaskIPError:
| Exception | When |
|---|---|
InvalidIPError |
Not a valid IPv4/IPv6 address (raised before any request) |
PrivateIPError |
Private or reserved address such as 10.0.0.1 or 127.0.0.1 |
RateLimitError |
HTTP 429 and the retry budget is used up |
NetworkError |
DNS failure, timeout, connection refused, ... |
APIError |
Any other unexpected response |
InvalidIPError and PrivateIPError are also ValueErrors.
Command line
unmaskip # your own IP
unmaskip 8.8.8.8 1.1.1.1 # several IPs
unmaskip 8.8.8.8 --json # raw JSON
unmaskip 8.8.8.8 -f vpn # one field: true / false
unmaskip 8.8.8.8 -f country # United States
unmaskip 1.2.3.4 --strict # exit code 3 if proxy / VPN / Tor / hosting
$ unmaskip 8.8.8.8
IP 8.8.8.8
Hostname dns.google
ASN AS15169
ISP Google LLC
Organisation Level 3
Type Business
Range 8.8.8.0/24
Location Mountain View, California, United States
Timezone America/Los_Angeles
Proxy no
VPN no
Tor no
Hosting no
Anonymous yes
Compromised no
Scraper no
Risk 100/100
Exit codes: 0 success, 1 lookup error, 2 bad arguments, 3 flagged IP (with --strict).
python -m unmaskip works too.
Privacy
unmaskip sends the IP addresses you look up to the checkip.me API over HTTPS,
together with a User-Agent header (unmaskip/<version>). Nothing else is
collected or sent. Results are cached only in your process memory.
Links
- API docs: https://checkip.me/api
- Website: https://checkip.me
License
MIT
Metadata
Release files for unmaskip 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| unmaskip-0.1.1.tar.gz | 13.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| unmaskip-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 26.5 kB
Release files / unmaskip-0.1.1.tar.gz
| Download URL | unmaskip-0.1.1.tar.gz |
|---|---|
| Size | 13.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
376856f3b4bb35641e576255bfc010be7f48a211c3e3d519cfce04466975ed6e
|
|
BLAKE2b-256 checksum How to use checksums |
024c74fccd545be8c44bce1f6e1d20f3cb6a46d2fb5d23d4e57e243dab396dab
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.7
|
Release files / unmaskip-0.1.1-py3-none-any.whl
| Download URL | unmaskip-0.1.1-py3-none-any.whl |
|---|---|
| Size | 13.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a11f9a5218003cde848833ffab7eb77f6259dddc2b3542d0e595388849f44a49
|
|
BLAKE2b-256 checksum How to use checksums |
357f8d57b8be0a48290630331c891fe7832d3dd67505086b363a8440cddf496e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.7
|