Skip to main content

Batch IP address enrichment for research: rate-limit aware, cached, reproducible, and useful without API keys

Project description

Know Your IP

PyPI version CI Downloads

Turn a list of IP addresses into a table you can analyse.

Built for research: hand it ten thousand addresses and it stays inside every API's rate limit, never pays for the same lookup twice, doesn't lose a row when a service goes down, and records enough about the run that you can defend the numbers in a paper months later.

It does something useful before you sign up for anything.

Thirty seconds, no account needed

import know_your_ip as kyi

result = kyi.enrich(["8.8.8.8", "1.1.1.1"], providers=["network", "rdap"])

for row in result:
    print(row["ip"], row["rdap.name"], row["network.reverse_dns"])
8.8.8.8 GOGL dns.google
1.1.1.1 APNIC-LABS one.one.one.one

That is who the address is registered to, and what it calls itself — with no API key, no database download, and no account. Add keys later for reputation and exposure data.

Why not just call the APIs yourself?

You can. Thirty lines of requests gets you the first hundred addresses. It's the next ten thousand that hurt, and these are the four things you end up building:

Your loop will hit rate limits. VirusTotal's free tier is four requests a minute. Here, requests are paced per provider from published limits — six concurrent lookups on that tier finish in thirty seconds with zero rate errors, so raising concurrency is safe rather than counterproductive.

Re-running will cost you a day. VirusTotal allows 500 lookups daily, so a 5,000-address study is a ten-day job you can't repeat after a reviewer asks a question. Results cache to disk; the second run costs nothing.

One bad service will cost you rows. A timeout mid-loop loses everything after it. Here a failing provider becomes a value in that row, not an exception — malformed addresses are skipped, not fatal, and identical failures are reported once rather than ten thousand times.

You'll be asked where the numbers came from. Every run produces a manifest: package version, which providers ran, a fingerprint of the settings, cache hits, and per-provider error counts.

And one thing you probably wouldn't build: because results are appended rather than overwritten, enriching the same list monthly leaves you with a panel dataset as a side effect.

What you can find out

Organised by the question, not by the vendor.

Question Where it comes from Needs an account?
Is this address even routable? Offline classification — private, loopback, CGNAT, reserved No
What does it call itself? Reverse DNS No
Who is it registered to, and who do I report abuse to? RDAP, the registry system that replaced WHOIS No
Where is it? MaxMind GeoLite2 · Censys Free database · free tier
Has it been reported for abuse? AbuseIPDB · VirusTotal Free tiers
What is it running, and what's exposed? Censys · Shodan Free tier · paid
Is it a VPN, proxy, or datacenter? APIVoid · AbuseIPDB usage type Paid · free
How does the network reach it? ping, traceroute No

Knowing what isn't routable matters more than it sounds: real address data is full of RFC1918, and spending metered quota to be told 192.168.1.1 is private is waste.

Working with batches

import know_your_ip as kyi

result = kyi.enrich_csv(
    "addresses.csv",
    "enriched.csv",
    column="ip",
    cache="cache.sqlite",  # second run costs no quota
    max_workers=10,  # safe: pacing is per provider
)

print(f"{len(result)} rows, errors: {result.errors}")

Or from the shell:

know_your_ip --file addresses.csv --cache cache.sqlite -o enriched.csv
know_your_ip --list-providers      # what's registered and what each costs

Into pandas, if you'd rather:

import know_your_ip as kyi

df = kyi.enrich(["8.8.8.8"], providers=["network"]).to_dataframe()

Reproducibility

Every run describes itself:

import json

import know_your_ip as kyi

result = kyi.enrich(["8.8.8.8"], providers=["network"])
print(json.dumps(result.manifest, indent=2)[:200])

Save it next to your results and the table can be regenerated and defended. API keys are deliberately excluded from the fingerprint, so the manifest is safe to publish.

Asking about the past is honest about what it doesn't know:

from datetime import date

import know_your_ip as kyi

result = kyi.enrich(["8.8.8.8"], as_of=date(2019, 3, 14))
print(result.manifest["providers"])

No provider can answer for 2019 yet, so none of them pretends to — you get an empty provider list rather than today's data wearing a 2019 label. As historical sources land they'll honour the same contract.

Install

Python 3.11+.

pip install know_your_ip

The base install is deliberately small — three dependencies, no accounts needed. Optional extras:

pip install 'know_your_ip[pandas]'    # to_dataframe()
pip install 'know_your_ip[shodan]'    # Shodan
pip install 'know_your_ip[timezone]'  # offline timezone lookup

Configuration

Keys go in know_your_ip.toml, in the working directory or ~/.config/know-your-ip/config.toml:

[abuseipdb]
enabled = true
api_key = "..."
days = 180          # lookback window; API maximum is 365

[virustotal]
enabled = true
api_key = "..."

Or as environment variables — KNOW_YOUR_IP_VIRUSTOTAL_API_KEY and so on. Unknown keys and sections are rejected rather than ignored, so a typo fails loudly instead of silently disabling a provider.

Generate a complete annotated file:

from pathlib import Path

from know_your_ip import create_default_config

create_default_config(Path("know_your_ip.toml"))

Geolocation database

MaxMind needs a free account since 2019. Once you have an account ID and license key:

know_your_ip download-db --account-id YOUR_ID --license-key YOUR_KEY

It lands where the package looks for it, with no further configuration. GeoLite2 allows 30 downloads per 24 hours, and its licence requires deleting outdated copies within 30 days.

Where to look next

Command line reference

usage: know_your_ip [-h] [-f FILE] [-c CONFIG] [-o OUTPUT] [-n MAX_CONN]
                    [--from FROM_ROW] [--to TO] [--all-columns]
                    [--providers PROVIDERS] [--as-of AS_OF] [--cache [PATH]]
                    [--max-age HOURS] [--list-providers]
                    [--log-file LOG_FILE] [-v] [--no-header]
                    [ip ...]

Citation

If this package contributes to published work, see CITATION.cff.

Authors

Suriyan Laohaprapanon and Gaurav Sood. Released under the MIT License.


Intended for legitimate research, security analysis, and network diagnostics. Respect each service's terms and rate limits.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

know_your_ip-0.5.0.tar.gz (326.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

know_your_ip-0.5.0-py3-none-any.whl (47.7 kB view details)

Uploaded Python 3

File details

Details for the file know_your_ip-0.5.0.tar.gz.

File metadata

  • Download URL: know_your_ip-0.5.0.tar.gz
  • Upload date:
  • Size: 326.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for know_your_ip-0.5.0.tar.gz
Algorithm Hash digest
SHA256 a1a830a1ce0e3d3b33e3da6f42c09df3b864d245c3ef352a67948decd408fff2
MD5 7fb5e8174b7f8c6190f75590d8c2a279
BLAKE2b-256 4fe992f9e43a42904496739e4ea550a9da369560eb2ccd01414479100389a8eb

See more details on using hashes here.

Provenance

The following attestation bundles were made for know_your_ip-0.5.0.tar.gz:

Publisher: release.yml on themains/know-your-ip

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file know_your_ip-0.5.0-py3-none-any.whl.

File metadata

  • Download URL: know_your_ip-0.5.0-py3-none-any.whl
  • Upload date:
  • Size: 47.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for know_your_ip-0.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a082da94a4159718d6a10a9abcba1c4593368227269fe1a43927cd09b6b5d115
MD5 22acc9d887535944b7db67fed2b498da
BLAKE2b-256 98af3462f040fc1ae45a6bcbc7656e8946d4a33f118a9c2c0384915d69c80c86

See more details on using hashes here.

Provenance

The following attestation bundles were made for know_your_ip-0.5.0-py3-none-any.whl:

Publisher: release.yml on themains/know-your-ip

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page