webdev #python #javascript #maps #api #geolocation #golf #rapidapi #showhn
A recent Show HN project mapped every US golf course—16,000+ of them, free, no signup. That is a goldmine for anyone building a golf app, travel planner, or local discovery map. But a map full of pins is only useful if you know where the user is.
Instead of asking users to type in a ZIP code, you can auto-locate them from their IP address and immediately suggest nearby courses. In this post, I’ll show you how to wire the IP Geolocation API (RapidAPI, GitHub) to a golf-course dataset so your app can say:
“You’re in Scottsdale, AZ. Here are the 5 closest golf courses.”
What we are building
- A visitor opens your web app.
- Your backend reads the visitor’s IP.
- You call the IP Geolocation API to get
latitude,longitude,city, andstate. - You compare that position against a local golf-course dataset using the haversine formula.
- You return the closest courses and render them on a map.
The golf-course data can come from the Show HN dataset. For this example, we’ll assume a CSV like this:
name,lat,lon,city,state
TPC Scottsdale,33.6405,-111.9086,Scottsdale,AZ
Grayhawk Golf Club,33.6754,-111.8240,Scottsdale,AZ
...
Backend: Flask + IP Geolocation API
Here is a minimal Flask endpoint that does the heavy lifting.
from flask import Flask, request, jsonify
import requests
import csv
import math
app = Flask(__name__)
RAPIDAPI_KEY = "YOUR_RAPIDAPI_KEY"
GEOLOCATION_URL = "https://ip-geolocation44.p.rapidapi.com/"
COURSES_FILE = "courses.csv"
def haversine(lat1, lon1, lat2, lon2):
"""Return distance in miles between two lat/lon points."""
R = 3958.8 # Earth radius in miles
phi1 = math.radians(lat1)
phi2 = math.radians(lat2)
dphi = math.radians(lat2 - lat1)
dlambda = math.radians(lon2 - lon1)
a = (
math.sin(dphi / 2) ** 2
+ math.cos(phi1) * math.cos(phi2) * math.sin(dlambda / 2) ** 2
)
c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
return R * c
@app.route("/api/nearby")
def nearby_courses():
# Grab the client IP, accounting for proxies like Heroku/Render/Vercel
ip = request.headers.get("X-Forwarded-For", request.remote_addr)
ip = ip.split(",")[0].strip() if ip else ""
# 1. Geolocate the IP
headers = {
"X-RapidAPI-Key": RAPIDAPI_KEY,
"X-RapidAPI-Host": "ip-geolocation44.p.rapidapi.com",
}
params = {"ip": ip}
geo_resp = requests.get(GEOLOCATION_URL, headers=headers, params=params)
geo_resp.raise_for_status()
geo = geo_resp.json()
user_lat = float(geo["latitude"])
user_lon = float(geo["longitude"])
# 2. Find the closest courses
courses = []
with open(COURSES_FILE, newline="") as f:
reader = csv.DictReader(f)
for row in reader:
d = haversine(
user_lat,
user_lon,
float(row["lat"]),
float(row["lon"]),
)
courses.append(
{
"name": row["name"],
"city": row["city"],
"state": row["state"],
"lat": float(row["lat"]),
"lon": float(row["lon"]),
"distance_mi": round(d, 1),
}
)
courses.sort(key=lambda c: c["distance_mi"])
return jsonify(
{
"user": {
"city": geo.get("city"),
"state": geo.get("region"),
"country": geo.get("country"),
"lat": user_lat,
"lon": user_lon,
},
"courses": courses[:5],
}
)
if __name__ == "__main__":
app.run(debug=True)
A request to GET /api/nearby returns JSON like:
{
"user": {
"city": "Scottsdale",
"state": "Arizona",
"country": "US",
"lat": 33.4942,
"lon": -111.9261
},
"courses": [
{
"name": "TPC Scottsdale",
"city": "Scottsdale",
"state": "AZ",
"lat": 33.6405,
"lon": -111.9086,
"distance_mi": 10.1
}
...
]
}
Frontend: Plot the results on a map
Once the backend returns the user location and nearby courses, the frontend is straightforward. Here is a minimal Leaflet example.
<!DOCTYPE html>
<html>
<head>
<link
rel="stylesheet"
href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"
/>
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
<style>
#map { height: 500px; }
</style>
</head>
<body>
<div id="map"></div>
<script>
async function initMap() {
const res = await fetch("/api/nearby");
const data = await res.json();
const map = L.map("map").setView([data.user.lat, data.user.lon], 11);
L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
attribution: "© OpenStreetMap contributors",
}).addTo(map);
// User marker
L.marker([data.user.lat, data.user.lon])
.addTo(map)
.bindPopup(`You are here: ${data.user.city}, ${data.user.state}`)
.openPopup();
// Course markers
data.courses.forEach((course) => {
L.marker([course.lat, course.lon])
.addTo(map)
.bindPopup(
`<b>${course.name}</b><br>${course.distance_mi} miles away`
);
});
}
initMap();
</script>
</body>
</html>
How to use IP Geolocation API
The IP Geolocation API (RapidAPI listing) geolocates any IP address and returns country, city, latitude/longitude, timezone, ISP, and ASN. It also has a dual-source fallback, so you get more reliable results than a single-source service.
cURL example
curl --request GET \
--url 'https://ip-geolocation44.p.rapidapi.com/?ip=8.8.8.8' \
--header 'X-RapidAPI-Key: YOUR_RAPIDAPI_KEY' \
--header 'X-RapidAPI-Host: ip-geolocation44.p.rapidapi.com'
Python example
import requests
url = "https://ip-geolocation44.p.rapidapi.com/"
querystring = {"ip": "8.8.8.8"}
headers = {
"X-RapidAPI-Key": "YOUR_RAPIDAPI_KEY",
"X-RapidAPI-Host": "ip-geolocation44.p.rapidapi.com",
}
response = requests.get(url, headers=headers, params=querystring)
print(response.json())
For more response fields, SDKs, and error handling, check the official docs on RapidAPI and the open-source repo at github.com/On13uka/ip-geolocation-api.
Other ways to use this combo
- Geo-restricted content delivery: Only show US golf courses to US visitors.
- Fraud detection by IP location: Flag bookings where the IP country does not match the billing address.
- Analytics and visitor statistics: Track which cities drive the most golfers to your site.
- Timezone detection for users: Schedule tee-time reminders in the user’s local timezone.
Conclusion
With a free golf-course dataset and the IP Geolocation API, you can turn a static map into a personalized discovery tool in under an hour. No signup friction for the user, no manual location input, and no expensive geolocation stack.
Grab your RapidAPI key at rapidapi.com/On13uka/api/ip-geolocation44, download the Show HN course data, and start routing golfers to their next tee time automatically.
Happy hacking! ⛳
Top comments (0)