Introduction
I’ll be honest with you:
I didn’t wake up one morning thinking “Let me reverse-engineer TikTok today.”
It started with something much simpler:
“I just want to upload videos to TikTok programmatically…
why is this so damn hard?”
No matter what I tried — simple requests, faked headers, even stolen cookies — TikTok kept slamming the door in my face.
But every failure taught me something.
Every blocked request revealed the next security layer.
So I dug in.
I became the “hacker” TikTok didn’t want.
And in this post, I’ll take you through the exact journey — from the most naive HTTP request… all the way to running TikTok’s own obfuscated JavaScript in a Node VM to generate browser signatures.
All code here comes from my real TikTok automation stack (based on my repo:
github.com/mrzaizai2k/auto_tiktok).
Table of Contents
- Raw Request — My First Dumb Attempt
- User-Agent — “Fine, I’ll Pretend to Be Chrome”
- Cookies — The Real Passport
- Browser Signatures — When TikTok Got Serious
- Summary
- Final Thoughts
- Resources
Raw Request
đź§ What I Tried
The first time I tried calling TikTok’s API, I thought it would be as easy as:
import requests
print(requests.get("https://www.tiktok.com/api/whatever").text)
TikTok looked at me like:
“Bro, who even are you?”
No headers.
No cookies.
No browser identity.
Instant block.
To understand why, I built a minimal FastAPI to simulate what TikTok sees when a bot sends a naked request:
from fastapi import FastAPI, Request, HTTPException
app = FastAPI()
@app.get("/api/data")
def get_data(request: Request):
# no checks, no identity
return {"data": "public info"}
This is how the early internet worked.
And this is why it died.
User-Agent
“I’ll wear Chrome’s clothes… surely that will work.”
I added:
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
My FastAPI simulation:
@app.get("/api/data")
def get_data(request: Request):
ua = request.headers.get("User-Agent")
if not ua:
raise HTTPException(403, "Missing UA")
return {"data": "public info"}
And my crawler:
import requests
requests.get(url, headers={"User-Agent": "Mozilla/5.0"})
This worked…
…for exactly 5 minutes.
Because any idiot can fake a UA.
Including me.
So TikTok uses the next level.
Cookies
“Fine, TikTok, you want identity? Here’s my passport.”
Cookies are small pieces of data the server sets in your browser.
When I login to TikTok on Chrome, the browser stores cookies like:
sessionidmsTokentt-target-idccsrf_session_id
These aren’t random strings — they’re TikTok’s way of saying:
“This browser is logged in. We know this guy.”
To get these cookies, I use this extension (the best one I’ve found):
👉 J2Team Cookies (Chrome)
It exports cookies into a neat JSON file — perfect for automation.
Then in Python:
cookies = load_cookies_from_file("cookies/tiktok.json")
session = requests.Session()
session.cookies.set("sessionid", session_id, domain=".tiktok.com")
session.cookies.set("tt-target-idc", dc_id, domain=".tiktok.com")
Now TikTok was finally willing to talk to me.
For a while.
Because cookies can still be:
- stolen
- copied
- reused
- shared
TikTok needed something harder.
Browser Signatures
“Prove you’re a real browser or get lost.”
This is where TikTok gets nasty.
Even with:
- Valid cookies
- Valid User-Agent
TikTok still blocks you unless you generate:
X-Bogus_signature-
msTokenvalidation - device/environment fingerprints
- obfuscated JS crypto outputs
TikTok literally sends JavaScript that only a real browser can execute.
So to bypass it…
I used their own JavaScript.
👉 Running TikTok’s JS in a Node VM
This is my real browser.js (the one doing the magic):
// Browser.js
const Signer = require("./index");
var url = process.argv[2];
var userAgent = process.argv[3];
(async function main() {
try {
const signer = new Signer(url, userAgent);
await signer.init();
const sign = await signer.sign(url);
const navigator = await signer.navigator();
let output = JSON.stringify({
status: "ok",
data: {
...sign,
navigator: navigator,
},
});
console.log(output);
await signer.close();
} catch (err) {
console.error(err);
}
})();
And this is how my Python script calls it:
def subprocess_jsvmp(js, user_agent, url):
proc = subprocess.Popen(['node', js, url, user_agent], stdout=subprocess.PIPE)
return proc.stdout.read().decode('utf-8')
Every API request needs this signature.
Without it — TikTok spits on you.
With it — you suddenly become “a real browser.”
This is exactly how I upload videos automatically:
signatures = subprocess_jsvmp(js_path, user_agent, sig_url)
tt = json.loads(signatures)["data"]
headers = {
"User-Agent": user_agent,
"X-Bogus": tt["x-bogus"],
"_signature": tt["signature"],
}
Now TikTok believes me.
And lets me upload videos through automation.
Summary
| Layer | What I Did | Why It Failed |
|---|---|---|
| Raw request | Called API directly | “Who are you?” |
| User-Agent | Pretended to be Chrome | Too easy to fake |
| Cookies | Exported real TikTok cookies | Reusable → insecure |
| Browser Signatures | Ran TikTok’s own JS | Finally works |
Final Thoughts
There are even more authentication methods out there:
- OAuth
- JWT tokens
- PKCE
- Rotating keys
- Device-bound tokens
If you want, I can continue this series:
👉 Hit follow + drop a comment if you want the next chapter.
Resources
- My TikTok uploader code: auto_tiktok → tiktok.py
Top comments (3)
This post honestly feels like a small masterclass in modern web security. I love how you walk through the evolution rather than explaining each technique in isolation. Seeing the server code vs crawler code side-by-side makes everything click — especially how each layer becomes useless once hackers figure out a workaround.
This is an awesome Post, I wish it had more traffic as not only is it informative and provides a ton of useable information the writing style is flat out hilarious. Hopefully it gets more traction as I would love to see a next chapter :). Well Done, Fine Sir!
As a note: I especially enjoyed the narrative as I also find myself anthropomorphizing software especially when explaining concepts and functionality to those unfamiliar with coding languages. So, the "Hey, who are you pal? Buzz Off..." type inclusions had me laughing to myself...
Thank you so much for the kind words! 🙏 I really appreciate your support and I’m thrilled to hear the writing style and humor resonated with you. Knowing that fellow coders also anthropomorphize software made me laugh too