Virtual Newsletter about Software Freedom May 17, 2025 Reverse-engineering OneTV API ----------------------------- OneTV is an Android app that allows you to watch TV from Iran and other places. It is an interesting app. Most of it is built upon `geoindex.json` (https://cdnw-onetv.github.io/geoindex.json), the main JSON that stores all data. The streams format is different, but I easily converted it to M3U. Some of the streams are unusual. There are some streams that just take you to the download page. Every attribute has an ID for some reason, even the settings. The IDs for streams are not really in order. Just random. The "user channels" has URLs that are already there, just that they are un-named streams so they don't show up. Now, besides streams, there is much more to OneTV. The `metadata` section of `geoindex` has a lot of unused strings. OneTV has a special feature that doesn't exist in other players. A "Trending" tab. This is actually real, it is not just picked by the server admin. I was interested on how this trending tab works. Using information from `geoindex` it was easy to find how to get the trending streams in JSON. It was simply in attribute `stats_update_url` where I could find it. But actually influencing the trending tab? Unknown. Attribute `stats_report_url` has a link, "https://ca-ss-rt.onetvapi.xyz". If you open this link with a browser, it will reply with a test response. Nothing. But, I knew that this held something for me. So, I downloaded a `gobuster` wordlist (https://github.com/aels/subdirectories-discover). I scanned for links, looking for something that would help. What I found was my first clue. A single directory was found after the `gobuster` scan, `/docs`. This page, "https://ca-ss-rt.onetvapi.xyz/docs", is a Swagger UI for a FastAPI. It has 2 entries. "GET / (Get)" "POST / (Create item)" I noticed POST, and hoped that it was the solution. But, when I checked it, there was nothing. No parameters. That couldn't be right. So, I ran the example, and got a 500 Internal Server Error. That probably means I need parameters. I was desperate. Went to Stack Overflow and searched how to intercept connections on Android. But then, I found it. HTTP Toolkit. It's great software, and it's AGPL. I played around with HTTP Toolkit, configured it for my device, and decided to try it with OneTV. I downloaded it from Aurora Store, and I tried to run it. I was able to load into the app. But, whenever I tried to load a stream, it crashed. Luckily I have tools to capture crashes, and it reported that it crashed due to not being able to find a Play Services function. Now, my phone doesn't use Play Services, but I do have one which does. I was also able to root it, making the setup of HTTP Toolkit easier. Once I got HTTP Toolkit and OneTV set up, I loaded a stream. At first, nothing happened. But after a bit it sent a request to "https://ca-ss-rt.onetvapi.xyz". That domain, was the one that was mentioned as the trending reporter. I captured the request, and took the data. There are many variables in a request. { "Accept" (Required?; Unknown, always "*") "channel_id" (Required; Channel ID to report.) "channel_id_" (Required?; Duplicate of `channel_id`) "channel_title" (Recommended; Channel title) "channel_language" (Recommended; Language code of channel, example: fa) "channel_country" (Recommended; Country code of channel, example: IR) "country" (Recommended?; Country code of user, example: US) "language" (Recommended?; Language code of user, example: en) "user_pseudo_id" (Required?; User ID, to generate, just create a UUID4 and remove the dashes) "country_name" (Recommended?; Country name of user, example: United States) "city_name" (Recommended?; City name of user, example: Los Angeles) "region_name" (Recommended?; Region that the user is in, example: California) "isp_name" (Recommended?; ISP of user) "ip" (Required?; IP address of user) } Most of this data is gathered by a request to `http://ip-api.com/json`. Using this newfound information, I wrote an app. For an example, I found an IP range in Iran, and used it to report trending status for a channel, one IP after another. This is all actually being sent from my IP, but the JSON says otherwise. I ran the script, and in about 10 minutes, the channel I selected went to 2nd place. I will release the source code for both the OneTV-to-M3U and the Trending-API tool on Codeberg. - NexusSfan --- JSON Request: https://mrchicken.nsf-home.ip-dynamic.org/cdn/onetv-trending-request.json --- --- Copyright (c) 2025 NexusSfan Except where otherwise noted, this work is licensed under the Creative Commons Attribution-NoDerivatives 4.0 International License A copy of the license is included at https://creativecommons.org/licenses/by-nd/4.0 ---