How to Get IP Geolocation in JavaScript (Node + Browser)

By Mudassar Tariq Software Engineer at IP Geolocation
Posted on June 24, 2026 | 11 min read
How to Get IP Geolocation in JavaScript (Node + Browser)
Back to All Tutorials

IP geolocation in JavaScript means turning an IP address into location, timezone, currency, and network data, in Node.js or the browser. It is a different thing from the browser's navigator.geolocation, which asks the user for GPS permission. This tutorial covers the IP kind: no permission prompt and a free tier to start.

With the IPGeolocation API and its official JavaScript SDK, a single call returns where an IP is and the network that owns it, with optional VPN, proxy, and threat signals on paid plans. Developers reach for it for localization, fraud checks, analytics, and access control. The core lookups run on a free key (1,000 a day, no card); the paid extras are flagged where they appear.


TL;DR

  • Get IP geolocation in JavaScript: install ip-geolocation-api-javascript-sdk, create an IpGeolocationClient with your API key, call lookupIpGeolocation({ ip }) in Node.js, and read response.data.location, timeZone, currency, and asn. Run it server-side so the key stays private.
  • Node vs browser: keep the key in an env var and look up server-side. In the browser, call your own backend or use request-origin auth (paid). Never ship the key in front-end code.
  • Visitor IP: behind a proxy or CDN, set a scoped trust proxy in Express (or read the platform header in Next.js), then geolocate that IP.
  • Free vs paid: 1,000 lookups a day free, no card; VPN, proxy, threat, abuse, and bulk lookups are paid.
  • No SDK: call https://api.ipgeolocation.io/v3/ipgeo with fetch, key kept server-side.

IP geolocation vs the browser Geolocation API

The browser Geolocation API (navigator.geolocation) returns device coordinates from GPS, Wi-Fi, or cell signal. It is accurate to a few meters, runs only in the browser, and always shows a permission prompt the user can deny. IP geolocation takes an IP address and maps it to a city-level location plus the owning network. It needs no permission prompt and runs server-side or in the browser, so it fits localizing content, screening traffic, or enriching logs without asking anyone for anything.

When to use the browser Geolocation API versus IP geolocation in JavaScript

City-level is the honest expectation for IP data; it is not a GPS replacement. For how that accuracy is sourced and where it varies, see how IP geolocation works. The rest of this tutorial is the IP kind.


Prerequisites

Node.js 18 or newer, which ships a global fetch (the SDK uses it), a free API key, and npm. The Node examples run anywhere Node does; the browser pattern needs a small backend, which the Express section covers.


Get a free IPGeolocation API key

Create a free IPGeolocation account and copy a key from the dashboard. No card required. The free tier is 1,000 lookups a day and covers everything in the core walkthrough: location, country metadata, currency, basic ASN, and timezone.

Paid plans add company and network data, bulk lookups, the security (VPN, proxy, threat) and abuse modules, and non-English responses; compare tiers on the pricing page. Keep the key in an environment variable so it never lands in your source or git history. The examples read it from IPGEOLOCATION_API_KEY.

export IPGEOLOCATION_API_KEY="your_api_key_here"

Install the JavaScript SDK

Install the official JavaScript SDK. It ships ESM, CommonJS, and TypeScript declarations, and returns typed objects so your editor autocompletes the response.

npm install ip-geolocation-api-javascript-sdk

Import it with ES modules:

import { IpGeolocationClient } from "ip-geolocation-api-javascript-sdk";

Or with CommonJS:

const { IpGeolocationClient } = require("ip-geolocation-api-javascript-sdk");

On TypeScript projects, the TypeScript SDK (ip-geolocation-api-sdk-typescript) gives you the same client with first-class typed request and response models.


Your first IP lookup in Node.js

Here is a complete server-side lookup: the key comes from the environment, the call is wrapped so a bad key or a network hiccup never crashes the process, and the client is closed when you are done.

import {
  IpGeolocationClient,
  UnauthorizedError,
} from "ip-geolocation-api-javascript-sdk";

async function geolocate(ip) {
  const client = new IpGeolocationClient({
    apiKey: process.env.IPGEOLOCATION_API_KEY,
  });

  try {
    const response = await client.lookupIpGeolocation({ ip });
    const location = response.data.location;

    console.log(location?.countryName, location?.city); // United States Mountain View
    console.log(response.data.timeZone?.name); // America/Los_Angeles
    return response.data;
  } catch (error) {
    if (error instanceof UnauthorizedError) {
      console.error("Check your API key:", error.apiMessage);
    } else {
      console.error("IP geolocation lookup failed:", error);
    }
    return null;
  } finally {
    await client.close();
  }
}

geolocate("8.8.8.8");

Two details matter. The response is typed, and optional objects are absent until you request them or your plan includes them, so location?.city uses optional chaining instead of assuming the field is there. And the client holds an open connection, so call close() when a short script finishes. In a long-running server you create the client once and keep it; you do not open one per request.


1. Look up the caller's IP

Leave out ip and the API geolocates whoever made the request, which is your server's own public IP. It is handy for a quick check, not for finding a visitor.

const response = await client.lookupIpGeolocation({});
console.log(response.data.ip); // your server's public IP

Get the visitor's real IP (Express and Next.js)

Geolocating a fixed address like 8.8.8.8 is trivial. Finding the real visitor is the part that trips people up: behind a load balancer or CDN, the connecting socket belongs to the proxy, so the visitor's address arrives in the X-Forwarded-For header instead. That header is easy to forge on a direct request, so trust it only from proxies you control.

In Express, do not parse the header by hand. Set trust proxy to the number of proxy hops in front of you (or a trusted CIDR), and let Express resolve req.ip. Avoid trust proxy: true unless your edge proxy reliably overwrites the X-Forwarded-* headers, because otherwise a client can forge them.

import express from "express";
import { IpGeolocationClient } from "ip-geolocation-api-javascript-sdk";

const app = express();

// Trust exactly the proxies in front of your app. 1 = a single load balancer or CDN.
// Prefer a hop count or CIDR; `true` is safe only if your edge proxy overwrites X-Forwarded-* headers.
app.set("trust proxy", 1);

// Create the client once for the whole process, not per request.
const client = new IpGeolocationClient({
  apiKey: process.env.IPGEOLOCATION_API_KEY,
});

app.get("/", async (req, res) => {
  const ip = req.ip; // resolved from X-Forwarded-For using your trust setting

  try {
    const response = await client.lookupIpGeolocation({ ip });
    res.json({
      ip,
      country: response.data.location?.countryName ?? null,
      city: response.data.location?.city ?? null,
    });
  } catch (error) {
    console.error("Geolocation failed for", ip, error);
    res.status(502).json({ ip, country: null, city: null });
  }
});

app.listen(3000);

Express documents the trust settings in its behind proxies guide. Which entry in the chain you can actually trust, and how to set it for Nginx, Cloudflare, and other proxies, is its own topic; we cover it in getting the real client IP behind a proxy.

On Next.js, read the client IP in a route handler. On a managed platform like Vercel, the platform populates x-forwarded-for with the real client IP, so reading it here is safe. Only trust this header when your platform or reverse proxy overwrites it; if you run your own proxy, apply the trusted-proxy rules from the guide above instead of trusting the raw header.

// app/api/geo/route.js (Next.js App Router)
import { IpGeolocationClient } from "ip-geolocation-api-javascript-sdk";

const client = new IpGeolocationClient({
  apiKey: process.env.IPGEOLOCATION_API_KEY,
});

export async function GET(request) {
  const forwarded = request.headers.get("x-forwarded-for") ?? "";
  const ip = forwarded.split(",")[0].trim();

  if (!ip) {
    return Response.json({ error: "No client IP" }, { status: 400 });
  }

  try {
    const response = await client.lookupIpGeolocation({ ip });
    return Response.json({
      ip,
      country: response.data.location?.countryName ?? null,
    });
  } catch (error) {
    console.error("Geolocation failed for", ip, error);
    return Response.json({ ip, country: null }, { status: 502 });
  }
}

IP geolocation in the browser without exposing your key

You can run the SDK in any runtime with fetch, including the browser. The catch is the API key. If you put it in a front-end fetch, anyone can open dev tools and read it. If you have ever shipped a key that way, you are in large company, but it does mean strangers can spend your quota, so treat the browser as untrusted and keep the key on the server.

There are two correct patterns. The first works on the free tier: the browser calls your own backend, and the backend (the Express or Next.js handler above) holds the key and does the lookup.

// Browser: call your own endpoint, never the IP geolocation API directly.
const res = await fetch("/api/geo");
const geo = await res.json();
console.log(geo.country);
Secure browser IP geolocation by calling your Node backend instead of exposing the API key

The second is request-origin auth, a paid-plan feature for single lookups: you authorize an allowlisted origin instead of shipping a key, so the browser can call the API directly.

import { IpGeolocationClient } from "ip-geolocation-api-javascript-sdk";

// Paid plans only, single lookups. Authorizes by origin, no key in the page.
const client = new IpGeolocationClient({
  requestOrigin: "https://app.example.com",
});

const response = await client.lookupIpGeolocation({ ip: "8.8.8.8" });
console.log(response.data.location?.countryName);

What a lookup returns

A default lookup returns more than most apps use. This trimmed example shows the objects the free plan returns:

{
  "ip": "8.8.8.8",
  "location": {
    "country_name": "United States",
    "state_prov": "California",
    "city": "Mountain View",
    "latitude": "37.42240",
    "longitude": "-122.08421"
  },
  "country_metadata": { "calling_code": "+1", "languages": ["en-US", "es-US", "haw", "fr"] },
  "currency": { "code": "USD", "name": "US Dollar", "symbol": "$" },
  "asn": { "as_number": "AS15169", "organization": "Google LLC" },
  "time_zone": { "name": "America/Los_Angeles" }
}
IPGeolocation API JSON response fields in JavaScript: location, timezone, currency, ASN

The SDK hands these back as typed, camelCase objects, so response.data.location?.countryName gives United States and response.data.timeZone?.name gives the zone. Paid plans add company and network, with security and abuse available through include. If you only need a couple of fields, trim the response with fields; note the field paths use snake_case even though the accessors are camelCase.

const response = await client.lookupIpGeolocation({
  ip: "8.8.8.8",
  fields: ["location.country_name", "location.city", "time_zone.name"],
});

console.log(response.data.location?.countryName, response.data.timeZone?.name);

IP geolocation in JavaScript without the SDK (raw fetch)

If you would rather not add a dependency, call the endpoint directly with fetch. Keep the key server-side, set a timeout, and check the status before reading the body.

const API_KEY = process.env.IPGEOLOCATION_API_KEY;

async function geolocate(ip) {
  // Build the query with URLSearchParams so values are encoded (IPv6 colons, etc.).
  // The key rides in the query string, so avoid logging this full URL.
  const params = new URLSearchParams({ apiKey: API_KEY, ip });
  const url = `https://api.ipgeolocation.io/v3/ipgeo?${params}`;

  try {
    const res = await fetch(url, { signal: AbortSignal.timeout(5000) });
    if (!res.ok) {
      throw new Error(`IP geolocation API returned ${res.status}`);
    }
    const data = await res.json();
    return data.location?.country_name ?? null;
  } catch (error) {
    console.error("IP geolocation request failed:", error);
    return null;
  }
}

The raw endpoint returns snake_case fields (location.country_name), and you handle parsing, timeouts, and errors yourself. The SDK adds typed responses, validation, and named error classes, which is why the rest of this tutorial uses it.


Errors, timeouts, and retries

The SDK does not retry for you, which is the right default: it raises typed errors and lets you decide what to do. Back off on the transient ones (rate limits, server errors, timeouts) and fail fast on the ones a retry will not fix, like a bad key.

import {
  IpGeolocationClient,
  RateLimitError,
  ServerError,
  RequestTimeoutError,
  TransportError,
  UnauthorizedError,
} from "ip-geolocation-api-javascript-sdk";

const client = new IpGeolocationClient({
  apiKey: process.env.IPGEOLOCATION_API_KEY,
  connectTimeoutMs: 5000,
  readTimeoutMs: 5000,
});

async function lookupWithRetry(ip, attempts = 3) {
  for (let attempt = 1; attempt <= attempts; attempt++) {
    try {
      return await client.lookupIpGeolocation({ ip });
    } catch (error) {
      const transient =
        error instanceof RateLimitError ||
        error instanceof ServerError ||
        error instanceof RequestTimeoutError ||
        error instanceof TransportError;

      if (error instanceof UnauthorizedError || !transient || attempt === attempts) {
        throw error; // a retry will not fix a bad key, and we are out of attempts
      }

      await new Promise((resolve) => setTimeout(resolve, 2 ** attempt * 250)); // 0.5s, 1s, 2s
    }
  }
}

Every response also carries metadata: response.metadata.creditsCharged tells you what the call cost, and response.metadata.firstHeaderValue(name) reads any response header the API includes.


Production checklist

The handful of things that separate a demo from code you can ship:

  • Shipping the key to the browser. Keep it server-side behind your own endpoint, or use request-origin auth on a paid plan.
  • trust proxy: true. Scope it to your real proxy hops or a CIDR, so a forged X-Forwarded-For cannot set the visitor IP.
  • Sending private or reserved IPs. Validate the address first; a private IP has no public location.
  • Fetching everything every time. Cache results per IP to save credits, and use fields to reduce payload and latency.
  • Treating IP geolocation as exact. It is approximate, especially on mobile and VPN traffic, so do not make it your only fraud or access-control signal.
  • Bundling an offline IP database and forgetting it. Local databases drift out of date and carry no VPN or threat data; an API stays current. The tradeoff is real, and an IP geolocation API versus a local database walks through when each fits.

Examples tested with ip-geolocation-api-javascript-sdk 3.0.1 on Node.js 18.20.8.


Going further: security, abuse, and bulk

Three paid add-ons extend the same client once you outgrow plain geolocation. Each links to its own reference rather than a worked example here:

  • VPN, proxy, and threat detection: add include: ["security"] for a security object with threatScore, isVpn, isProxy, and isTor. See the IP Security API.
  • Network abuse contact: add include: ["abuse"] for the reporting contact behind an IP range. See the Abuse Contact API.
  • Bulk lookups: call bulkLookupIpGeolocation({ ips: [...] }) for up to 50,000 IPs in one request, with a success or error result per IP.

FAQ

Install ip-geolocation-api-javascript-sdk, create an IpGeolocationClient with your API key, and call lookupIpGeolocation({ ip }). Read response.data.location, timeZone, currency, and asn. Run it in Node.js with the key in an environment variable. The free tier allows 1,000 lookups a day with no card.

Set a scoped trust proxy in Express (the number of proxy hops, or a CIDR, never true), then read req.ip and pass it to the API. That resolves the client IP from X-Forwarded-For only for proxies you trust, instead of a value a client can spoof.

Yes. The free tier gives 1,000 lookups a day with no credit card and returns location, country metadata, currency, basic ASN, and timezone for any IPv4 or IPv6 address. VPN, proxy, and threat detection, abuse contact data, and bulk lookups are paid.

Yes, two ways. On the free tier, have the browser call your own backend, which holds the key and does the lookup. On a paid plan, use request-origin auth, which authorizes an allowlisted origin so no key ships in your front-end code. Never put the key in browser fetch.

Yes to both. Pass an IPv6 address as ip exactly like IPv4, on the free and paid plans. In Next.js, read the client IP from x-forwarded-for in a route handler (your platform sets it), then pass that IP to the SDK the same way the Node example does.

navigator.geolocation is the browser API: it returns precise GPS coordinates but needs a permission prompt and runs only client-side. IP geolocation maps an IP address to a city-level location server-side with no prompt. Use the browser API for maps, IP geolocation for localization, analytics, and access control.


Next steps

Grab a free API key, run the Node example, then wire in the visitor-IP step for your framework. From here, the tutorial series covers the same workflow in other languages, including IP geolocation in Python and IP geolocation in PHP.

Related Tutorials

How to Get IP Geolocation in PHP (API Tutorial)
How to Get IP Geolocation in PHP (API Tutorial)

Get IP geolocation in PHP with the official IPGeolocation.io library: install with Composer, run your first lookup, and read the real visitor IP in vanilla PHP and Laravel. Links to optional VPN/proxy, abuse contact, and bulk lookups on paid plans.

Posted onJune22, 2026
ByMudassar Tariq
Read More
How to Get IP Geolocation in Python (API Tutorial)
How to Get IP Geolocation in Python (API Tutorial)

Get IP geolocation in Python with the official IPGeolocation.io library: single lookups, async requests, and real visitor IP handling in Flask and FastAPI, plus optional bulk lookup and VPN/proxy detection examples.

Posted onJune19, 2026
ByMudassar Tariq
Read More
WooCommerce Fraud Prevention: Setup Guide for FraudShield
WooCommerce Fraud Prevention: Setup Guide for FraudShield

A full setup walkthrough for FraudShield, the WooCommerce fraud detection plugin built on the ipgeolocation.io API. Install to first protected order in under 20 minutes.

Posted onJune16, 2026
Read More
How to Secure Your API Key Before Production
How to Secure Your API Key Before Production

Your API key works in development, but shipping it as-is to production is a security risk. This tutorial covers environment variables, backend proxies, CORS-based auth, and usage monitoring for the IPGeolocation.io API.

Posted onMay14, 2026
Read More
IP Geolocation in Google Tag Manager
IP Geolocation in Google Tag Manager

Learn how to set up IP geolocation tracking in Google Tag Manager using the official IPGeolocation.io custom template. Covers API key setup, tag configuration, data layer variables, and practical use cases.

Posted onMay7, 2026
Read More
How to Use the IPGeolocation.io Astronomy API
How to Use the IPGeolocation.io Astronomy API

Learn how to use the IPGeolocation.io Astronomy API to get sunrise, sunset, moon phase, golden hour, and 50+ other data fields from a single API call.

Posted onMay6, 2026
Read More

Subscribe to Our Newsletter

Get the latest in geolocation tech, straight to your inbox.