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
| Need | Use IP Geolocation | Use GPS |
|---|---|---|
| Show local currency | โ | Overkill |
| Set timezone | โ | Overkill |
| Personalize content | โ | Overkill |
| Navigation/maps | โ | โ |
| Delivery tracking | โ | โ |
| Nearby search | Rough 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
- Onboarding โ Pre-select country and language during first launch
- Currency โ Show prices in local currency without asking
- Timezone โ Schedule notifications in the user's local time
- Content โ Show region-specific promotions or news
- Analytics โ Track user geography without invasive permissions
No Permissions Required
Get city, country, and timezone from any mobile app. Free API, no key.
View Documentation โ