Question: I'm running a Streamlit app where I try to retrieve the user's geolocation in streamlit. However, when using geocoder.ip("me"), the coordinates returned are 45, -121, which point to Oregon, USA, rather than my actual location. This is the function I use: def get_lat_lon(): # Use geocoder to get the location based on IP g = geocoder.ip('me') if g.ok: lat = g.latlng[0] # Latitude lon = g.latlng[1] # Longitude return lat, lon else: st.error("Could not retrieve location from IP address.") return None, None  I would like to find a solution that can work in an streamlit app so by clicking a st.button I can call a function that retrieves my lat, long.

Answer: Consider the following simple Streamlit app: import streamlit as st import requests import geocoder from typing import Optional, Tuple def get_location_geocoder() -> Tuple[Optional[float], Optional[float]]: """ Get location using geocoder library """ g = geocoder.ip('me') if g.ok: return g.latlng[0], g.latlng[1] return None, None def get_location_ipapi() -> Tuple[Optional[float], Optional[float]]: """ Fallback method using ipapi.co service """ try: response = requests.get('https://ipapi.co/json/') if response.status_code == 200: data = response.json() lat = data.get('latitude') lon = data.get('longitude') if lat is not None and lon is not None: # Store additional location data in session state st.session_state.location_data = { 'city': data.get('city'), 'region': data.get('region'), 'country': data.get('country_name'), 'ip': data.get('ip') } return lat, lon except requests.RequestException as e: st.error(f"Error retrieving location from ipapi.co: {str(e)}") return None, None def get_location() -> Tuple[Optional[float], Optional[float]]: """ Tries to get location first using geocoder, then falls back to ipapi.co """ # Try geocoder first lat, lon = get_location_geocoder() # If geocoder fails, try ipapi if lat is None: st.info("Primary geolocation method unsuccessful, trying alternative...") lat, lon = get_location_ipapi() return lat, lon def show_location_details(): """ Displays the additional location details if available """ if 'location_data' in st.session_state: data = st.session_state.location_data st.write("Location Details:") col1, col2 = st.columns(2) with col1: st.write("📍 City:", data['city']) st.write("🏘️ Region:", data['region']) with col2: st.write("🌍 Country:", data['country']) st.write("🔍 IP:", data['ip']) def main(): st.title("IP Geolocation Demo") st.write("This app will attempt to detect your location using IP geolocation.") if st.button("Get My Location", type="primary"): with st.spinner("Retrieving your location..."): lat, lon = get_location() if lat is not None and lon is not None: st.success("Location retrieved successfully!") # Create two columns for coordinates col1, col2 = st.columns(2) with col1: st.metric("Latitude", f"{lat:.4f}") with col2: st.metric("Longitude", f"{lon:.4f}") # Show additional location details if available show_location_details() # Display location on a map st.write("📍 Location on Map:") st.map(data={'lat': [lat], 'lon': [lon]}, zoom=10) else: st.error("Could not determine your location. Please check your internet connection and try again.") if __name__ == "__main__": main()  The app above allows users to click a button to generate their location using the geocoder library. I added a back up in case geocoder doesn't work as expected, using the ipapi.co api, it has been proven to be more accurate at times. There will be some limitations with this approach, it will be less accurate relative to browser geolocation API alternatives. Nevertheless it works on all devices and doesn't require permissions, whereas the browser geolocation api version will. Below are some pictures of what the app from above looks like. The geolocation button:  And the resulting output:  Depending on how exact the location requirements are it might be worth exploring the browser geolocation api alternative.