com.github.stormbit.tiktokapi.TikTokApi.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of tiktok-api Show documentation
Show all versions of tiktok-api Show documentation
Kotlin version of the python TikTokApi library
package com.github.stormbit.tiktokapi
import com.google.gson.Gson
import com.google.gson.JsonObject
import net.dongliu.requests.Requests
import org.apache.http.NameValuePair
import org.apache.http.client.utils.URLEncodedUtils
import org.apache.http.message.BasicNameValuePair
import java.lang.Thread.sleep
import kotlin.random.Random
private const val BASE_URL = "https://m.tiktok.com/"
@Suppress("unused", "unused_variable", "MemberVisibilityCanBePrivate")
class TikTokApi(private val request_delay: Int = 0, executablePath: String, external_signer: String? = null) {
private var signerUrl: String? = null
private var userAgent: String = ""
private var referrer: String? = null
private var width = "1920"
private var height = "1080"
private val browserLanguage = ""
private val browserPlatform = ""
private val browserName = ""
private val browserVersion = ""
private val timezoneName = ""
private lateinit var browser: Browser
init {
if (external_signer == null) {
this.browser = Browser(executablePath = executablePath)
this.userAgent = browser.userAgent
this.referrer = browser.referrer
this.width = browser.width
this.height = browser.height
}
}
fun close() {
browser.close()
}
fun getTiktokById(id: String, params: HashMap): JsonObject {
val (region, language, proxy, maxCount, did) = processParams(params)
val query = listOf(
BasicNameValuePair("itemId", id),
BasicNameValuePair("language", language)
)
val apiUrl = "%sapi/item/detail/?%s&%s".format(BASE_URL, addNewParams(), URLEncodedUtils.format(query, "utf-8"))
val prms = hashMapOf("url" to apiUrl)
prms.putAll(params)
return getData(prms)
}
fun getTikTokByUrl(url: String, params: HashMap): JsonObject {
var postId = ""
if (url.contains("@") && url.contains("/video/")) {
postId = url.split("/video/")[1].split("?")[0]
}
return getTiktokById(postId, params)
}
fun getVideoURL(url: String, params: HashMap): String {
val tiktokSchema = getTikTokByUrl(url, params)
val download_url = tiktokSchema.get("itemInfo").asJsonObject.get("itemStruct").asJsonObject.get("video").asJsonObject.get("downloadAddr").asString
return download_url
}
fun getBytes(params: HashMap): ByteArray {
val (region, language, proxy, maxCount, did) = processParams(params)
params["custom_did"] = did
if (request_delay != 0) {
sleep(request_delay.toLong())
}
val verifyFp: String
val didd: String
val signature: String
val userAgent: String
val referrer: String
if (this.signerUrl == null) {
val args = this.browser.signUrl(params)
verifyFp = args[0]
didd = args[1]
signature = args[2]
userAgent = this.browser.userAgent
referrer = this.browser.referrer
} else {
val resp = externalSigner(params["url"].toString(), params.getOrDefault("custom_did", null).toString())
verifyFp = resp[0]
didd = resp[1]
signature = resp[2]
userAgent = resp[3]
referrer = resp[4]
}
val query = listOf(
BasicNameValuePair("verifyFp", verifyFp),
BasicNameValuePair("_signature", signature)
)
val url = "%s&%s".format(params["url"], URLEncodedUtils.format(query, "utf-8"))
val url2 = "https://v16-web.tiktok.com/video/tos/alisg/tos-alisg-pve-0037c001/d40364f8143c495fbb718a3dbf2641f4/?a=1988&br=924&bt=462&cr=0&cs=0&dr=0&ds=2&er=&expire=1605476212&l=2020111515363101018907414801124BE0&lr=tiktok_m&mime_type=video_mp4&policy=2&qs=0&rc=andndHJ2eGdoeDMzNjczM0ApOWQ6ODQ8OTtmNzRmOjMzZWdvbHFyXjIwY2tfLS0tMTRzcy42Yi9eNTVgYDQtNTU2MTU6Yw%3D%3D&signature=9a38cc496936df261c22db24447352d6&tk=tt_webid_v2&vl=&vr=&verifyFp=verify_khgp4f49_V12d4mRX_MdCO_4Wzt_Ar0k_z4RCQC9pUDpX&_signature=_02B4Z6wo00f01cUV0hgAAIBBz-Rqd-BUVYHFBNaAAC7357"
val headers = mapOf(
"Accept" to "*/*",
"Accept-Encoding" to "identity;q=1, *;q=0",
"Accept-Language" to "en-US;en;q=0.9",
"Cache-Control" to "no-cache",
"Connection" to "keep-alive",
"cookie" to "tt_webid_v2=$didd",
"Host" to url.split("/")[2],
"Pragma" to "no-cache",
"Range" to "bytes=0-",
"Referer" to referrer,
"User-Agent" to userAgent,
)
val bytes = Requests.get(url)
.headers(headers).send().readToBytes()
return bytes
}
fun getVideoBytesByURL(url: String, params: HashMap = HashMap()): ByteArray {
val (region, language, proxy, maxCount, did) = processParams(params)
params["custom_did"] = did
val downloadUrl = getVideoURL(url, params)
val prms = hashMapOf(
"url" to downloadUrl
)
prms.putAll(params)
return getBytes(prms)
}
private fun getData(params: HashMap = HashMap()): JsonObject {
val (region, language, proxy, maxCount, did) = processParams(params)
params["custom_did"] = did
if (request_delay != 0) {
sleep(request_delay.toLong())
}
val verifyFp: String
val didd: String
val signature: String
val userAgent: String
val referrer: String
if (this.signerUrl == null) {
val args = this.browser.signUrl(params)
verifyFp = args[0]
didd = args[1]
signature = args[2]
userAgent = this.browser.userAgent
referrer = this.browser.referrer
} else {
val resp = externalSigner(params["url"].toString(), params.getOrDefault("custom_did", null).toString())
verifyFp = resp[0]
didd = resp[1]
signature = resp[2]
userAgent = resp[3]
referrer = resp[4]
}
val query = listOf(
BasicNameValuePair("verifyFp", verifyFp),
BasicNameValuePair("did", didd),
BasicNameValuePair("_signature", signature)
)
val url = "%s&%s".format(params["url"], URLEncodedUtils.format(query, "utf-8"))
val headers = mapOf(
"authority" to "m.tiktok.com",
"method" to "GET",
"path" to url.split("tiktok.com")[1],
"scheme" to "https",
"accept" to "application/json, text/plain, */*",
"accept-encoding" to "gzip, deflate, br",
"accept-language" to "en-US,en;q=0.9",
"referer" to referrer,
"sec-fetch-dest" to "empty",
"sec-fetch-mode" to "cors",
"sec-fetch-site" to "same-site",
"user-agent" to userAgent,
"cookie" to "tt_webid_v2=$did"
)
val r = Requests.get(url)
.headers(headers).send().readToText()
return Gson().fromJson(r, JsonObject::class.java)
}
private fun externalSigner(url: String, custom_did: String? = null): List {
val query: List = if (custom_did != null) {
listOf(
BasicNameValuePair("url", url),
BasicNameValuePair("custom_did", custom_did)
)
} else {
listOf(
BasicNameValuePair("url", url)
)
}
val data = Requests.get("" + "?%s".format(URLEncodedUtils.format(query, "utf-8"))).send().readToText()
val parsedData = Gson().fromJson(data, JsonObject::class.java)
return listOf(parsedData["verifyFp"].asString, parsedData["did"].asString, parsedData["_signature"].asString, parsedData["userAgent"].asString, parsedData["referrer"].asString)
}
private fun processParams(params: HashMap): List {
val region = params.getOrDefault("region", "US").toString()
val language = params.getOrDefault("language", "en").toString()
val proxy = params.getOrDefault("proxy", null).toString()
val maxCount = params.getOrDefault("maxCount", "35").toString()
val did = params.getOrDefault("did", Random.nextInt(10000, 999999999).toString()).toString()
params["did"] = did
return listOf(region, language, proxy, maxCount, did)
}
private fun addNewParams(): String {
val query = listOf(
BasicNameValuePair("aid", "1988"),
BasicNameValuePair("app_name", "tiktok_web"),
BasicNameValuePair("device_platform", "web"),
BasicNameValuePair("referer", "https://www.tiktok.com/"),
BasicNameValuePair("user_agent", formatNewParams(this.userAgent)),
BasicNameValuePair("cookie_enabled", "true"),
BasicNameValuePair("screen_width", this.width),
BasicNameValuePair("screen_height", this.height),
BasicNameValuePair("browser_language", this.browserLanguage),
BasicNameValuePair("browser_platform", this.browserPlatform),
BasicNameValuePair("browser_name", this.browserName),
BasicNameValuePair("browser_version", this.browserVersion),
BasicNameValuePair("browser_online", "true"),
BasicNameValuePair("ac", "4g"),
BasicNameValuePair("timezone_name", this.timezoneName),
BasicNameValuePair("appId", "1233"),
BasicNameValuePair("appType", "m"),
BasicNameValuePair("isAndroid", "false"),
BasicNameValuePair("isMobile", "false"),
BasicNameValuePair("isIOS", "false"),
BasicNameValuePair("OS", "windows"),
BasicNameValuePair("page_referer", "https://www.tiktok.com/")
)
return URLEncodedUtils.format(query, "utf-8")
}
private fun formatNewParams(parm: String): String {
return parm.replace("/", "%2F").replace(" ", "+").replace(";", "%3B")
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy