TikTok-Api
TikTok-Api copied to clipboard
[BUG] - how to generate x-tt-params?
the api changed where now instead of sending the old params directly you have to encrypt them and send them encrypted as an x-tt-params header with sending a param with mstoken, xbogus, and the signature
https://github.com/davidteather/TikTok-Api/issues/695
import requests
headers = {
'Host': 'm.tiktok.com',
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:98.0) Gecko/20100101 Firefox/98.0',
'Accept': '*/*',
'Accept-Language': 'n-US,en;q=0.5',
'Accept-Encoding': 'gzip, deflate, br',
'Referer': 'https://www.tiktok.com/',
'x-tt-params': '4mOJhGnMOdadxrLEy2bkmGSR2R38w8nZC8MQKREioTAU76aXIbW+KkRzj5O7qqbOI65rqSqkFAXNltiJ1p2YyvalYQ0VbxXkcXRyJfQSSRReg2K0v9Pg8C3JQ2XpgNJeK9TBQlzIhq658TurxN5EEGAUTrTmN1XStQ7Wb+vv8Rxg9TJYgVpSiPx6zpldv/vRCw8Z9HJzRGDHCnSz0A+qwk0sgzpoeEd8C1RAml95U1hXfWNKqTyrk6cvq6qPLZfK2ny3lb4XkHhFDEM7lrUIot9+cPFYsbeiECuPNWN8rcuarwOhB5yNv+uwAQiKKtvW1JtC0EbNLafHMsM0X2xEhkuFtCgo8BSAEI7HfRUY9nr/D8jhFGs/LFw5KIIJuQV5fkhAIF6BtqSe6P+6bSXDqfGaiSH87mE9CbnbnRtb6zfLPTSDu4X0SHPV1u9pPLCs0J5oB+hhY6QKl5Bh5vv9V3sOrcfLoPLUIguHDfDVrp9zXujFYlmyK5ALnr9XDf96n3wi/wV+z9hybUnWXkjXWOxcL/XDHaKHeTUFH6NGVeZnY7AdXCO9+q/R0IEdKIigw2/dKnE4fH77Afb8SxCD7OQRWGGJVLY+zQpSYbonxl8SsVjplpFuC7shMEbM1VJ6o9ppsYLMNGBS1as91aoRBSMLWsb/8G062SHW/boDzw5f4pbXANKb0Us7KAGH9v/eh+2vJhakpxW1c3kZkSKz4BgJm6q4Sse6u0ffSV/VFiIlo48GaFMVWeQgNNWcatnmORr25SfxqOl6A4Fx13NDb7uBE50EVvSh5AvZHV4D5zNtQ2HGSqYOOoH24e9f4I/IrwjxXeZpqVu1uJNK94fUCfUz7PajwiZmCwE8uGXGcTroO9S6JEZADRuz7N+0znGdzMfEmgF0MtCRLTY58IPmjuPwMkcEATrbNcx0IqaIZZHRkv6QI1hWE7StuWjgjBJiql1/qSAwcM7QJV1ZCY/vPcJ/6Wouhvi2Y68J5gKex2Feuwk6EDhJBxsSAz2x2XSh',
'Origin': 'https://www.tiktok.com',
'DNT': '1',
'Connection': 'keep-alive',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'same-site',
}
u="https://m.tiktok.com/api/post/item_list/?aid=1988&app_language=en&app_name=tiktok_web&browser_language=en-US&browser_name=Mozilla&browser_online=true&browser_platform=Win32&browser_version=5.0%20%28Windows%29&channel=tiktok_web&cookie_enabled=true&device_id=&device_platform=web_pc&focus_state=true&from_page=user&history_len=2&is_fullscreen=false&is_page_visible=true&os=windows&priority_region=&referer=®ion=EG&screen_height=528&screen_width=939&tz_name=Etc%2FGMT-2&webcast_language=en&msToken=&X-Bogus=&_signature="
r1 = requests.get(u, headers=headers)
print(r1.text)
note that i removed device id and ms-token and X-Bogus and signature the api url is the same but changing x-tt-params will change the user id or the cursor! of the response data...
the big question is how to generate x-tt-params???
I'm having the same question. Please if anyone knows how to solve this.
I was able to reproduce the encrypted string using the pycryptodom library
from base64 import b64decode, b64encode
from urllib.parse import parse_qsl, urlencode
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
def encrypt(r):
s = urlencode(r, doseq=True, quote_via=lambda s, *_: s)
key = "webapp1.0+202106".encode("utf-8")
cipher = AES.new(key, AES.MODE_CBC, key)
ct_bytes = cipher.encrypt(pad(s.encode("utf-8"), AES.block_size))
return b64encode(ct_bytes).decode("utf-8")
def decrypt(s):
key = "webapp1.0+202106".encode("utf-8")
cipher = AES.new(key, AES.MODE_CBC, key)
ct = b64decode(s)
s = unpad(cipher.decrypt(ct), AES.block_size)
return dict(parse_qsl(s.decode("utf-8"), keep_blank_values=True))
You can test it by pulling the x-tt-param
value from the request and running it through the decrypt to see the payload being sent.
Test:
from pprint import pprint
xttparams = "..." # value from request header
pprint(decrypt(xttparams)) # see payload as python dict
xttparams == encrypt(decrypt(xttparams)) # verify
Usage:
payload = {
'aid': '1988',
'app_language': 'en',
'app_name': 'tiktok_web',
'battery_info': '1',
'browser_language': 'en-US',
'browser_name': 'Mozilla',
...
}
xttparams = encrypt(payload)
@scotthaleen Thanks! It is working great
@scotthaleen after i decrypt xttparams , i have a param which is 'secUid': 'MS4wLjABAAAAcgUJiFIjRKsrjCW9DZEZrrG5Ord-p4jEX_YGCAXdWDAawwrZ0laVr2Blq4oZLEQR'. I think it is encrypted. Do you have solution for decrypting it ??
Thanks to @scotthaleen ,it's working perfect now we can generate x-tt-params using @scotthaleen code without problem You are the man
secUid
It's a secondary tiktok userID.
Hey, @scotthaleen , where did the string / key "webapp1.0+202106" used to encrypt / decrypt come from?
I know it's in the webpage JS code but... how did you find it and / or know it was used for this?
(I need to know mostly to find it again whenever they decide to change it...)
Thanks!!!
@luispablo it is hardcoded in the js for their encryption call. It is in the webapp-desktop.*.js
Thanks to @scotthaleen ,it's working perfect now we can generate x-tt-params using @scotthaleen code without problem You are the man
hello,i use the code,but i failed,can u give me a example code?my email is [email protected]
I was able to reproduce the encrypted string using the pycryptodom library
from base64 import b64decode, b64encode from urllib.parse import parse_qsl, urlencode from Crypto.Cipher import AES from Crypto.Util.Padding import pad, unpad def encrypt(r): s = urlencode(r, doseq=True, quote_via=lambda s, *_: s) key = "webapp1.0+202106".encode("utf-8") cipher = AES.new(key, AES.MODE_CBC, key) ct_bytes = cipher.encrypt(pad(s.encode("utf-8"), AES.block_size)) return b64encode(ct_bytes).decode("utf-8") def decrypt(s): key = "webapp1.0+202106".encode("utf-8") cipher = AES.new(key, AES.MODE_CBC, key) ct = b64decode(s) s = unpad(cipher.decrypt(ct), AES.block_size) return dict(parse_qsl(s.decode("utf-8"), keep_blank_values=True))
You can test it by pulling the
x-tt-param
value from the request and running it through the decrypt to see the payload being sent.Test:
from pprint import pprint xttparams = "..." # value from request header pprint(decrypt(xttparams)) # see payload as python dict xttparams == encrypt(decrypt(xttparams)) # verify
Usage:
payload = { 'aid': '1988', 'app_language': 'en', 'app_name': 'tiktok_web', 'battery_info': '1', 'browser_language': 'en-US', 'browser_name': 'Mozilla', ... } xttparams = encrypt(payload)
hello
i use x-tt-params as a params then use decrypt() ,then i use the result as a params but the result of encrypt is different from x-tt-params,why?
@scotthaleen have you implemented this with TikTokAPI? Maybe you'd be willing to share your branch? 😀
Hi all, thanks for your help, based on your comments I worked on the implementation in R:
encode
decrypted_payload = "aid=1988&app_name=tiktok_web&channel=tiktok_web..."
passphrase <- charToRaw("webapp1.0+202106")
key <- as.raw(passphrase)
x <- charToRaw(decrypted_payload)
y = openssl::aes_cbc_encrypt(x, key = key, iv = key)
encrypted_payload = openssl::base64_encode(y)
encrypted_payload
decode
encrypted_payload_tk = "4mOJhGnMOdadxrLEy2bkmGSR2R38w8...."
b64_decode = openssl::base64_decode(encrypted_payload_tk)
y_decode = openssl::aes_cbc_decrypt(b64_decode, key = key, iv = key)
x_decode = rawToChar(y_decode)
x_decode
Thanks
did someone find secret key "webapp1.0+202106"
analog for Android app?
in Android API there is x-tt-token
param. It looks the same format, but I believe it has a different secret key.