Great for road trips: match GPS positions to played Spotify songs.
SpotifyGPX allows you to recount where you listened to each song of a set based on a tracked journey, placing points as close as possible to the location of each song.
SpotifyGPX allows you to create a map of the songs you listened to on Spotify during a journey. Imagine a map that shows not just where you went, but also the soundtrack of your trip! It does this by combining two kinds of data:
- Your Spotify listening history: It gets a list of the songs you played and when you played them from Spotify.
- A GPX file of your journey: A GPX file is like a digital map of your travels. It includes information about your location (latitude and longitude) at different points in time.
Here's how it works:
- You provide SpotifyGPX with these two files: Your Spotify listening history JSON file and the GPX file of your trip.
- It matches up the songs with the locations: It looks at the timestamps in both files to figure out which songs you were listening to at each point along your journey.
Cool things you can do after you return from your journey:
- Visualize your musical journeys: You can use mapping tools to see your route and the songs you listened to along the way, creating a visual memory of your trip.
- Share your musical adventures: You can share the GPX file (or Google MyMaps link) with friends or family so they can experience your trip through your music choices.
- Create playlists based on your travels: You can export a playlist of the songs you listened to during a particular journey, making it easy to relive those memories.
Think of it like a musical scrapbook of your travels!
SpotifyGPX is not endorsed by Spotify Technology SA. It exists only as a third-party tool that you can opt to use with the data Spotify freely provides to you. SpotifyGPX does not interact with Spotify itself in any way. It relies on user-submitted data alone. SpotifyGPX does not exchange your data with any outside parties. In other words, the data you feed SpotifyGPX (including your original GPX tracks and Spotify data) is operated on by your computer alone.
SpotifyGPX does not modify the contents of the files you feed it. It will instead create new files representing its calculated data.
Why don't we just use the Spotify API instead of having users provide JSON? The Spotify API only provides us the last 50 songs played by a user, which is rarely adequate for including their entire journey (if at all).
- .NET 8.0 & C# version 11 installed
- A supported journey source file (see below), containing position data (such as GPX)
- A supported song playback source file (see below), containing played back songs (such as JSON)
- Dependencies of file format handlers (such as Newtonsoft.Json, see formats table for more info)
SpotifyGPX's InputHandler and OutputHandler classes allow you to easily implement your own formats if desired.
See the below Source
links for each format's input or output definition source file, and the below Sample
links for samples of actual data in these formats.
Format | Extension | Input | Output | Type of Data | Hash Support |
---|---|---|---|---|---|
JSON | .json |
Source / Sample (With Newtonsoft.Json) | Source / Sample (With Newtonsoft.Json) | Song Records | |
XSPF | .xspf |
Source / Sample | Source / Sample | Song Records | X |
KML | .kml |
Source | GPS Journey | ||
GPX | .gpx |
Source / Sample | GPS Journey | ||
JsonReport | .jsonreport |
Source / Sample | Source / Sample | Pair Records | X |
GPX | .gpx |
Source / Sample | Pair Records | X | |
KML | .kml |
Source | Pair Records | X | |
CSV | .csv |
Source / Sample | Pair Records | ||
TXT | .txt |
Source / Sample | Pair Records | ||
XLSX | .xlsx |
Source / Sample (With EPPlus) | Pair Records |
SpotifyGPX's OutputHandler class also supports conversion of certain data types to XML.
If -x
is passed, and you have also passed flags for exporting in the below supported formats, an XML of the data will be saved in addition to the targeted format.
For example, if you pass -r
and -x
, the <name>.jsonreport
will be saved in addition to a <name>.jsonreport.xml
representing the JsonReport data in XML-form.
See the below table for the object types (and their corresponding formats) supporting conversion to XML.
Data Source Type | Applicable Output Formats | Supports Conversion to XML |
---|---|---|
List<JObject> |
JSON, JsonReport | Yes |
XDocument |
GPX, KML, XSPF | Yes |
string?[] |
CSV, TXT | Yes |
byte[] |
XLSX | No |
Below are some pre-created XSLT stylesheets for transforming the converted XML of various output formats.
Stylesheet | Transforms from | Transforms to | Description | Sample |
---|---|---|---|---|
copy.xslt | Any XML | An Identical XML | Maintains the identical structure of the original XML in the transformed XML | |
csv.xslt | CSV XML | HTML | Creates a table representing the contents of the CSV table | Sample |
gpx.xslt | GPX | HTML | Creates a table with each song-point pair represented as a row | Sample |
json.xslt | JSON XML | HTML | Creates a table of song playback records | Sample |
jsonreport.xslt | JsonReport XML | HTML | Creates a table for each track, containing the pairings of the corresponding track | Sample |
kml.xslt | KML | HTML | Creates a table with each song-point pair represented as a row | Sample |
txt.xslt | TXT XML | HTML | Creates a bulleted list, each bullet containing a line from the text file, with its contents hyperlinked | Sample |
txt_nolink.xslt | TXT XML | HTML | Creates a bulleted list, each bullet containing a line from the text file | |
xspf.xslt | XSPF | HTML | Creates a table of song playback records | Sample |
HTML created with the above stylesheets works well with the following included CSS stylesheets:
Transforming XML with XSLT stylesheets using SpotifyGPX:
- if there is an
.xslt
file of the same name as a selected output format class in the running directory (ie.jsonreport.xslt
for exporting JsonReports), and, - if the data type of said format is supported for conversion to XML (see above table), and,
- if
-x
is passed
Then, the XSLT stylesheet will be used in the creation of the converted XML.
If -x
is passed and no stylesheet is present, the XML will be saved without transformation.
SpotifyGPX [--spotify <spotify> --gps <gps>] [--pairs <pairs>] [-c] [-g] [-j] [-k] [-p] [-t] [-r] [-e] [-x] [-pp [-pa]] [-s] [-h]
Argument | Description |
---|---|
SpotifyGPX |
Path to the SpotifyGPX executable |
--spotify <spotify> --gps <gps> |
Path to a Spotify playback history and GPS journey file |
--pairs <pairs> |
Path to a pairs file |
-c |
Export a CSV table of all the pairs |
-g |
Export a GPX from the calculated points |
-j |
Export the relevant part of the Spotify json |
-k |
Export a KML from the calculated points |
-p |
Export a XSPF playlist of the songs |
-t |
Export a plain text list of pairs |
-r |
Export a JsonReport of all the data used to compile the resulting pairings |
-e |
Export an Excel workbook of all pairings, grouped into worksheets for each track |
-x |
Export an XML conversion of each file exported (combine this with other format export flags) |
-pp |
Predict new positions for duplicate points (use with -pa for automatic prediction of all duplicate positions) |
-s |
Do not print out each newly created Song-Point pairing upon creation |
-h |
Print the help instructions |
Ensure you take the below steps to prepare before setting off:
- Make sure you have access to the music playback application (ie. Spotify) along the journey
- Use an app such as GPSLogger (for Android) or Open GPX Tracker for iOS + WatchOS to track your position at different points in time along the route
- Ensure a position is saved frequently enough for SpotifyGPX to create accurate pairings, between a song and a point (recommended: 1 point every 15-30 seconds)
- Run a few test logging sessions at short distances. Make sure points are created by your tracker, and that their times have an identifiable time zone (UTC or UTC offset). Compare your test data to the confirmed sample GPX log.
As long as there is song playback and GPS tracking running simultaneously, and that both datasets have times for each record, you will be able to use SpotifyGPX to pair the two sets of data.
To use SpotifyGPX, retrieve the data you tracked:
- Request and download your
Account data
orExtended streaming history
datajson
(see below for a comparison between the two forms) - Copy the appropriate GPX files from the device you used for tracking
- Run SpotifyGPX with the following two files:
Sample | Use case |
---|---|
GPX | The route you took and the times where you were in each place |
JSON | The songs you listened to and the times you listened to them |
SpotifyGPX will allow you to:
- Use each of the coordinates (from the GPX) to identify (with closest possible precision) a position for a song
- Use the exported formats below to parse the song-point positions:
Sample | Use case |
---|---|
CSV | View a table of pairs for each track |
GPX | View a map of where each of your tracks was played using a tool like kepler.gl or Google MyMaps |
JSON | Preserve the original Spotify data (from the original JSON) used for your journey |
JsonReport | Preserve all data SpotifyGPX used to create the pairings for your journey. Includes data from Json. |
KMZ | View a map of where each of your tracks was played using a tool like kepler.gl or Google MyMaps |
TXT | Create a txt file of a Spotify URI (song link) list of the songs on your journey. Paste into Spotify playlists on Desktop. |
XLSX | Complete data analysis and filtration of pairing data \ |
XSPF | Use as a playlist to visualize your journey's songs in an app such as VLC Media Player |
Options.cs contains global and local options variables for various elements within the program.
The following parsing options are given to you when your journey contains multiple track <trk>
elements:
Option | Filters by track of type |
---|---|
The index of an individual track (in the printed list) | That track only (GPX, Gap, or Combined) |
[A] GPX tracks |
GPX |
[B] GPX tracks, and gaps between them |
GPX, Gap |
[C] Gaps between GPX tracks only |
Gap |
[D] GPX tracks and Combined track |
GPX, Combined |
[E] Gap tracks and Combined track |
Gap, Combined |
[F] GPX, Gap, and Combined tracks (everything) |
GPX, Gap, Combined |
Here is an explanation of each track type:
A track generated from:
- GPX - track in the original GPS file
- Gap - gap between tracks in your file
- Combined - all the points in your GPX combined into a single track (ignores track designations in provided GPX)
The differences between the types of data Spotify provides are detailed below.
Extended streaming history
data takes longer for Spotify to send, but contains significantly more information than Account data
.
By default, SpotifyGPX needs a song name, artist name, and end time of each song. An end time value is required at the bare minimum.
JSON tag name | Description |
---|---|
endTime |
Time the song ended |
trackName |
Song Name |
artistName |
Artist Name |
msPlayed |
Number of milliseconds of song playback |
JSON tag name | Description |
---|---|
ts |
This field is a timestamp indicating when the track stopped playing in UTC (Coordinated Universal Time). The order is year, month and day followed by a timestamp in military time |
username |
This field is your Spotify username. |
platform |
This field is the platform used when streaming the track (e.g. Android OS, Google Chromecast). |
ms_played |
This field is the number of milliseconds the stream was played. |
conn_country |
This field is the country code of the country where the stream was played (e.g. SE - Sweden). |
ip_addr_decrypted |
This field contains the IP address logged when streaming the track. |
user_agent_decrypted |
This field contains the user agent used when streaming the track (e.g. a browser, like Mozilla Firefox, or Safari) |
master_metadata_track_name |
This field is the name of the track. |
master_metadata_album_artist_name |
This field is the name of the artist, band or podcast. |
master_metadata_album_album_name |
This field is the name of the album of the track. |
spotify_track_uri |
A Spotify URI, uniquely identifying the track in the form of “spotify:track:<base-62 string >” |
episode_name |
This field contains the name of the episode of the podcast. |
episode_show_name |
This field contains the name of the show of the podcast. |
spotify_episode_uri |
A Spotify Episode URI, uniquely identifying the podcast episode in the form of “spotify:episode:<base-62 string >” |
reason_start |
This field is a value telling why the track started (e.g. “trackdone”) |
reason_end |
This field is a value telling why the track ended (e.g. “endplay”). |
shuffle |
This field has the value True or False depending on if shuffle mode was used when playing the track. |
skipped |
This field indicates if the user skipped to the next song |
offline |
This field indicates whether the track was played in offline mode (“True”) or not (“False”). |
offline_timestamp |
This field is a timestamp of when offline mode was used, if used. |
incognito |
This field indicates whether the track was played in incognito mode (“True”) or not (“False”). |