What's in your Spotify data export, field by field
Updated
When you request your data from Spotify, you get a zip of JSON files. This page explains what those files contain, what each field means, and how StreamHistory uses it. It is also useful if you want to analyse the files yourself in a spreadsheet or a script.
Two formats
Spotify sends listening history in two different shapes, depending on what you ticked:
- Extended streaming history: one record per play for your whole account lifetime, with detailed
fields. Files are named
Streaming_History_Audio_2019-2021_0.json(a year or range of years, then a number) andStreaming_History_Video_2020-2024.jsonfor video plays. Older exports useendsong_0.json,endsong_1.jsonand so on, with the same fields. - Account data: a simpler record covering roughly the last year, in
StreamingHistory_music_0.jsonandStreamingHistory_podcast_0.json(older exports:StreamingHistory0.json).
Each file is a JSON array: a list of objects, one per play. A large history is split across several numbered files. StreamHistory detects the format from the fields, so file names do not matter if you have renamed them.
Extended streaming history fields
Every record has the same set of fields. Fields that do not apply (for example podcast fields on a song) are null.
| Field | Example | Meaning | How StreamHistory uses it |
|---|---|---|---|
| ts | 2021-07-14T18:32:05Z | When the play ended, in UTC. | Converted to your time zone for every date and hour chart. |
| platform | android | The device or app type, sometimes a long technical string. | Grouped into device types for “devices over time”. |
| ms_played | 213400 | How long the item played, in milliseconds. | Total time listened; decides whether a play counts as a stream. |
| conn_country | DE | Two-letter country code of the connection. | Shown only as “countries you listened from”. |
| ip_addr | (an IP address) | The IP address you were connected from. | Ignored; never stored or shown. |
| master_metadata_track_name | Dreams | Song title. | Top songs, search. |
| master_metadata_album_artist_name | Fleetwood Mac | The album's main artist. | Top artists, loyalty, search. |
| master_metadata_album_album_name | Rumours | Album title. | Top albums. |
| spotify_track_uri | spotify:track:0ofHAo… | Spotify's unique ID for the track. | Identifies a song and removes duplicate plays. |
| episode_name | Episode 112: … | Podcast episode title. | Top episodes. |
| episode_show_name | (a podcast name) | The podcast the episode belongs to. | Top podcasts. |
| spotify_episode_uri | spotify:episode:… | Unique ID for the episode. | Identifies episodes and removes duplicates. |
| audiobook_title | (a book title) | Audiobook title, in newer exports. | Counted as audiobook listening. |
| audiobook_uri | spotify:… | Unique ID for the audiobook. | Groups chapters of one book. |
| audiobook_chapter_title | Chapter 3 | Chapter title. | Shown with the audiobook. |
| audiobook_chapter_uri | spotify:… | Unique ID for the chapter. | Removes duplicate plays. |
| reason_start | clickrow | Why playback started (see below). | “Why tracks started” chart. |
| reason_end | trackdone | Why playback ended (see below). | “Why tracks ended” chart. |
| shuffle | true | Whether shuffle was on. | Shuffle share. |
| skipped | false | Whether you skipped to the next track. Often null in older data. | Skip rate. |
| offline | false | Whether it was played in offline mode. | Offline share. |
| offline_timestamp | 1626287525 | When an offline play happened, as a Unix timestamp; the format varies. | Not used. |
| incognito_mode | false | Whether a private session was on. | Private session share. |
Older exports may lack the audiobook fields, and Spotify occasionally adds new ones. StreamHistory ignores fields it does not recognise.
reason_start and reason_end values
These two fields explain how each play began and finished. The values you are likely to see:
trackdone: the previous track finished (start), or this track played to the end (end).fwdbtn: the next button was pressed.backbtn: the previous button was pressed.clickrow: you clicked or tapped a track in a list.playbtn: you pressed play.appload: playback resumed when the app opened.endplay: playback was stopped, for example by starting something else.remote: controlled from another device, such as Spotify Connect, a car or a smart speaker.logout: you logged out while playing.trackerror: the track failed to play.unexpected-exitandunexpected-exit-while-paused: the app closed or crashed.unknown: Spotify did not record a reason.
Spotify does not publish an exact definition of each value, so treat these as reasonable readings rather than official ones.
Account data fields
The streaming history in account data is much simpler. Music files look like this:
| Field | Example | Meaning | How StreamHistory uses it |
|---|---|---|---|
| endTime | 2026-03-02 21:14 | When the play ended, in UTC, to the minute. | Converted to your time zone for charts. |
| artistName | Fleetwood Mac | Artist name. | Top artists. |
| trackName | Dreams | Song title. | Top songs. |
| msPlayed | 213400 | Milliseconds played. | Time listened and the stream threshold. |
| podcastName | (a podcast name) | In podcast files, the show. | Top podcasts. |
| episodeName | Episode 112: … | In podcast files, the episode. | Top episodes. |
There are no albums, track IDs, skip flags or countries here, so some sections (albums, habits) stay empty if you only load account data. Because there is no track ID, StreamHistory treats two rows as the same play when the end time, artist and track match. If you also load the extended history, account rows already present in it are dropped.
The other files in account data
The account data zip also contains files such as Userdata.json (profile details),
YourLibrary.json (saved tracks, albums and artists), Playlist1.json (your playlists),
SearchQueries.json (what you searched for), Inferences.json (interest segments used for
advertising) and others like follow lists and payment details. StreamHistory ignores all of them; only the streaming
history files are read.
Things worth knowing
Timestamps are in UTC
Both ts and endTime are in Coordinated Universal Time, not your local time. A late-night
play in New York appears as the next morning in UTC. StreamHistory converts every play to your browser's time zone,
and you can pick a different one in the settings if you lived somewhere else for years. Note that the timestamp
marks when a play ended, not when it started.
Why some plays have no name
Many records have null in the track, artist and album fields. Usually that is because the record is a
podcast episode or audiobook chapter (those use their own fields), a local file you played from your device, or a
track that was later removed from Spotify. StreamHistory counts the listening time but leaves unnamed songs out of
the top lists.
Short plays are in there too
Every play is recorded, including the ones you skipped after two seconds. That is why the file contains far more rows than you might expect, and why the “number of plays” depends on where you draw the line. StreamHistory counts a stream when at least 30 seconds were played (you can change this to 5, 10 or 60 seconds), while total time listened includes every play. The Wrapped comparison page explains why this can differ from Spotify's figures.
Privacy: be careful sharing the raw files
The extended history contains your IP address for every play and the country you connected from, which together can reveal where you lived and travelled over the years. The account data includes your search queries and profile details. Think twice before posting these files online or sending them to someone. If you want to share your stats, share a summary or an image instead.
In StreamHistory, your file is processed on your device and never uploaded to our servers. The IP address field is skipped while reading. Questions? See the FAQ.