A powerful, web-based GPX track editor for simplifying, editing, splitting, and joining GPS tracks. Perfect for cleaning up recorded tracks from apps like GeoTracker before sharing or analyzing.
π Live App: https://asg49.github.io/GPXWeaver/
- Fast load for massive files β tested with 500,000+ points in 120MB+ GPX files
- Toggle-only marker visibility β no automatic recalculation on zoom, fast zooming at any scale
- Clean default β only the track line is shown on load; markers appear only when you ask for them
- Douglas-Peucker algorithm for intelligent point reduction
- Manual simplification at any percentage (1β95%) β no auto-simplification
- Restore Original to undo simplification at any time
- Simplification respects your current marker visibility setting
- Manual toggle only β "ββ Points OFF / β Points ON" button controls all marker display
- No automatic zoom-based marker loading β zoom freely without performance hits
- Marker colors: π΄ Red (normal/delete mode) Β· π Orange (split mode)
- Drag points β move any point to adjust position (coordinates rounded to 6 decimal places)
- Add points β tap the track line to insert new waypoints with interpolated ele, time, speed, and course
- Delete points β long-press (2.6s) on any point to mark for deletion
- Rectangle Selection β draw a rectangle to bulk-select and delete multiple points (works on mobile and desktop)
- All edits update the track line in real time
- Split mode β tap any point to divide the track at that location
- Save individual segments as separate GPX files
- Split markers auto-clean after save
- Smart multi-file loading β select 2+ files and they join automatically
- Select 1 file = load normally; select multiple = auto-join
- Logarithmic gap threshold slider (10m β 1,000km)
- Prevents unwanted connector lines between segments in joined or recorded tracks
- Adjustable in real time
- OpenStreetMap
- OpenTopoMap (topographic contours)
- Google Terrain (default)
- Google Satellite
- Google Hybrid
- Esri World Imagery
Desktop:
- Zoom display + Points toggle β bottom-left
- Scale bar β bottom-right
- Layer selector β top-right
Mobile:
- Zoom display β top-left (below +/β buttons)
- Points toggle β top-right
- Scale bar β bottom-right
- Save filename uses the actual disk filename you loaded, not the internal GPX track name
- Edited files get
_Xsuffix (e.g.MyHike_X.gpx) - Saved GPX always includes a
<metadata>block with save filename and UTC timestamp - All original
<trkpt>data preserved on save: elevation, time, speed, course, extensions - Coordinate precision: always 6 decimal places (~0.11m β more than sufficient for GPS)
- GeoTracker extensions (
<geotracker:meta c="course" s="speed"/>) fully preserved and interpolated for added points
- HTML sanitization on all track name display (
sanitizeHTML()) - XML sanitization on all GPX output (
sanitizeXML()) - Protects against malicious GPX files with injected content
- Responsive layout for phones and tablets
- Touch-friendly controls including rectangle selection (fixed
changedTouchesfor reliable touch-end detection) - Compact header with current filename displayed
- Load a GPX file β Menu (β°) β Load GPX File β select file(s)
- Select multiple files to auto-join them
- View your track β blue line shown immediately; no markers until you ask
- Show markers β click "ββ Points OFF" β becomes "β Points ON"
- Edit β drag points, tap line to add, long-press to delete, or draw a rectangle to bulk-delete
- Simplify β Menu β adjust slider β Apply Simplification β Restore Original if needed
- Save β Menu β Save GPX β file saves with
_Xsuffix using your original filename
- Menu β Enable "Rectangle Select"
- Draw a rectangle over the points you want to remove
- Tap "Delete Selected" to remove them all at once
- Menu β Enable "Split Mode"
- Tap the point where you want to split
- Save β downloads as separate GPX files
- Auto: Menu β Load GPX File β select 2+ files at once
- Manual: Menu β Load Multiple Files β Join All Tracks
- Menu β adjust Gap Detection slider
- Increase to hide connector lines between segments
- Works in real time
- Input:
.gpxfiles (GPX 1.0 and 1.1) - Output: GPX 1.1, all original
<trkpt>data preserved (ele, time, speed, course, extensions) - Metadata:
<metadata>block added to every saved file with name and timestamp - Coordinates: 6 decimal places in all output
| Control | Desktop | Mobile |
|---|---|---|
| Zoom +/β | top-left | top-left |
| Zoom display | bottom-left | top-left |
| Points toggle | bottom-left | top-right |
| Layer selector | top-right | top-right |
| Scale bar | bottom-right | bottom-right |
- Single HTML file β no dependencies to install, works offline after first load
- Leaflet.js mapping library
- Douglas-Peucker simplification algorithm
- File System Access API for save location control
- All event listeners properly registered inside
DOMContentLoaded - XSS protection on all user-generated content inserted into HTML or XML
β v6.2 β Code correctness & GPX metadata
- All event listeners moved inside
DOMContentLoaded(was causing menu/layer control failures) - GPX
<metadata>block (filename + UTC timestamp) added to all saved files - Coordinate precision fixed to 6 decimal places in all three GPX generators
- CSS header conflict fixed (duplicate
#headerrule withposition: relativewas hiding header)
β v6.1 β Coordinate precision
- Dragged and added points now stored and output at 6 decimal places (was 15+)
β v6.0 β GeoTracker data preservation
- Full
<trkpt>innerHTMLpreserved on load and save (speed, course, extensions, all tags) interpolateSpeed()andinterpolateCourse()for added points (with 0Β°/360Β° wrap handling)- Comprehensive code audit: XSS sanitization, dead code removal, duplicate function removed, logic consistency
β v5.99 β trkpt round-tripping
- All three GPX generators now output
innerXMLverbatim for existing points - Synthesized points fall back to ele/time only
β v5.98 β Header filename display
- Current filename shown in header bar (right-aligned, between title and β°)
- Updates to
_Xsuffix on first edit; clears on track clear; hidden in join mode
β v5.97 β Save filename fix
- Save now uses the actual disk filename, not the internal GPX
<name>tag markAsEdited()appends_Xto the disk filename
β v5.96 β Security & logic audit
sanitizeHTML()andsanitizeXML()added and applied throughout- Removed duplicate
generateGPXForTrack(), dead code, unused constants - All
createMarkers()calls now respect toggle-only rule
β v5.95 β Toggle-only marker visibility
- Removed all auto-zoom-based marker display
zoomendhandler does safety cleanup only β no marker recalculation- Fast zooming at any zoom level, any file size
β v5.94 β Rectangle selection mobile fix
- Root cause:
e.touchesis empty ontouchend(finger already lifted) - Fixed
getEventPoint()to usee.changedTouches - Rectangle selection now works reliably on mobile
β v5.87 β Mobile control layout
- Zoom at top-left, Points toggle at top-right, scale at bottom-right on mobile
- Desktop unchanged: zoom + toggle at bottom-left
- Fixed all event listeners to be inside
DOMContentLoaded(menu and layer dropdown were broken) - Added
<metadata>block (filename + UTC timestamp) to all saved GPX files - Fixed coordinate precision to 6 decimal places in
generateGPXForTrack()(was using raw float) - Fixed CSS duplicate
#headerrule hiding the header bar - Fixed
deleteSelectedPoints()to use disk filename for_Xsuffix
- Fixed dragged points: stored at 6 decimal places (was full float precision ~15 digits)
- Fixed added points: stored at 6 decimal places
- Fixed multitrack GPX generators:
toFixed(7)βtoFixed(6)
- Parses GeoTracker
<geotracker:meta c="course" s="speed"/>extensions interpolateSpeed()andinterpolateCourse()for added points- Added points now include interpolated extensions in their
innerXML - Major code audit: XSS sanitization, dead code removal, brace/indentation fixes, operator precedence, consistent creator version across all GPX generators
- All
<trkpt>data preserved through edits viainnerXMLcapture on parse - All three GPX generators output
innerXMLverbatim for existing points
- Filename displayed in header bar (right-aligned, italic, truncates if too long)
- Cleared on track clear; not shown in join mode
- Save uses actual disk filename (not internal GPX track name)
markAsEdited()appends_Xto disk filename, updates header display
sanitizeHTML()andsanitizeXML()added; applied to all track name insertions- Removed duplicate
generateGPXForTrack()function - Removed dead
adjustSimplifyForTarget(), unusedZOOM_THRESHOLDconstants, empty stubs - All
createMarkers()calls enforce toggle-only rule clearMarkers()state management fixedclearSelection()null-check ongetElement()- Fixed
percentToTolerance()indentation, operator precedence ininteractive:option - All three GPX generators use consistent
creator="GPXWeaver vX.X"
- Removed all automatic zoom-based marker visibility
zoomendhandler now only does safety cleanup- Toggle button sole control: "ββ Points OFF" / "β Points ON"
- Fast zooming at any zoom level, no recalculation overhead
- Fixed rectangle selection on mobile (
e.changedTouchesinstead ofe.touches) - Fixed
clearMarkers()to always remove markers from map
- Mobile controls: zoom top-left, toggle top-right, scale bottom-right
- Desktop unchanged
- Fixed unconditional marker creation after simplification and restore
- Smart multi-file auto-join
- Logarithmic gap threshold slider (10mβ1,000km)
- Restore Original button; auto-simplification removed
- Core features: rectangle selection, track splitting/joining, gap detection, Douglas-Peucker simplification, multi-map layers, lazy marker loading
MIT License β see LICENSE file for details.
Tony Gozdz Β© 2026
Battery & 3D Printing R&D Engineer Β· Serious GPX Geek πΊοΈ
Open an issue on GitHub with your browser/device info and a description of the problem.
Tested with files from 100 to 500,000+ points (120MB+ GPX). Handles extreme files efficiently. All editing operations β drag, add, delete, rectangle select, split, join, simplify β work reliably on both mobile and desktop.