TikTok Video Downloader

I was feeling bored, so I decided to create some Python code for downloading TikTok videos without watermarks. This code utilizes SnapTik instead of TikTok’s official API. I do have another program that relies on my own reverse-engineered TikTok API. However, I’m hesitant to share it for several reasons, including the possibility of TikTok trying to patch it. Additionally, I don’t want people claiming my code as their own. Nevertheless, I decided to reverse engineer SnapTik's weak protection and develop this code to share with you all.

GitHub Page: SnapTikReversed

Source Code (main.py):

from tls_client import Session, response
from colorama import Fore, init
from bs4 import BeautifulSoup
from random import randint
import subprocess
import requests
import os
import re

init(autoreset=True)

class SnapTikReversed:
    def __init__(self, userAgent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36'):
        self.userAgent = userAgent
        self.client = Session(client_identifier='chrome_109')
        self.token = self.get_token()
        self.base = []
        self.url = ""

    def get_token(self) -> response:
        try:
            response = self.client.get("https://snaptik.app")
            soup = BeautifulSoup(response.text, "lxml")
            for _input in soup.find_all("input"):
                if _input.get("name") == "token":
                    self.token = _input.get("value")
            return self.token
        except requests.exceptions.RequestException as e:
            print(f"Request error: {e}")
            return None

    def send_request(self, video: str) -> response:
        try:
            headers = {
                'authority': 'snaptik.app',
                'accept': '*/*',
                'accept-language': 'it-IT,it;q=0.9,en-US;q=0.8,en;q=0.7',
                'dnt': '1',
                'origin': 'https://snaptik.app',
                'referer': 'https://snaptik.app/',
                'sec-ch-ua': '"Opera";v="99", "Chromium";v="113", "Not-A.Brand";v="24"',
                'sec-ch-ua-mobile': '?0',
                'sec-ch-ua-platform': '"Windows"',
                'sec-fetch-dest': 'empty',
                'sec-fetch-mode': 'cors',
                'sec-fetch-site': 'same-origin'
            }
            response = self.client.get('https://snaptik.app/abc2.php', headers=headers, params={
                'url': video,
                'token': self.token
            })
            _var = re.findall(r'\(\".*?,.*?,.*?,.*?,.*?.*?\)', response.text)
            self.base = []
            for e in (_var[0].split(",")):
                self.base.append(str(e).replace("(", "").replace(")", "").replace('"', ""))
            return self.base
        except requests.exceptions.RequestException as e:
            print(f"Request error: {e}")
            return None

    def decode(self, variable: list):
        try:
            output = subprocess.check_output([
                'node', 'decode.js',
                str(variable[0]), str(variable[1]), str(variable[2]), str(variable[3]), str(variable[4]), str(variable[5])
            ])
            result = (output).decode("utf-8")
            return result
        except Exception as e:
            print(f"Decode error: {e}")
            return None

    def get_video(self, video: str, _path: str=None) -> response:
        try:
            _page = self.send_request(video)
            _page = self.decode(_page)
            soup = BeautifulSoup(_page, "lxml")
        
            for a in soup.find_all("a"):
                url = a.get("href")
                url = str(url).replace('\\', "").replace('"', "")

                if "snaptik" in url:
                    self.url = url
        
            response = requests.get(self.url)
            id = f"{randint(1000000, 9999999)}.mp4"

            if _path:
                file_path = os.path.join(_path, id)
            else:
                file_path = id

            with open(file_path, "wb") as file:
                file.write(response.content)

            return f">> [{Fore.GREEN}{video}{Fore.RESET}] success | {file_path}"
        except requests.exceptions.RequestException as e:
            print(f"Request error: {e}")
            return None

Source Code (decode.js):

// I just wanted to say, Snaptik.app, if you see this, please enhance your security measures. It was surprisingly easy to reverse engineer the rather ineffective "protection" you're currently employing.
// Author: cxstles on github
// Date: Sep 29th, 2023.

// Initialize variables
let h, u, n, t, e, r;

// Get values from command line arguments
process.argv.forEach(function (val, index) {
    switch (index) {
        case 2:
            h = val;
            break;
        case 3:
            u = parseInt(val);
            break;
        case 4:
            n = val;
            break;
        case 5:
            t = parseInt(val);
            break;
        case 6:
            e = parseInt(val);
            break;
        case 7:
            r = parseInt(val);
            break;
    }
});

// Decode function
function decodeString(d, e, f) {
    const baseChars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+/";
    const charArray = baseChars.split('').slice(0, e);
    const outputChars = baseChars.split('').slice(0, f);

    let j = d.split("").reverse().reduce(function (a, b, c) {
        if (charArray.indexOf(b) !== -1) {
            return a + charArray.indexOf(b) * Math.pow(e, c);
        }
        return a;
    }, 0);

    let k = "";
    while (j > 0) {
        k = outputChars[j % f] + k;
        j = Math.floor(j / f);
    }

    return k || "0";
}

function evalFunction(h, u, n, t, e, r) {
    r = "";

    for (let i = 0, len = h.length; i < len; i++) {
        let s = "";
        while (h[i] !== n[e]) {
            s += h[i];
            i++;
        }
        for (let j = 0; j < n.length; j++) {
            s = s.replace(new RegExp(n[j], "g"), j);
        }
        r += String.fromCharCode(parseInt(decodeString(s, e, 10)) - t);
    }
    return decodeURIComponent(escape(r));
}

console.log(evalFunction(h, u, n, t, e, r));
5 Likes

wonderful job mate, am I allowed to use this and include your username?

2 Likes

Thanks for publishing this. I’ve been using the snaptik website but this seems like a better solution. At least this way there’s no annoying ads to worry about.

2 Likes

Yeah, of course you’re allowed to use this :).

Nice. I also made something similar, a minimal YouTube watcher/downloader: replit.com/@boston2029/loader

1 Like