Kamero

IP Geolocation in React Native: Detect Location Without Permissions

Requesting location permissions in mobile apps creates friction. Many users deny the prompt, and app stores scrutinize why you need it. IP geolocation gives you approximate location (city, country, timezone) without any permission dialog.

When to Use IP vs GPS

NeedUse IP GeolocationUse GPS
Show local currencyโœ…Overkill
Set timezoneโœ…Overkill
Personalize contentโœ…Overkill
Navigation/mapsโŒโœ…
Delivery trackingโŒโœ…
Nearby searchRough estimateโœ…

Basic Fetch

const getLocation = async () => {
  try {
    const response = await fetch("https://geo.kamero.ai/api/geo");
    const data = await response.json();
    return data;
  } catch (error) {
    console.error("Geolocation failed:", error);
    return null;
  }
};

// Returns: { ip, city, country, timezone, latitude, longitude, ... }

Custom Hook: useIPLocation

import { useState, useEffect } from "react";

interface IPLocation {
  ip: string;
  city: string;
  country: string;
  countryRegion: string;
  continent: string;
  latitude: string;
  longitude: string;
  timezone: string;
  postalCode: string;
}

export function useIPLocation() {
  const [location, setLocation] = useState<IPLocation | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    let cancelled = false;

    fetch("https://geo.kamero.ai/api/geo")
      .then((res) => res.json())
      .then((data) => {
        if (!cancelled) setLocation(data);
      })
      .catch((err) => {
        if (!cancelled) setError(err.message);
      })
      .finally(() => {
        if (!cancelled) setLoading(false);
      });

    return () => { cancelled = true; };
  }, []);

  return { location, loading, error };
}

Usage in a Component

import { View, Text, ActivityIndicator } from "react-native";
import { useIPLocation } from "./hooks/useIPLocation";

export default function WelcomeScreen() {
  const { location, loading } = useIPLocation();

  if (loading) {
    return <ActivityIndicator size="large" />;
  }

  return (
    <View style={{ padding: 20 }}>
      <Text style={{ fontSize: 24 }}>
        Welcome from {location?.city || "there"}!
      </Text>
      <Text style={{ color: "#666" }}>
        {location?.country} ยท {location?.timezone}
      </Text>
    </View>
  );
}

Progressive Enhancement: IP First, Then GPS

Start with IP geolocation for instant results, then upgrade to GPS if the user grants permission:

import * as Location from "expo-location";

export function useLocation() {
  const [location, setLocation] = useState(null);
  const [source, setSource] = useState<"ip" | "gps">("ip");

  useEffect(() => {
    // Step 1: Instant IP-based location
    fetch("https://geo.kamero.ai/api/geo")
      .then(r => r.json())
      .then(data => {
        setLocation({
          latitude: parseFloat(data.latitude),
          longitude: parseFloat(data.longitude),
          city: data.city,
          country: data.country,
        });
        setSource("ip");
      });

    // Step 2: Try GPS (non-blocking)
    (async () => {
      const { status } = await Location.requestForegroundPermissionsAsync();
      if (status === "granted") {
        const pos = await Location.getCurrentPositionAsync({});
        setLocation(prev => ({
          ...prev,
          latitude: pos.coords.latitude,
          longitude: pos.coords.longitude,
        }));
        setSource("gps");
      }
    })();
  }, []);

  return { location, source };
}

Caching the Result

import AsyncStorage from "@react-native-async-storage/async-storage";

async function getCachedLocation() {
  const cached = await AsyncStorage.getItem("ip_location");
  if (cached) {
    const { data, timestamp } = JSON.parse(cached);
    // Cache for 1 hour
    if (Date.now() - timestamp < 3600000) return data;
  }

  const response = await fetch("https://geo.kamero.ai/api/geo");
  const data = await response.json();

  await AsyncStorage.setItem("ip_location", JSON.stringify({
    data,
    timestamp: Date.now(),
  }));

  return data;
}

Common Use Cases in Mobile Apps

No Permissions Required

Get city, country, and timezone from any mobile app. Free API, no key.

View Documentation โ†’