Google Takeout exports YouTube watch history as a single JSON array where every element is one viewing event. The structure is stable and small, which is good news: a decade of viewing is usually a few megabytes of text, not the multi-gigabyte archive people brace for. What trips people up is not the size but the assumptions. The file records far less than most viewers expect, and several fields quietly disappear on videos that no longer exist. This reference walks the format field by field so you know what any analysis of it can honestly claim.
The shape of a single entry
Each element of the array is a flat object. There is no nesting beyond a single subtitles array, and no per-video metadata block. The same handful of keys repeat for every entry from your first watch to your most recent.
The fields that matter for analysis are the following.
- title — the video title, prefixed with the literal string 'Watched '. The prefix is part of the value, not a separate field, so any parser has to strip it.
- titleUrl — the canonical watch URL in the form https://www.youtube.com/watch?v=VIDEO_ID. This is where a video ID comes from; there is no separate id field.
- subtitles — an array that in practice holds a single object with name and url, identifying the channel.
- time — an ISO 8601 timestamp for the view. Every chart anyone builds from this file ultimately comes from this one field.
- activityControls — an array naming which Google setting recorded the entry. Watch events list 'YouTube watch history'.
What disappears on removed and private videos
This is the single biggest source of confusion. When a video is deleted, made private, or taken down after you watched it, YouTube can no longer supply its metadata, and Takeout writes a degraded entry instead of omitting it.
Those entries read 'Watched a video that has been removed'. There is no real title to recover, no titleUrl, and typically no subtitles array, which means no channel name either. The timestamp survives.
The practical consequence is that removed videos still count toward your totals and still appear in your activity timeline, but they cannot appear in a top-channels ranking, because there is no channel attached. A tool that shows 4,000 views but only attributes 3,600 of them to channels is not losing data; it is being honest about a gap that Google created. Our analyzer labels these 'Unknown Channel' rather than dropping them, so the totals stay consistent.
What the export does not contain
The omissions matter more than the fields. watch-history.json is a log of events, not of engagement, and it carries none of the following.
There is no watch duration. The file does not record whether you watched ten seconds or the whole video. There is also no video length, so duration cannot be derived either. Any tool that shows you 'total hours watched' from a Takeout export is multiplying your view count by an assumed average length. That is an estimate wearing the costume of a measurement, and it can be wrong by an order of magnitude if you watch a lot of Shorts or a lot of long-form video.
There is also no like, comment, or subscription data in this file, no view counts, no categories or tags, and no thumbnail. Those live in separate Takeout files or nowhere at all. And there is no device or location field, so the export cannot tell you whether a view happened on a phone or a TV.
Reading timestamps correctly
The time field is an ISO 8601 string, which makes it unambiguous — it carries its own offset, so there is no guessing about which timezone a view happened in.
That matters for the charts people care about most. A 'what hour do I watch?' histogram is only meaningful if every timestamp is normalised the same way, and it will shift if some entries are interpreted as local time and others as UTC. This is the main technical reason to prefer the JSON export over the HTML one, where dates are written in your account's display language and have to be parsed heuristically.
If you travel across timezones, remember that the histogram shows clock time at the moment of viewing, not time relative to your body. A month abroad will smear your evening peak.
Where the file sits in the archive
Inside the Takeout archive, the file lives under the 'YouTube and YouTube Music' folder, in a 'history' subfolder, named watch-history.json.
You do not have to go looking for it manually. Our analyzer accepts the .zip or .tgz straight from Takeout and locates the history file inside, scoring candidates by filename and content so that a combined MyActivity.json export is also recognised. The tar reader runs in your browser alongside the rest of the analysis, so unpacking never requires uploading anything.
Getting a video ID out of titleUrl
There is no id field. The video ID has to come out of titleUrl, and the obvious approach of splitting the string on 'v=' and taking what follows is the one that breaks.
It breaks because the watch URL can carry more than one parameter. A link copied out of a playlist arrives with a list= value attached, one copied from the mobile app arrives with a share-tracking si= parameter, and a link shared at a timestamp carries t=. Split naively and the ID silently absorbs whatever came after it, so the same video ends up counted as several different videos and your top-videos list fragments.
Parse the URL properly and read the v parameter as a parameter. In a browser that is one line: new URL(entry.titleUrl).searchParams.get('v'). The distinct-video count you get afterwards is the one worth trusting.
Sanity checks before you trust any analysis
Before reading conclusions off a chart, spend thirty seconds confirming the file is what you think it is. Three checks catch almost every problem.
Check the size. Watch history is text only, so even many years of heavy viewing usually lands in single-digit megabytes. A file of a few kilobytes means the export did not include history; a file of hundreds of megabytes means you exported far more than history.
Check the date range against your memory. If the earliest entry is far more recent than when you started using the account, something trimmed the tail — most often auto-delete.
Check the removed-video share. A large gap between total views and views with a known channel is normal for old histories, but if nearly everything is unattributed, you are probably looking at a parsing failure rather than a decade of deleted videos.
How a history file is recognised inside an archive
You can hand our analyzer the whole Takeout archive rather than hunting for the right file, because it scores every candidate it finds and takes the best one rather than trusting a fixed path. Google has changed folder layouts before, and localised account exports do not always use English folder names.
The scoring is weighted toward filename first: watch-history.json scores highest, watch-history.html slightly lower, and a combined MyActivity.json lower again but still eligible. Path hints add to the score when the route contains 'youtube', 'history', or 'takeout'.
Content is then checked as a tiebreak. A file whose opening bytes mention 'youtube watch history' gains a large bonus, and one containing 'watched ' or the content-cell class used by the HTML export gains a smaller one. The result is that a correctly named file in an unexpected folder still wins, and a plausible-looking file with the wrong contents loses.