Understanding YouTube TV's Channel Lineup
YouTube TV lists its channel packages through a few different methods depending on what you're trying to do. The official approach is pulling from Google's own channel map API or scraping the YouTube TV help pages directly. Most people building channel lists either work with the published channel list JSON files that streamers occasionally share, or they query the YouTube Data API v3 using channel IDs mapped to a master list. Here's the practical path. YouTube TV doesn't offer an official bulk export of their channel lineup, which is annoying if you need it programmatically. What most people end up doing is using the web player's internal API calls. You can hit https://www.youtube.com/tv#/guide and inspect the network tab while browsing channels. The request to youtubei.googleapis.com/youtubei/v1/guide returns a JSON blob containing channel metadata including names, logos, and category groupings. I spent about three weeks reverse-engineering this a while back when I needed to build a custom EPG for a friend's apartment complex that wanted a cleaner interface than YouTube TV's native guide. The API response includes the full channel lineup for the current DMA, but the catch is it's location-dependent. A household in Chicago sees a completely different channel set than one in Miami because of local network affiliations and regional sports networks.
Technical Approach and Pitfalls
The core script is straightforward. You send a POST request to the YouTube InnerTube API with a client context, parse the guide section, extract channel objects, and output them as JSON or CSV. The tricky part is the client context. YouTube rotates their client configurations between web, Android TV, and iPhone clients. If your script works one day and breaks the next, this is usually why. I ended up hardcoding a few client contexts from the Android TV app since those are more stable over time. Another issue nobody talks about: YouTube TV periodically removes and adds channels without updating any public documentation. The local Bally's Sports affiliates have been a moving target for years, and ESPN+ content gets shuffled around during contract disputes. If you're maintaining a channel list, budget at least a few hours per quarter just for verification passes. There's also the M3U route. Some people prefer converting the channel data into M3U playlists for use with IPTV players and Kodi setups. You can combine the JSON extraction with a simple conversion script that maps channel IDs to streamable URLs or uses the YouTube TV URL structure. The quality of M3U files depends entirely on how fresh your source data is. Stale lists will have dead links for channels that were dropped in the last year.
Where This Method Falls Apart
Let me be direct about the limitations. The InnerTube API approach requires you to stay under YouTube's request limits, or your IP gets throttled. Running this as a one-time dump is fine. Running it on a schedule without proper rate limiting will get you blocked. I've seen people try to poll this every hour and end up with captcha challenges within a day. The channel mapping is also incomplete for certain data points. The guide API returns channel names and logos, but it does not provide channel numbers as they appear in the YouTube TV interface. Those are dynamically generated based on your location and subscription tier. If you need accurate channel numbers for a remote control setup or a custom guide interface, you'll need to layer in additional data from community-maintained sources or scrape the guide page itself. For most users, the simplest solution is probably visiting the official YouTube TV channel lookup page at youtube.com/tv/channel_lookup, entering your address, and exporting what you can manually. It's not automated but it's reliable. If automation is what you need, the InnerTube method described above will get you there, just expect to maintain it over time.
Get the Full Details

What I'd Do Differently Now
Looking back, I wish I had just maintained a local database with timestamps on each channel entry instead of trying to refresh the full list every time. Querying the API once per month, comparing against the previous snapshot, and only updating changed entries cut my maintenance time down significantly. The channel list doesn't change daily. Most of the churn is concentrated around sports rights deals and regional network reorganizations, which happen on quarterly cycles at most. If you're starting from scratch, I'd recommend writing a script that saves the raw JSON response alongside your parsed output. That way if the API structure changes and your parser breaks, you still have the original data to work with rather than trying to re-scrape and hoping nothing has shifted.