Node-RED nodes for the IPGeolocation.io v3 API: IP geolocation, security and threat intelligence, VPN and proxy detection, abuse contacts, ASN lookup, bulk IP processing, time zone, astronomy, and user-agent parsing.
A complete, production-ready set of Node-RED IP geolocation nodes. Look up the country, city, latitude, and longitude of any IP address or domain, score IPs for proxy, VPN, Tor, and bot risk, resolve ASN and abuse-contact data, parse user-agent strings, and fetch time zone and astronomy data, all from low-code Node-RED flows.
- Features
- Quick start
- Requirements
- Installation
- Configuration: API key
- How the nodes work
- Node reference
- Message properties
- Error handling and retries
- Example flows
- Recipes
- API credits
- Development and testing
- FAQ
- License
- Links
- Single IP geolocation: resolve country, region, city, latitude, longitude, currency, and time zone for any IPv4, IPv6, or domain.
- Bulk IP geolocation: process up to 50,000 IP addresses in one request.
- IP security and threat intelligence: detect proxy, VPN, Tor, bot, and threat scores for fraud prevention and access control.
- Bulk security lookup: score large IP lists in a single call.
- Abuse contact lookup: retrieve the abuse email, phone, and owning organization for an IP.
- ASN lookup: resolve Autonomous System details by IP or AS number.
- Time Zone API: get time zone data by name, IP, coordinates, city, IATA code, ICAO code, or UN/LOCODE.
- Astronomy API: sunrise, sunset, moonrise, moonset, twilight phases, moon phase, and solar and lunar positions by coordinates, address, or IP.
- User-agent parser: identify browser, device, OS, and engine from a user-agent string.
- Developer friendly: dynamic
msg,flow, andglobalinputs, an optional dedicated error output, automatic retries with exponential backoff, secure credential storage, and per-request credit reporting.
# In your Node-RED user directory (usually ~/.node-red)
npm install node-red-contrib-ipgeolocation- Restart Node-RED.
- Drag the ipgeo lookup node onto the canvas (find it under the IPGeolocation palette category).
- Open the node, click the pencil next to API Config, and paste your free IPGeolocation.io API key.
- Wire an inject node in and a debug node out, then deploy.
- Inject any IP string as
msg.payload, for example8.8.8.8, and read the geolocation result from the debug panel.
That is the whole loop: inject an IP, get structured location data back.
| Requirement | Version |
|---|---|
| Node-RED | >= 2.0 |
| Node.js | >= 14.0 |
| IPGeolocation.io API key | Free tier works (sign up) |
- Open Node-RED.
- Go to Menu > Manage palette > Install.
- Search for
node-red-contrib-ipgeolocation. - Click Install.
cd ~/.node-red
npm install node-red-contrib-ipgeolocationFor an existing installation, update the package and refresh its HTTP dependencies in the Node-RED user directory:
npm install node-red-contrib-ipgeolocation@latest
npm update axios follow-redirectsRestart Node-RED. All ten nodes appear under the IPGeolocation category in the palette.
Every functional node references a shared ipgeo config node that holds your API key. The key is stored as an encrypted Node-RED credential and is never written into exported flow JSON.
- Drag any IPGeolocation node onto the canvas.
- Double-click it, then click the pencil icon beside API Config.
- Enter a Name and paste your API Key.
- Click Add, then Done.
Reuse the same config node across every IPGeolocation node so you manage one key in one place.
These conventions apply to all nine functional nodes.
Dynamic input. Any IP, coordinate, or value can be a static string or read at runtime from a msg, flow, or global property. One configured node can serve many different inputs.
Two outputs by default. Each node ships with two outputs:
- Output 1 (success): the API result, written to the configured property (default
msg.payload). - Output 2 (error): the original
msgwith a structuredmsg.errorattached.
Uncheck Use second output to collapse to a single output and handle failures flow-wide with a standard Catch node.
Response shaping. Most nodes expose Fields (return only the listed dot-notation paths) and Excludes (drop listed paths) so you can trim large responses, for example location.city,location.country_name or security.threat_score.
Credit reporting. Every successful response sets msg.ipgeo_credits to the number of API credits the request consumed.
| Node | Endpoint | Purpose |
|---|---|---|
ipgeo-config |
n/a | Shared API key credential |
ipgeo-lookup |
GET /v3/ipgeo |
Single IP or domain geolocation |
ipgeo-bulk |
POST /v3/ipgeo-bulk |
Bulk geolocation, up to 50,000 IPs |
ipgeo-security |
GET /v3/security |
Single-IP security and threat data |
ipgeo-bulk-security |
POST /v3/security-bulk |
Bulk security, up to 50,000 IPs |
ipgeo-abuse |
GET /v3/abuse |
Abuse contact details |
ipgeo-asn |
GET /v3/asn |
ASN details by IP or AS number |
ipgeo-timezone |
GET /v3/timezone |
Time zone by name, IP, coords, city, IATA, ICAO, UN/LOCODE |
ipgeo-astronomy |
GET /v3/astronomy |
Sun and moon data |
ipgeo-useragent |
GET /v3/user-agent |
User-agent parsing |
Resolves a single IPv4, IPv6, or domain. Leave the IP blank to look up the caller's own IP.
| Option | Description | Default |
|---|---|---|
| IP / Domain | Static value or msg / flow / global property |
empty (caller IP) |
| Include | Optional data modules to add | none |
| Fields / Excludes | Restrict or trim the response | all |
| Language | Response language | en |
| User-Agent header | Forward a UA string as a request header | off |
| Output to | Destination property | msg.payload |
Include modules:
| Module | Extra credits | Adds |
|---|---|---|
security |
+2 | Proxy, VPN, Tor, bot, threat score |
abuse |
+1 | Abuse contact (email, phone, org) |
user_agent |
0 | Parsed user-agent |
geo_accuracy |
0 | Accuracy radius and confidence |
dma_code |
0 | US Designated Market Area code |
hostname |
0 | PTR from local database |
liveHostname |
0 | Live DNS PTR lookup |
hostnameFallbackLive |
0 | Database first, then live DNS |
Set msg.ipgeo_include upstream to override the include list per message.
Sends up to 50,000 IPs or domains in one POST.
- Input:
msg.payloadas a string array (["1.2.3.4", "example.com"]) or a comma-separated string, which is split automatically. - Output: an array of result objects in input order. Invalid or private entries come back as
{ "message": "..." }.
// Keep only successfully resolved results
const resolved = msg.payload.filter(r => r.ip);Single-IP risk lookup: proxy, VPN, Tor, and bot detection plus a threat score, useful for fraud checks, login protection, and access control. Supports Fields and Excludes.
Bulk version of the security lookup, up to 50,000 IPs. Input handling matches ipgeo-bulk. When some entries cannot be scored, the node summarizes them:
| Property | Set when | Meaning |
|---|---|---|
msg.ipgeo_invalid_count |
an entry has no security object |
count of invalid entries |
msg.ipgeo_invalid_messages |
as above | the invalid entries' messages |
Both are removed from msg when every entry is valid.
Returns the abuse-contact record for an IP, such as abuse.emails, abuse.phone_numbers, and the owning organization. Supports Fields and Excludes.
Looks up Autonomous System details. The Query type selects what gets sent:
| Query type | Sends | Notes |
|---|---|---|
auto |
neither ip nor asn | API infers from context |
ip |
ip=<value> |
resolve the ASN behind an IP |
asn |
asn=<number> |
an AS prefix is stripped automatically (AS15169 becomes 15169) |
Supports an Include list (peers, downstreams, upstreams, and more), overridable per message via msg.ipgeo_include, plus Fields and Excludes.
Seven lookup modes:
| Mode | Parameter sent | Example |
|---|---|---|
| Time zone name | tz |
America/New_York |
| IP address | ip |
8.8.8.8 |
| Address / city | location |
Paris, France |
| Coordinates | lat + long |
48.8566, 2.3522 |
| IATA airport | iata_code |
CDG |
| ICAO airport | icao_code |
LFPG |
| UN/LOCODE | lo_code |
FRPAR |
Returns INVALID_INPUT when the value required for the chosen mode is missing.
Returns sunrise, sunset, moonrise, moonset, twilight phases (civil, nautical, astronomical, plus blue hour and golden hour), solar noon, day length, moon phase, illumination, and live solar and lunar positions.
The location can be derived four ways, selected by the Look up by mode:
| Mode | Sends | Notes |
|---|---|---|
coords |
lat + long |
decimal degrees; both required |
location |
location |
address, preferably a city, for example New York, USA |
ip |
ip |
any IPv4 or IPv6 address; adds an ip field to the response |
auto |
nothing | the API uses the caller's IP |
When more than one is supplied, the API prefers coordinates, then location, then IP. Coordinates and location modes return INVALID_INPUT when their value is missing.
Optional parameters (all modes):
| Option | Parameter | Description |
|---|---|---|
| Date | date |
YYYY-MM-DD; defaults to today at the location |
| Time zone | time_zone |
IANA name; converts all event times into this zone |
| Elevation | elevation |
meters above sea level, 0 to 10000; defaults to 0 |
| Language | lang |
language for the location object (paid plans) |
The response nests results under an astronomy object alongside a location object, so read values such as payload.astronomy.sunrise and payload.location.city.
Parses a user-agent string into browser, device, OS, and engine. The UA is sent to the API as a request header rather than a query parameter.
Ideal in HTTP-in flows: point the UA source at msg.req.headers.user-agent (the default) to parse each visitor's browser automatically. An empty UA returns INVALID_INPUT.
| Property | Direction | Type | Description |
|---|---|---|---|
ipgeo_credits |
output | number | Credits consumed by the request |
ipgeo_include |
input | string | Per-message override of the include list, where supported |
ipgeo_invalid_count |
output | number | Bulk-security: entries with no security result |
ipgeo_invalid_messages |
output | array | Bulk-security: messages for invalid entries |
error |
output | object | On the error output: { code, message, status, body } |
On failure, the node sets msg.error with a typed code, a readable message, the HTTP status where applicable, and the raw response body.
| Code | Cause |
|---|---|
NO_API_KEY |
Config node missing or key empty |
BAD_REQUEST |
Invalid parameters (HTTP 400) |
AUTH_FAILED |
Invalid or missing API key (HTTP 401) |
FORBIDDEN |
Plan restriction or origin not whitelisted (HTTP 403) |
NOT_FOUND |
Endpoint or resource not found (HTTP 404) |
VALIDATION |
Validation error (HTTP 422) |
LOCKED |
Private or bogon IP address (HTTP 423). Check that the input is a valid public IP and that your application resolved the visitor's address correctly. Localhost and private-network addresses cannot be geolocated. |
RATE_LIMITED |
Too many requests (HTTP 429) |
SERVER_ERROR |
API internal error (HTTP 500) |
HTTP_ERROR |
Any other non-2xx status |
TIMEOUT |
Request timed out |
NETWORK_ERROR |
DNS or connectivity failure |
NO_RESPONSE |
Request sent but no response received |
INVALID_INPUT / INVALID_MODE |
Missing or malformed node input |
TOO_MANY_IPS |
Bulk request over the 50,000-IP limit |
Automatic retries. Transient failures (HTTP 429, 500, 502, 503, 504, timeouts, and network errors) are retried up to 3 times with exponential backoff (500 ms, 1 s, 2 s). For HTTP 429, the Retry-After header is honored when present. The default request timeout is 10 seconds, and 30 seconds for the bulk endpoints.
The package bundles ready-to-import examples, one per functional node:
| Example | Demonstrates |
|---|---|
| 01 - Single IP Lookup | ipgeo-lookup |
| 02 - Bulk IP Lookup | ipgeo-bulk |
| 03 - IP Security Lookup | ipgeo-security |
| 04 - Bulk IP Security | ipgeo-bulk-security |
| 05 - Abuse Contact Lookup | ipgeo-abuse |
| 06 - ASN Lookup | ipgeo-asn |
| 07 - Timezone Lookup | ipgeo-timezone |
| 08 - Astronomy (Sun & Moon) | ipgeo-astronomy |
| 09 - User-Agent Parser | ipgeo-useragent |
To import: Menu > Import > Examples, then choose node-red-contrib-ipgeolocation and pick a flow. Each example has an inject trigger, the node wired to result and error debug nodes, and a placeholder config node. Point that config node at your own API key before deploying.
// In a Function node upstream of ipgeo-lookup or ipgeo-asn
msg.ipgeo_include = "security,abuse";
return msg;Give ipgeo-lookup one validated client IP. Do not map the raw req.headers['x-forwarded-for'] chain: the node sends it as one value, for example 203.0.113.7, 10.0.0.2, and any entry your own proxies did not add is whatever the client sent. Never let the input be empty either, because the API then looks up the caller's IP, which is your Node-RED server.
Read the address from msg.req.ip. The http in node runs on Express, which sets msg.req.ip to a single address:
- Direct connection: with the default settings,
msg.req.ipis the socket's remote address. - Behind a reverse proxy: list your proxies under
httpServerOptionsin Node-RED'ssettings.js. Express then readsX-Forwarded-Forfrom right to left, skips the trusted proxies, and uses the first address it does not trust. Do not set"trust proxy": true, which trusts every entry, including ones the client wrote.
// settings.js: nginx on the same host as Node-RED, behind a load balancer at 10.0.0.2
httpServerOptions: {
"trust proxy": ["loopback", "10.0.0.2"],
},Add a Function node with two outputs between http in and ipgeo-lookup. Wire output 1 to ipgeo-lookup and output 2 to a fallback such as an http response, then set IP / Domain to the msg property ipgeo_ip:
let ip = msg.req.ip || "";
if (ip.startsWith("::ffff:")) ip = ip.slice(7); // IPv4 client on a dual-stack listener
if (!/^(\d{1,3}\.){3}\d{1,3}$|^[0-9a-f]*:[0-9a-f:.]+$/i.test(ip)) {
return [null, msg]; // not one IP address; an empty value would look up your server's IP
}
msg.ipgeo_ip = ip;
return [msg, null];If your proxy instead overwrites a dedicated header with the client address, for example nginx proxy_set_header X-Real-IP $remote_addr;, read msg.req.headers['x-real-ip'] in the first line. Do this only when clients cannot reach Node-RED without passing through that proxy.
Run incoming IPs through ipgeo-security, then use a Switch node on payload.security.is_proxy or the threat score to drop or flag risky traffic before it reaches your application.
On ipgeo-bulk, set Fields to location.city,location.country_name,asn.organization, optionally add Include security, and Excludes security.threat_score to return only the data you need per IP.
| Endpoint or module | Credits |
|---|---|
| Single IP lookup (base) | 1 |
| + security module | +2 |
| + abuse module | +1 |
| Bulk lookup | 1-4 per valid IP |
| Security / bulk-security | 2 per valid IP |
| ASN, Abuse, Timezone, User-Agent, Astronomy | 1 |
Each node reports the real charge in msg.ipgeo_credits. See the Credits Usage Guide for current pricing.
npm ci # install the locked dependencies
npm test # run the mocha test suite
npm run coverage # run tests with an HTML and text coverage report
npm run audit:security # check runtime and development dependencies
npm run test:package # test fresh installs and upgrades of the packed npm package
npm run test:http # test HTTPS behavior with the locally installed Postman CLITests use mocha, node-red-node-test-helper, should, and nock, with all HTTP fully mocked so the suite runs offline with no live API calls. Specs live in test/**/*_spec.js and cover the shared API client, the helpers, every node, and the bundled example flows.
test:http starts a local Postman simulation and checks real HTTPS requests, redirects, retries and timeouts. It uses test credentials and stops the proxy when the checks finish. test:package requires registry access to verify fresh installations and upgrades from version 1.0.1, including an existing lock with current Axios and an older redirect dependency.
How do I get an IPGeolocation.io API key?
Sign up for a free account atapp.ipgeolocation.io/signup. The free plan covers the lookup, time zone, astronomy, and user-agent nodes, within free-plan fields and options. Bulk, security, dedicated ASN, and abuse nodes require a paid plan.
Is the API key safe in exported flows?
Yes. The API key is stored as an encrypted Node-RED credential on theipgeo-config node and is never included in exported flow JSON.
Can I look up many IP addresses at once?
Yes. Use theipgeo-bulk node for geolocation lookups or the ipgeo-bulk-security node for security and threat analysis. Both support processing up to 50,000 IP addresses in a single request.
How do I detect VPNs, proxies, or Tor exit nodes?
Use theipgeo-security node, or enable the security include module when using ipgeo-lookup. The response includes fields indicating proxy usage, VPN detection, Tor exit node status, and other threat-related information.
Does it work behind a reverse proxy?
Yes. List your proxies under"trust proxy" in httpServerOptions in Node-RED's settings.js. Express then sets msg.req.ip to one client address selected through those trusted proxies; check it in a Function node and pass it to ipgeo-lookup as a dynamic msg input. Do not pass the raw X-Forwarded-For header, which can hold several addresses, some of them written by the client. The "Geolocate the visitor in an HTTP flow" recipe shows the full setup.
What happens when I hit a rate limit?
The nodes automatically retry requests using exponential backoff and honor theRetry-After response header when provided. If the rate limit persists, the operation fails with a RATE_LIMITED error on the error output.
MIT (c) IPGeolocation.io