| src | ||
| .gitignore | ||
| deno.json | ||
| DISTRIBUTION.md | ||
| main.ts | ||
| README.md | ||
gmapsConvert
Convert Google Maps CSV exports to GeoJSON or GPX format using the Nominatim geocoding service.
Features
- Converts Google Maps saved places (CSV format) to GeoJSON or GPX
- Batch processing: Process multiple CSV files at once using glob patterns
- Waypoint colors: Customize waypoint colors with hex codes or named colors (compatible with OsmAnd)
- Uses OpenStreetMap's Nominatim API for geocoding
- Supports both GeoJSON and GPX 1.1 output formats
- Auto-detects output format from file extension
- Auto-generates smart collection names from filenames
- Custom collection naming with
-nflag - Respects Nominatim's rate limiting (1 request/second)
- Reports failed geocoding attempts
- Simple CLI interface
Requirements
Option 1: Using Pre-built Binary (Recommended)
No requirements! Download the pre-built binary for your platform from the releases page.
Option 2: Running from Source
- Deno 2.x or higher
Installation
Using Pre-built Binary
-
Download the appropriate binary for your platform:
- macOS (Apple Silicon):
gmaps-convert-macos-arm64 - macOS (Intel):
gmaps-convert-macos-x64 - Windows:
gmaps-convert-windows-x64.exe - Linux (x64):
gmaps-convert-linux-x64 - Linux (ARM64):
gmaps-convert-linux-arm64
- macOS (Apple Silicon):
-
Make it executable (macOS/Linux only):
chmod +x gmaps-convert-macos-arm64 -
Run it:
./gmaps-convert-macos-arm64 input/restaurants.csv -
(Optional) Move to PATH for global access:
# macOS/Linux sudo mv gmaps-convert-macos-arm64 /usr/local/bin/gmaps-convert # Now use from anywhere gmaps-convert ~/Downloads/places.csv
From Source
Clone this repository:
git clone <repository-url>
cd gmapsConvert
No additional installation steps required - Deno handles all dependencies automatically.
Usage
Using Pre-built Binary
# Basic usage (defaults to GeoJSON format)
./gmaps-convert input/restaurants.csv
# Convert to GPX format
./gmaps-convert input/restaurants.csv -f gpx
# Auto-detect format from file extension
./gmaps-convert input/restaurants.csv -d output/places.gpx
# Specify output file
./gmaps-convert input/restaurants.csv -d output/places.geojson
# Custom collection name
./gmaps-convert my_paris_places.csv -n "Best Places in Paris"
# Show help
./gmaps-convert --help
Using Deno (From Source)
Basic Usage
Convert a CSV file to GeoJSON (default format):
deno task convert input/restaurants.csv
This creates restaurants.geojson in the current working directory.
Convert to GPX format:
deno task convert input/restaurants.csv -f gpx
This creates restaurants.gpx in the current working directory.
Specify Output File and Format
Use the -d flag to specify a custom output path:
# GeoJSON format (auto-detected from extension)
deno task convert input/restaurants.csv -d output/my-places.geojson
# GPX format (auto-detected from extension)
deno task convert input/restaurants.csv -d output/my-places.gpx
# Explicit format flag (overrides extension)
deno task convert input/restaurants.csv -f gpx -d output/my-places.json
Direct Execution
You can also run the tool directly without using tasks:
deno run --allow-net --allow-read --allow-write main.ts input/restaurants.csv
Help
Show help information:
deno task convert --help
Collection Naming
The tool automatically generates a collection name for the output files based on the input filename. This name appears in:
- GPX:
<metadata><name>element - GeoJSON:
metadata.nameproperty
Auto-Generated Names
By default, the collection name is generated from the input filename:
- File extension (
.csv) is removed - Underscores (
_) are replaced with spaces - Multiple consecutive spaces are collapsed to a single space
- Smart title case is applied:
- First word is always capitalized
- Articles, prepositions, and conjunctions remain lowercase (except at start)
- Dashes are preserved
Examples:
my_favorite_places.csv→"My Favorite Places"eat_and_drink.csv→"Eat and Drink"paris-restaurants.csv→"Paris-restaurants"best___places.csv→"Best Places"(multiple underscores collapsed)
Custom Names
Use the -n or --name flag to specify a custom collection name:
# Using binary
./gmaps-convert my_places.csv -n "Best Coffee Shops in Paris"
# Using Deno
deno task convert my_places.csv -n "Mom's Favorite Restaurants"
Custom names are preserved exactly as provided (including capitalization and special characters).
Waypoint Colors
You can customize the color of waypoints using the -c, --color, or --colour flag. Colors are supported in both GPX and GeoJSON output formats.
Supported Color Formats
-
Named colors (case-insensitive, 30 standard colors):
gmaps-convert places.csv -c red -f gpx gmaps-convert places.csv -c darkgreen -f geojson -
Hex colors (3, 6, or 8 digit format):
# 6-digit hex (RRGGBB) gmaps-convert places.csv -c "#FF0000" -f gpx # 3-digit hex (RGB - expands to RRGGBB) gmaps-convert places.csv -c "#F00" -f gpx # 8-digit hex with alpha/transparency (RRGGBBAA) gmaps-convert places.csv -c "#80FF0000" -f gpx # 50% transparent redNote: Use quotes around hex colors to prevent shell interpretation of
#.
Available Named Colors
aqua, black, blue, cyan, darkblue, darkcyan, darkgray, darkgreen, darkgrey, darkmagenta, darkred, darkyellow, fuchsia, gray, green, grey, lightgray, lightgrey, lime, magenta, maroon, navy, olive, purple, red, silver, teal, white, yellow, darkyellow
How Colors Work
-
GPX format: Colors are stored in the
<extensions>section using multiple color tags for maximum compatibility. The tool writes all four fallback tags that OsmAnd and other GPX readers check:<wpt lat="48.8582599" lon="2.2945006"> <name>Eiffel Tower</name> <extensions> <osmand:color xmlns:osmand="https://osmand.net">#FF0000</osmand:color> <osmand:colour xmlns:osmand="https://osmand.net">#FF0000</osmand:colour> <osmand:displaycolor xmlns:osmand="https://osmand.net">#FF0000</osmand:displaycolor> <osmand:displaycolour xmlns:osmand="https://osmand.net">#FF0000</osmand:displaycolour> <!-- other extensions --> </extensions> </wpt>Compatibility: Writing all four tags (
color,colour,displaycolor,displaycolour) ensures the color is recognized by OsmAnd and other GPX applications, regardless of which tag name they check first. -
GeoJSON format: Colors are stored as a
colorproperty in each feature's properties object.{ "type": "Feature", "properties": { "title": "Eiffel Tower", "color": "#FF0000", ... } } -
Batch mode: The same color is applied to all waypoints in all files when processing multiple files.
Color Examples
# Using pre-built binary with named color
./gmaps-convert places.csv -c blue -f gpx
# Using Deno with hex color
deno task convert places.csv -c "#00FF00" -f gpx
# Batch processing with color (applies to all files)
./gmaps-convert input/*.csv -d output/ -f gpx -c red
# British spelling variant
gmaps-convert places.csv --colour purple -f gpx
# With transparency (50% opacity green)
gmaps-convert places.csv -c "#8000FF00" -f gpx
OsmAnd Compatibility
The GPX color implementation follows OsmAnd's GPX color extension standard, ensuring that colored waypoints display correctly in OsmAnd and other compatible applications.
Batch Processing
Process multiple CSV files at once using shell glob patterns or explicit file lists. All files will be geocoded and converted to the output directory.
Basic Batch Usage
Using glob patterns (shell expansion):
# Using binary
./gmaps-convert input/*.csv -d output/
# Using Deno
deno task convert input/*.csv -d output/
Using brace expansion:
# Process specific files
./gmaps-convert input/{eat,drink,hipster}.csv -d output/
# Process with format
deno task convert input/{eat,drink,hipster}.csv -d output/ -f gpx
Using explicit file list:
./gmaps-convert input/eat.csv input/drink.csv input/hipster.csv -d output/
Batch Processing Behavior
When processing multiple files:
-
Output directory required: Use
-dwith a directory path ending in/- Creates the directory if it doesn't exist
- Files are automatically named based on input filenames
-
Auto-generated names: Collection names are automatically generated from each filename
- The
-nflag is ignored in batch mode (with a warning) - Each file gets its own collection name
- The
-
Format applies to all: The
-fflag (or auto-detection) applies to all files# All files will be converted to GPX ./gmaps-convert input/*.csv -d output/ -f gpx -
Error handling: Processing continues even if individual files fail
- Failed files are reported in the final summary
- Exit code is 1 if any file fails
-
Progress display: Shows per-file progress and batch summary
Processing file 1/5: input/eat.csv Processing file 2/5: input/drink.csv ...
Batch Examples
Process all CSV files to GeoJSON:
./gmaps-convert input/*.csv -d output/
Process all CSV files to GPX:
deno task convert input/*.csv -d output/ -f gpx
Process specific files:
./gmaps-convert input/eat.csv input/drink.csv input/hipster.csv -d results/
Create output directory automatically:
# Directory will be created if it doesn't exist
./gmaps-convert input/*.csv -d new-directory/
Batch Output Example
============================================================
BATCH PROCESSING: 3 files
============================================================
Output directory: output/
Output format: GEOJSON
============================================================
────────────────────────────────────────────────────────────
Processing file 1/3: input/eat.csv
────────────────────────────────────────────────────────────
...
============================================================
BATCH PROCESSING SUMMARY
============================================================
Files processed: 3
✓ Successful: 3
✗ Failed: 0
Total entries: 120
✓ Successfully geocoded: 115
✗ Failed to geocode: 5
Output directory: output/
────────────────────────────────────────────────────────────
PER-FILE RESULTS
────────────────────────────────────────────────────────────
✓ eat.csv → eat.geojson
75/77 geocoded
✓ drink.csv → drink.geojson
30/31 geocoded
✓ hipster.csv → hipster.geojson
10/12 geocoded
Shell Compatibility
Glob pattern expansion is handled by your shell (bash, zsh, fish, etc.) before the command runs:
- Works:
gmaps-convert input/*.csv -d output/(shell expands*.csvto individual files) - Important: Glob patterns must match at least one file, or your shell will error
Windows users (PowerShell/CMD):
# PowerShell also supports glob expansion
.\gmaps-convert.exe input\*.csv -d output\
# Or use explicit lists
.\gmaps-convert.exe input\eat.csv input\drink.csv -d output\
CSV Format
The tool expects CSV files exported from Google Maps with the following columns:
Title- Place name (used for geocoding)Note- Notes about the placeURL- Google Maps URLTags- Tags/categoriesComment- Additional comments
Note: Only the Title column is used for geocoding. Rows with empty titles are skipped silently.
Output Formats
GeoJSON Format (Default)
The tool generates a valid GeoJSON FeatureCollection with the following structure:
{
"type": "FeatureCollection",
"metadata": {
"name": "My Favorite Places",
"generated": "2026-01-05T12:00:00.000Z"
},
"features": [
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [longitude, latitude]
},
"properties": {
"title": "Place Name",
"color": "#FF0000",
"display_name": "Full address from Nominatim",
"type": "restaurant",
"class": "amenity",
"importance": 0.5,
"place_id": 12345,
"osm_type": "node",
"osm_id": 67890
}
}
]
}
GPX Format
The tool can also generate GPX 1.1 (GPS Exchange Format) files compatible with GPS devices and mapping applications:
<?xml version="1.0" encoding="UTF-8"?>
<gpx version="1.1" creator="gmaps-convert" xmlns:osmand="https://osmand.net">
<metadata>
<name>My Favorite Places</name>
<desc>Converted from Google Maps CSV export using gmaps-convert</desc>
<time>2026-01-05T12:00:00.000Z</time>
<bounds minlat="48.8582" minlon="2.2945" maxlat="48.8611" maxlon="2.3380"/>
</metadata>
<wpt lat="48.8582599" lon="2.2945006">
<name>Eiffel Tower</name>
<desc>Tour Eiffel, 5, Avenue Anatole France...</desc>
<type>tower</type>
<src>Nominatim</src>
<extensions>
<osmand:color xmlns:osmand="https://osmand.net">#FF0000</osmand:color>
<osmand:colour xmlns:osmand="https://osmand.net">#FF0000</osmand:colour>
<osmand:displaycolor xmlns:osmand="https://osmand.net">#FF0000</osmand:displaycolor>
<osmand:displaycolour xmlns:osmand="https://osmand.net">#FF0000</osmand:displaycolour>
<nominatim:place_id>89233259</nominatim:place_id>
<nominatim:class>man_made</nominatim:class>
<nominatim:importance>0.62</nominatim:importance>
<nominatim:osm_type>way</nominatim:osm_type>
<nominatim:osm_id>5013364</nominatim:osm_id>
<!-- Additional Nominatim data in extensions -->
</extensions>
</wpt>
</gpx>
GPX files include:
- Standard GPX waypoint data (name, description, type, coordinates)
- Metadata with timestamp and bounding box
- Waypoint colors with multiple fallback tags for broad compatibility (color, colour, displaycolor, displaycolour)
- All Nominatim fields in custom extensions (place_id, osm_type, importance, etc.)
- Compatible with GPS devices, mapping apps, and GIS software (especially OsmAnd)
Format Selection
The output format can be specified in three ways (in order of precedence):
-
Explicit format flag (highest priority):
gmaps-convert input.csv -f gpx gmaps-convert input.csv -f geojson -
Auto-detect from file extension:
.gpx→ GPX format.geojsonor.json→ GeoJSON format
gmaps-convert input.csv -d output.gpx # GPX format gmaps-convert input.csv -d output.geojson # GeoJSON format -
Default to GeoJSON (if no format specified and no valid extension)
Extension Validation:
- Valid extensions:
.geojson,.json,.gpx - Invalid extensions (like
.txt,.xml) will trigger a warning and default to GeoJSON - Use
-fflag to override extension-based detection
Rate Limiting
This tool uses the public Nominatim API operated by OpenStreetMap. According to their usage policy:
- Maximum 1 request per second
- Proper User-Agent header is sent with all requests
Processing time: A CSV file with 100 places will take approximately 100 seconds to process due to rate limiting.
Error Handling
- Rows with empty titles are skipped silently
- Failed geocoding attempts are reported at the end of processing
- Places that couldn't be found are not included in the output file
- A summary shows successful and failed geocoding attempts
- Batch mode: Processing continues even if individual files fail; failed files are reported in the final summary
Examples
Example 1: Convert to GeoJSON (default)
deno task convert input/eat.csv
Output: eat.geojson in current directory
Example 2: Convert to GPX format
deno task convert input/eat.csv -f gpx
Output: eat.gpx in current directory
Example 3: Auto-detect format from extension
deno task convert input/eat.csv -d output/restaurants.gpx
Output: output/restaurants.gpx (GPX format auto-detected)
Example 4: Custom output location with GeoJSON
deno task convert input/eat.csv -d output/restaurants.geojson
Output: output/restaurants.geojson
Example 5: Custom collection name
deno task convert my_paris_places.csv -n "Best Restaurants in Paris" -f gpx
Output: my_paris_places.gpx with metadata name "Best Restaurants in Paris"
Example 6: Process from a different directory
cd /path/to/your/data
deno run --allow-net --allow-read --allow-write /path/to/gmapsConvert/main.ts places.csv -f gpx
Output: places.gpx in /path/to/your/data/
Building from Source
If you want to create your own standalone executable:
Build for Current Platform
deno task build
This creates a gmaps-convert executable in the current directory (~95-100 MB).
Build for All Platforms
deno task build:all
This creates binaries for all supported platforms in the dist/ directory:
gmaps-convert-macos-arm64- macOS Apple Silicon (M1/M2/M3)gmaps-convert-macos-x64- macOS Intelgmaps-convert-windows-x64.exe- Windows x64gmaps-convert-linux-x64- Linux x64gmaps-convert-linux-arm64- Linux ARM64
Note: On first cross-compile, Deno will download the runtime for each target platform (~50MB per platform). These are cached for future builds.
Binary Details
- Size: ~95-100 MB (includes slimmed-down Deno runtime)
- No Runtime Required: Recipients don't need Deno installed
- Permissions: Network, read, and write permissions are baked into the binary
- Cross-Platform: Build for any platform from any platform
Sample Output
Reading CSV file: input/eat.csv
Found 77 valid entries to geocode
Geocoding locations (rate limited to 1 request/second)...
[1/77] Geocoding: Marino's Fish Bar - Rye
✓ Found: Marino's Fish Bar, 24, Tower Street, Rye, Wealden, East...
[2/77] Geocoding: Les Cèdres - Restaurant associatif
✓ Found: Les Cèdres, 7, Rue Charles de Gaulle, Grenoble, Isère,...
...
============================================================
SUMMARY
============================================================
Collection name: Eat
Total entries processed: 77
Successfully geocoded: 73
Failed to geocode: 4
Output format: GEOJSON
Output file: eat.geojson
============================================================
FAILED LOCATIONS
============================================================
- Unknown Place XYZ
Reason: No results found
Attribution
This tool uses:
- Nominatim by OpenStreetMap for geocoding
- Deno runtime
- Deno Standard Library for CSV parsing and path utilities
When using the generated GeoJSON files, please provide appropriate attribution to OpenStreetMap contributors as per the ODbL license.
License
This project is open source. See LICENSE file for details.
Contributing
Contributions are welcome! Please feel free to submit issues or pull requests.
Troubleshooting
"CSV file not found" error
Make sure the path to your CSV file is correct. Use relative or absolute paths.
"Import not found" errors
Run deno cache --reload main.ts to refresh dependencies.
Slow processing
This is expected due to Nominatim's rate limiting (1 request/second). Processing 100 places takes about 100 seconds.
No results for a place
Some place names may not geocode correctly if they're too generic or misspelled. Check the "FAILED LOCATIONS" section in the output for details.