photo-geolocator
Skill0 starsChanged 30 days agoMITView on GitHub
Extract when and where photos were taken using EXIF metadata, then reverse geocode GPS coordinates to venues, restaurants, and addresses. Trigger on "where was this taken," uploaded photos with where/when questions, mapping photos to places, converting GPS coordinates to addresses, or any mention of photo metadata, geolocation, or geotagging. Also the reusable building block when another skill needs date/location from photos.
- Installs packages
We split this skill into the rules it gives an agent
7 rules. About 0 are common, 6 are distinctive, and 1 is very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈6
Distinctive · estimate
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 21
Run the bundled extraction script on the photo directory or individual files:
- Distinctive: line 30
Not all photos have EXIF data — phone cameras almost always do, but screenshots, downloaded images, and some edited photos won't.
- Distinctive: line 54
Run the bundled reverse geocoding script on the unique coordinate clusters:
- Very specific: line 68
Check the name and amenity fields first — sometimes Nominatim returns the venue directly (e.g., "Andrew Edmunds", "Le Dive")
- Distinctive: line 70
If the photo itself shows a venue name (menu, signage, receipt), that's the most reliable identification
- Distinctive: line 80
Recurring locations: If the same GPS cluster appears across many different dates (5+ visits), it's almost certainly the user's home or …
- Distinctive: line 83
Travel patterns: Look at the dates and cities holistically to understand trips.
≈ “Common” is an estimate: at least 1 in 5 of the 308,232 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Photo Geolocator
Extract date, time, and GPS location from photos via EXIF metadata, then reverse geocode coordinates to street addresses and venue names using OpenStreetMap Nominatim.
When to use this skill
- User uploads photos and asks "where was this taken?" or "when was this?"
- Any workflow that needs to go from photo files → dates and locations
- Another skill (like the wine journal) needs date/location extraction as a building block
- User wants to map a set of photos to venues, restaurants, cities, or trips
How it works
Step 1: Extract EXIF data
Run the bundled extraction script on the photo directory or individual files:
pip install Pillow --break-system-packages -q
python3 <skill-path>/scripts/extract_exif.py <directory_or_file>This outputs JSON with file, date, lat, lon for each image. Dates are in YYYY:MM:DD HH:MM:SS format. GPS coordinates are decimal degrees (positive = N/E, negative = S/W).
Not all photos have EXIF data — phone cameras almost always do, but screenshots, downloaded images, and some edited photos won't. When GPS is missing, note it as "Unknown location" rather than guessing.
Step 2: Cluster nearby coordinates
Photos taken at the same venue will have slightly different GPS readings (within ~50m). Before reverse geocoding, cluster coordinates that are within 0.001° of each other (roughly 100m) to avoid redundant API calls.
# Cluster logic: group points within 0.001° lat AND 0.001° lon
clusters = {}
for point in exif_results:
if point['lat'] is None:
continue
matched = False
for key in clusters:
if abs(point['lat'] - key[0]) < 0.001 and abs(point['lon'] - key[1]) < 0.001:
clusters[key].append(point)
matched = True
break
if not matched:
clusters[(point['lat'], point['lon'])] = [point]Step 3: Reverse geocode
Run the bundled reverse geocoding script on the unique coordinate clusters:
python3 <skill-path>/scripts/reverse_geocode.py <coords.json>Where coords.json is a JSON array of {"lat": x, "lon": y} objects. The script respects Nominatim's 1-request-per-second rate limit automatically.
The output includes name (venue name if OSM knows it), road, house_number, neighbourhood, city, country, and amenity.
Step 4: Identify specific venues
Nominatim gives you the street address, but often not the specific restaurant or bar. To identify the actual venue:
- Check the
nameandamenityfields first — sometimes Nominatim returns the venue directly (e.g., "Andrew Edmunds", "Le Dive") - For addresses without a venue name, use WebSearch to search for restaurants/bars at that specific address:
restaurant "123 Main Street" [city] - If the photo itself shows a venue name (menu, signage, receipt), that's the most reliable identification
- For coordinates in residential areas visited repeatedly across many dates, these are likely the user's home — flag as "Home ([neighborhood])" rather than searching for restaurants
- For coordinates on park drives or waterfront walkways, these are likely outdoor picnics — flag as "[Park name] (picnic)" or "Waterfront (outdoor)"
Step 5: Present results
Return a structured summary with: date (reformatted to YYYY-MM-DD), city/neighborhood, specific venue (if identified), and the street address as fallback.
Tips for accuracy
- Recurring locations: If the same GPS cluster appears across many different dates (5+ visits), it's almost certainly the user's home or office, not a restaurant.
- Same-day clusters: Multiple photos at the same coordinates on the same day are the same venue visit. Group them.
- Sequential photos: Photos taken minutes apart at the same coordinates are the same event (e.g., front and back of a wine label, multiple dishes at dinner).
- Travel patterns: Look at the dates and cities holistically to understand trips. E.g., Dublin → London on consecutive days = a Europe trip.
Dependencies
- Python 3 with Pillow (
pip install Pillow --break-system-packages) - Internet access for Nominatim reverse geocoding and WebSearch for venue identification
In this repository38 other files it gives its agents.
- AGENTS.mdAGENTS.md
- 3d-bloom-sceneSkill
- api-design-reviewSkill
- api-drift-scoutSkill
- api-prompt-optimizerSkill
- autonomy-mapSkill
- behavior-spec-canvasSkill
- cloudflare-deploySkill
- database-designSkill
- docker-debugSkill
- eval-frameworkSkill
- force-graph-3dSkill
- gh-fix-ciSkill
- git-workflowsSkill
- glassmorphic-uiSkill
- imagegenSkill
- interactive-artifact-generatorSkill
- pdfSkill
- playwright-interactiveSkill
- playwrightSkill
- pr-shell-safety-packSkill
- react-query-test-harness-fixerSkill
- repo-first-vercel-buildSkill
- screenshotSkill
- scrutiny-feature-reviewerSkill
- sdk-ui-override-specialistSkill
- security-auditSkill
- security-best-practicesSkill
- security-ownership-mapSkill
- security-threat-modelSkill
- seeded-catalog-syncSkill
- speechSkill
- testing-strategySkill
- transcribeSkill
- user-testing-flow-validatorSkill
- windows-cli-wsl-repairSkill
- windows-node-sandbox-troubleshootingSkill
- workerSkill
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
Reviews can't be read right now.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

