Official Erlang client library for the ipdata.co IP geolocation and threat intelligence API.
- IP geolocation (city, region, country, continent, coordinates)
- ASN and company data
- Carrier detection (mobile network operator)
- Timezone, currency, and language detection
- Threat intelligence (Tor, VPN, proxy, datacenter, blocklists)
- Bulk lookups (up to 100 IPs per request)
- Field filtering to reduce response size
- EU endpoint support for data residency
- Production-ready with proper TLS verification and error handling
- Erlang/OTP 25 or later
- rebar3
Add ipdata to your rebar.config dependencies:
{deps, [
{ipdata, "~> 1.0"}
]}.%% Start the application
application:ensure_all_started(ipdata).
%% Create a client with your API key
{ok, Client} = ipdata:new(<<"YOUR_API_KEY">>).
%% Look up an IP address
{ok, Result} = ipdata:lookup(Client, <<"8.8.8.8">>).
maps:get(<<"country_name">>, Result).
%% => <<"United States">>%% Default options (global endpoint, 5s timeout)
{ok, Client} = ipdata:new(<<"YOUR_API_KEY">>).
%% Use the EU endpoint for data residency
{ok, Client} = ipdata:new(<<"YOUR_API_KEY">>, #{endpoint => eu}).
%% Custom endpoint and timeout
{ok, Client} = ipdata:new(<<"YOUR_API_KEY">>, #{
endpoint => <<"https://custom-api.example.com">>,
timeout => 10000
}).{ok, Result} = ipdata:lookup(Client).{ok, Result} = ipdata:lookup(Client, <<"8.8.8.8">>).
%% Access response fields
maps:get(<<"ip">>, Result). %% => <<"8.8.8.8">>
maps:get(<<"country_name">>, Result). %% => <<"United States">>
maps:get(<<"city">>, Result). %% => <<"Ashburn">>
maps:get(<<"latitude">>, Result). %% => 39.03
maps:get(<<"longitude">>, Result). %% => -77.5
%% Nested data
ASN = maps:get(<<"asn">>, Result).
maps:get(<<"name">>, ASN). %% => <<"Google LLC">>
Threat = maps:get(<<"threat">>, Result).
maps:get(<<"is_vpn">>, Threat). %% => false
TimeZone = maps:get(<<"time_zone">>, Result).
maps:get(<<"name">>, TimeZone). %% => <<"America/New_York">>Request only the fields you need to reduce response size and improve performance:
{ok, Result} = ipdata:lookup(Client, <<"8.8.8.8">>,
[<<"ip">>, <<"country_name">>, <<"city">>]).
%% Result contains only the requested fieldsLook up multiple IP addresses in a single request (up to 100, requires a paid plan):
{ok, Results} = ipdata:bulk(Client, [<<"8.8.8.8">>, <<"1.1.1.1">>]).
%% Results is a list of maps, one per IP
%% With field filtering
{ok, Results} = ipdata:bulk(Client, [<<"8.8.8.8">>, <<"1.1.1.1">>],
[<<"ip">>, <<"country_name">>]).All functions return {ok, Result} on success or {error, Reason} on failure:
case ipdata:lookup(Client, <<"8.8.8.8">>) of
{ok, Result} ->
io:format("Country: ~s~n", [maps:get(<<"country_name">>, Result)]);
{error, {http_error, 401, Message}} ->
io:format("Authentication failed: ~s~n", [Message]);
{error, {http_error, 403, Message}} ->
io:format("Forbidden: ~s~n", [Message]);
{error, {http_error, 429, Message}} ->
io:format("Rate limited: ~s~n", [Message]);
{error, {request_failed, Reason}} ->
io:format("Network error: ~p~n", [Reason]);
{error, {json_error, Reason}} ->
io:format("JSON parse error: ~p~n", [Reason])
end.-spec new(ApiKey :: binary()) -> {ok, client()} | {error, term()}.
-spec new(ApiKey :: binary(), Opts :: opts()) -> {ok, client()} | {error, term()}.Create a new client. Options:
| Key | Type | Default | Description |
|---|---|---|---|
endpoint |
global | eu | binary() |
global |
API endpoint to use |
timeout |
pos_integer() |
5000 |
Request timeout in milliseconds |
-spec lookup(Client) -> {ok, map()} | {error, term()}.
-spec lookup(Client, IP :: binary()) -> {ok, map()} | {error, term()}.
-spec lookup(Client, IP :: binary(), Fields :: [binary()]) -> {ok, map()} | {error, term()}.Look up geolocation and metadata for an IP address.
-spec bulk(Client, IPs :: [binary()]) -> {ok, [map()]} | {error, term()}.
-spec bulk(Client, IPs :: [binary()], Fields :: [binary()]) -> {ok, [map()]} | {error, term()}.Look up multiple IP addresses in a single request. Maximum 100 IPs. Requires a paid API key.
| Field | Type | Description |
|---|---|---|
ip |
binary | IP address |
is_eu |
boolean | Whether the country is in the EU |
city |
binary | City name |
region |
binary | Region/state name |
region_code |
binary | Region code |
region_type |
binary | Region type |
country_name |
binary | Country name |
country_code |
binary | ISO country code |
continent_name |
binary | Continent name |
continent_code |
binary | Continent code |
latitude |
float | Latitude |
longitude |
float | Longitude |
postal |
binary | Postal/ZIP code |
calling_code |
binary | International calling code |
flag |
binary | Country flag image URL |
emoji_flag |
binary | Country flag emoji |
emoji_unicode |
binary | Country flag unicode |
asn |
map | ASN data (asn, name, domain, route, type) |
organisation |
binary | Organization name |
company |
map | Company data (name, domain, network, type) |
carrier |
map | Mobile carrier (name, mcc, mnc) |
languages |
list | Languages (name, native, code) |
currency |
map | Currency (name, code, symbol, native, plural) |
time_zone |
map | Timezone (name, abbr, offset, is_dst, current_time) |
threat |
map | Threat data (see below) |
count |
binary | API request count |
| Field | Type | Description |
|---|---|---|
is_tor |
boolean | Tor exit node |
is_vpn |
boolean | VPN |
is_icloud_relay |
boolean | iCloud Private Relay |
is_proxy |
boolean | Proxy |
is_datacenter |
boolean | Datacenter IP |
is_anonymous |
boolean | Anonymous access |
is_known_attacker |
boolean | Known attacker |
is_known_abuser |
boolean | Known abuser |
is_threat |
boolean | Any threat detected |
is_bogon |
boolean | Bogon IP |
blocklists |
list | Blocklist entries (name, site, type) |
scores |
map | Reputation scores (vpn_score, proxy_score, threat_score, trust_score) |
rebar3 ctMIT - see LICENSE for details.