4.5B Posts Scraped from TikTok A developer scraped 4.5 billion TikTok videos and uploaded the dataset to Hugging Face, collected via TikTok's private mobile API over three weeks. The system gathered 3.23 billion creator profiles, 5.94 billion videos, and 2.8 billion comments, with the dataset including captions, view counts, like counts, comment counts, save counts, sound, country, and posting time. The developer documented the technical process, including device registration, request signing, regional hosts, and TLS fingerprinting, and made 24 API endpoints available. Scraping TikTok's Mobile API TikTok's Android app talks to a private HTTP+JSON API that is faster than the web endpoints and returns considerably more. This is a technical guide to reaching it: how devices are registered, how requests are signed, how the regional hosts are partitioned, and how the TLS handshake is fingerprinted. A system built on it collected 3.23 billion creator profiles, 5.94 billion videos and 2.8 billion comments in three weeks. Free dataset. I uploaded 4.5 billion of those videos to Hugging Face: captions, view, like, comment and save counts, the sound, the country and the posting time. huggingface.co/datasets/kuben-developer/tiktok-videos-4b https://huggingface.co/datasets/kuben-developer/tiktok-videos-4b What you can pull. Creator profiles, every video a creator has posted, followers and following lists, and TikTok's own similar-creator graph. Full video detail with the complete statistics block. Comments and comment replies, each with the commenter's account. Sounds, the videos using them, and the trending sounds chart. Hashtags and their videos, newest or most popular. Keyword search across videos, creators and sounds. Trending shelves and camera effects. 24 endpoints in all api , each with a measured success rate. What this is Almost every TikTok scraper you will find drives a headless browser or hits the public web endpoints. Both are the wrong layer: slow, fragile, and missing most of the interesting fields. The Android app does not use either. It talks to a private HTTP+JSON API, the same one com.zhiliaoapp.musically hits when you scroll, and that API is fast, stable, and returns far more. Getting into it is the hard part, and it is hard in a specific way. Four completely unrelated things have to be right at once: a device credential TikTok issued, a valid request signature, the correct regional host, and a TLS handshake that looks like a phone. Get any one of them wrong and you receive the identical response: a clean HTTP 200 with an empty body . No error message. No status code. Your HTTP client reports success, your logs stay green, and your database fills with nothing. There is no signal telling you which of the four you are standing at. This article walks through all four, then documents the 24 endpoints that come out the other side. It names the primitives, shows the real pipeline and gives measured numbers rather than claims. None of the four has a feedback loop. A wrong rotation constant, a wrong byte order, a wrong host and a wrong cipher suite in the handshake all produce the same well-formed request and the same empty response, so there is no error to bisect on and no partial credit. Everything below is anonymous device traffic. There is no login anywhere in this system, no account, no session cookie. That also means anything genuinely account-gated your own DMs, private videos, who liked what is out of reach and stays out of reach. No amount of tuning gets you there. Anatomy of a request Before anything else, here is what one of these requests actually looks like. This is a real call, with the identifying values shortened: Three things to notice, because each one bites later: - Two thirds of the URL is device identity. Thirty-eight common parameters describe the handset, the carrier, the region and the app build. They are not decoration. The signature covers them. - , not chosen by you. device id and iid are issued by TikTok cdid and openudid you generate and submit at registration. Getting the distinction wrong is the first wall. - Parameter order is fixed. The signature hashes the query string as a literal, so url.Values.Encode , which sorts keys alphabetically, silently produces an invalid signature. In Go you have to build the query by hand. The vocabulary, since it recurs throughout: | Field | What it is | Origin | |---|---|---| | aid | Application id. 1233 is the main app musically , 473824 is Lite, 1340 is musically go. Different aid means a different signing key and a different endpoint set. | Constant | | device id | The durable device identity. 19 digits. | TikTok, at register | | iid | Install id. Pairs with device id . | TikTok, at register | | cdid | Client device id. A UUID you generate. | You | | openudid | 16 hex characters you generate. | You | | license id | Feeds the X-Ladon key schedule. | Constant per app | | version code | App build. Gates which endpoints answer at all. | You choose | The first empty 200 A correctly implemented signer produces output that verifies against captured traffic, with parameters matching byte for byte. The response is still this: This is TikTok's soft block, and it is the single most important thing to understand about this API. It is not a 403. It is not a 429. It is not a challenge page. It is a successful HTTP response containing nothing. Which means this code, which is what everyone writes first, is silently broken: res = requests.get url, headers=signed if res.ok: True. Always true. store res.json {} stored, no exception six hours later: 400,000 rows in the database, all empty, nothing in the error log, dashboard green It is expensive to debug because four unrelated failures produce it : - Your device was never activated § activation activate - Your signature is wrong § X-Argus argus - You are talking to the wrong regional host § regions regions - Your TLS handshake looks like a server, not a phone § JA3 ja3 There is nothing in the response to tell you which. You cannot bisect it by reading errors, because there are none. The only way through is to fix all four and measure each one in isolation. Where device IDs come from You cannot invent a device id . TikTok issues it, from /service/2/device register/ on its logging host, in exchange for a plausible handset. The request body is a JSON document app header, device header, custom block encrypted with TTEncrypt TikTok's own body cipher, a simple byte-level transform with a fixed key schedule and posted as application/octet-stream;tt-data=a . It goes out with the full signature set, so you need working signing before you can get a device, and the signing needs a device . You bootstrap with the client-generated fields and zeros where the issued ones go. The body's shape, with the parts that matter: { "magic tag": "ss app log", "header": { // app identity: must agree with the aid in the query string "aid": 473824, "package": "com.ss.android.ugc.tiktok.lite", "app version": "32.8.2", "version code": 320820, "sdk version": "...", "git hash": "...", "sig hash": "...", // hardware: every field here has to be internally consistent "device model": "SM-A136U", "device brand": "Samsung", "device manufacturer": "samsung", "cpu abi": "arm64-v8a", "os version": "12", "os api": 30, "resolution": "2280 1080", "density dpi": 440, "rom": "...", "rom version": "...", // identity you generate and are about to trade in "cdid": "