Welcome to TikAPIs.com
Offering API services for Android, iOS, and Web platforms. Engage in coding, designing, or even coffee brewing with our diverse APIs.
Need an API key? Grab it here and kickstart your project!
Support us with a donation to keep the APIs running. Every contribution matters. Donate Now!
Contact Us
Email: [email protected]
Telegram Group: Join our Telegram group
Discord Server: Join our Discord server
Request Header:
{'Content-Type': 'application/json', 'api-key': 'YOUR_API_KEY'}
Include the following data when sending a request:
{ "aid": 1233, // A unique identifier for the API request. "lc_x": "138417152", // Argus data in protobuf, obtain via argus_decode. "app_version": "33.0.0", // Application version. "version_code": "330028", // Version code of the app. "manifest_version_code": "330028", // Version code in AndroidManifest. "update_version_code": "330028", // Update version code of the app. "tz_name": "Europe/Berlin", // Time zone of the requestor. "lang_b": "DE", // Browser language of the requestor. "lang_k": "de", // Language for the API response. "sdk_ver": "v05.00.06-alpha.10-ov-android", // SDK version. "get_token": "" // Send if token is obtained, otherwise leave empty. }
Device Template
This section provides information about the device templates.
Endpoint
POST /device_template
Request Body Example
{ "aid": 1233, "app_version": "33.0.0", #You can adjust it according to the desired version. "version_code": "330028", #You can adjust it according to the desired version. "manifest_version_code": "330028", #You can adjust it according to the desired version. "update_version_code": "330028", #You can adjust it according to the desired version. "tz_name": "Europe/Berlin", #this data must be equal to your ip address. "lang_b": "DE", #this data must be equal to your ip address. "lang_k": "de" #this data must be equal to your ip address. }
Include the following parameters in your request body: Application ID (aid), timezone (tz_name), browser language (lang_b), and keyboard language (lang_k).
Response Body Example
{ "aid": "1233", "app_name": "musical_ly", "app_version": "33.0.0", ...... "os_api": 22, "os_version": "5.1", "package_name": "com.zhiliaoapp.musically", "passport_sdk_version": "19", }
Device Register
This section provides information about registering a device.
Endpoint
POST /device_register
Request Body Example
{ "aid": "1233", "app_name": "musical_ly", "app_version": "33.0.0", ...... "os_api": 22, "os_version": "5.1", "package_name": "com.zhiliaoapp.musically", "passport_sdk_version": "19", }
All data obtained from device_template is required here.
Response Body Example
{ "headers": { "X-Argus": "cjZyaYFgZb4AA8Ja8+RYteWBP4w25bIBydcv4zWWZbRyNxHQTkDiXlkxdvIOThsD4FPRBaEmYlE2VOuIDXxl+vtPU/JDQwltM6FSI1Nw13B/o7YPd5PetskkBph48UEKNoYYY6JPuH6I6BI0pV+mfC+NwwOV5kEp/ZQ9aZn5jf20+iJkSfd6QTzvuy8nZR5iG5Gl+uNs4rfJ0FS8JxmvTmcMEDZgKjpg/6GfkIw46BLdVcg6YwlrBR7pCtbeJt9Oz0QLYpAM2b2HZzEXVli20s0h", "X-Gorgon": "0404623c0000cd0346592c3537218757d8071a0327a935c5c7fc", "X-Khronos": "1709164236", "X-Ladon": "q2iHvqXWP8GjrJOyN4JYUdFY4c5ofXMOZ7biyO3UQ2JSGy/Z", "content-type": "application/octet-stream;tt-data=a", "passport-sdk-version": "19", "sdk-version": "2", "user-agent": "com.zhiliaoapp.musically/330028 (Linux; U; Android 8.0; de_DE; 8.0; SM-A750GN; Build/6E6F.701039.443)", "x-ss-dp": "1233", "x-ss-req-ticket": "1709164236557", "x-ss-stub": "5BCEBE1C43B8D9B35751197BE359C86F", "x-tt-local-region": "de", "x-tt-store-region": "de", "x-tt-store-region-src": "did", "x-tt-trace-id": "00-f2208f0d10f0c9965825939694c804d1-f2208f0d10f0c996-01" }, "method": "POST", "payload": "74630510000006ba601ee27f2582c1e7c24be1bce63c36fb9bb3ac228158b762ba8da9b85dc9455027c55b90084466550a420fc2d2088327310fe4837ca853c83b6729dd6bafd61f69377f5fbdc3f9e642e439d7f12245b8c46b8939a6ac068187b6619b344e67b88f69851dd7d29f6aa95e93846d56757ba42e1eb22e74db1652857fa6d02f7de0534e1849e154ea8eb1f8d569f11db0f33f5b5f13a8276df7125d1a1647b130152b3799f8a6feb742d86efc783226f87a6d1a59bd9920615c4af6f58a4a884218c56468ccecf312ab9fd49e2f125ed0845f79a4474073a8c1e48b01c37789b8e1c4c690c980ea8c8f8ae74e0acc8540ccc07d0b9358869a35542384339e189f296495987273d077d35873fb62e5e68606838ce591b549c0f19e5a40ecbde48c43010df398857e504a5d3a057c91bef1082d665e3bb89a277448d55e7303bf9734a258208f5ad752f47e2fd711182ec3b6c6f1a0d72ba8f6f8a0ecda6af78fdf57d35712a54bffc0c6349509b8a3bb36a145f976ef7d63271d974ee635b3234db36e1134ca8ff4679650f5fa01003fabb41d58b400fc1d3798f6c0f7d565661dacb2750c028c2bfd387695a0da449f675baec8bcb24fa28aa503bc79cd6ceeb269346089964ee2e4f76200de12eb476bec5ed6de5d6851ee1d2acc3770fafe5766b8cf9924fdf285894fa26b897b44f1e7fc44151b77a72025df5569b35cf037ff01cd3c386fae551f4b84cec003cbae34e59bcde4d20d6a12511bd3e6af041790fc4650bcf87f19d996eb4580925708429c7460eefe1c641628b0f68827ba0bf140254c8bf26c67bcbf007cf732cf5c93510538f896ad31af5dfc7ec86b0720c0ae178ea308ddb3328647ff625b56b80306001161f7fcf76f3eed30dedba71429c8d074241482ff417b54fc5a7115eadf10de951e110e14276496c726cdf2362eebebb704a9fe445e344080e817cf549c845a951ce9d1129e2c53409a7fcbce6aa71ba5712e7895711d67ba40fd5aaab049970b3ac67b412753ec18a3c9d8c63215fae9e4a87dfd5bea3367875f1bec3d07b25891e4c2f7d3952ef8a85eb912f92d2efdef681bee9c2bc8c468a87dd1feebad7ad42ed992e988877b74b9b55a323d5c279c78b4880626aa47869f16f477c06765d4418ee64017384e8f1aeb", "url": "https://log.tiktokv.com/service/2/device_register/?manifest_version_code=330028&_rticket=1709164236543¤t_region=DE&app_language=de&channel=googleplay&device_type=SM-A750GN&language=de&locale=de-DE&resolution=2094*1080&openudid=0d19c75576df71f7&update_version_code=330028&ac2=wifi5g&cdid=48a65e74-74d2-40ef-bd87-7bed680a44d5&sys_region=DE&os_api=26&timezone_name=Europe%2FBerlin&dpi=420&carrier_region=DE&ac=wifi&mcc_mnc=&os_version=8.0&timezone_offset=3600&version_code=330028&app_name=musical_ly&version_name=33.0.0&device_brand=samsung&op_region=DE&ssmix=a&device_platform=android&build_number=33.0.0®ion=DE&aid=1233&ts=1709164236&uoo=0&tt_data=a" }
report_did_iid_update
This section provides information about registering a device.
Endpoint
POST /report_did_iid_update
Request Body Example
{ "aid": "1233", "app_name": "musical_ly", "app_version": "33.0.0", "install_id": "1", "device_id": "1", "sdk_ver": "v05.00.03-alpha.10-ov-android", ...... "os_api": 22, "os_version": "5.1", "package_name": "com.zhiliaoapp.musically", "passport_sdk_version": "19", }
Response Body Example
{ "headers": { "X-Argus": "NM5/ReGOP6syTbvrt4UNlqvFuq/5koSU9EFApaA70BM0z3GIsnPrAbtvBJhlxGBwcsjK3EM6Y8UWKhpqyqMi2n6tTTHvxzRoiWF+OXGkdKVP4VqrTbKp+nFSV04c+rcfH/kPxzchyCAzHpJFzrIMOD/D4WMpR9LRu4luiUBbMWNpYTbjU3Dpy3WVfp/kw7fZB60Yprt9QiMO4/Z5hyEGSOCqAtS28Y36vxS76oCJTlnF/okBKW9i4As6zaUz2GeQZb0E3uY2rwHNgPq2PeZ/GeJZ", "X-Gorgon": "04046ded00001aa8dc25d04304a86ac9a2b123964706b365aee7", "X-Khronos": "1709164612", "X-Ladon": "PkrB7kojGgPtvAj/uZC7leeCQrGLvsB/lxkmXHZgpj/eRziM", "accept": "*/*", "content-type": "application/octet-stream", "passport-sdk-version": "19", "sdk-version": "2", "user-agent": "ByteDance-MSSDK", "x-ss-dp": "1233", "x-ss-req-ticket": "1709164612074", "x-ss-stub": "390BD6EB79767B74AD6DF6159CD63F59", "x-tt-local-region": "de", "x-tt-request-tag": "t=1;n=0", "x-tt-store-region": "de", "x-tt-store-region-src": "did", "x-tt-trace-id": "00-f22649eb1013304d1-f22649eb1013304d-01" }, "method": "POST", "payload": "08c490808204100222800895f73a70bb84dee1de41a69bb0c9df453a35cf5c27010e7623cc7358f35b112d88d27c3dd77acaf901c2c2f34126724d6bb4892ef9d763c74252935dbac343da04b5f22b63372a1b98c3a33013ca4bb7585dd86581ab44ab52fe039376600b5b5bfc30762aa922c46ab04906be1d33fd670b2d0c9717b19f734de34d5a7b18a388e45581dfa0ab2b1c291b94b9924deec349f9dc8aaef663074eef6a8145df61d5a138d2016b2a32b85bdcb1c4cd367bd15eebb871bb756b340769b4165b2ae0ff27d77fc9ad7ad767ebbfd6f77edf2de785c6670d2f00dde7684014926edba82cdc6b1be56d49b2bf01ecfb7a3ee6a7ce29cb7e6441015d525b2134ece3f55c13b1bce39e9bc2bf58ab791de1aad0f90056ac6c746f39ee9e6ffde0f0fc8d6abd70a6d8ae1129c6ff2a4d2fbeb250aade50d90c93f774d1d2295599774407b52957d5f3c9e9831f84e92e160aab0740019bae059c3dc694e123340f876a4976e409bd66ed77717d4b1b8abecefd19508c2fa8187e2842de28b42bee91fa04e625e8029eb0118bd5a72b1a3cc9b6701c0f707e03998d3d341a5dabf6badfbc9bd8406f34e0055ddd9a1eaa649b3ad5a03d344a08ece0fe1621d92ab8d774cd2ed5b44aec52e66d9ea040cd766b0489f8749b5d2ea409e0d71e85d36f114cb69d4fa607ae74990ae18987f02d736dfb94e5d2da48155d4f59fd456e4d8b26de67973f86f47d25447a566d10a1c4fa93a4fbb05a88afed7191ad1ba2cd7c6c8a87d310a5aa13ffac5f41030b59d06e9e1cf4b6a7a80b0c9d3465b15b24e3017a462276e956d176c35a3078dc5edc8ae19206719f1282fbf28a70b851e6e713ff3ecfcaf17f45756196a84211ea76970068b4ef96415533751831b3c04ae2c59ec57f6c4a33ad5c846ff3d0e4635c881aae82568282af5b15be8def698faad3dfe6d1ef273c79f48a8327f773cf89558bf5d012ea4bf660a3f7dcc109b04ebc0f8dc50e096595f63c00a9cd208658cc919f02b04be240d7b929d75fcfc814741d085466ef061177335f6de89b2331a3596dd6aedaa1de3289b6999dde80331c47b6ea660e760e9fafd72ac0aec47eafb3e90b2b692d4e6679dd67fedaf20917d481cc432d895191d40c963173c6e5f968b01a48b6afefd8e1cf05c1c3e3ddf777616ca24bfe7f58ac2950ac220690fe312dbd518b1d7163d83dc15538e2deae1212c5c3cf5e1a50e9670c7cd0c1b05571321196d90defd7e4692c57231e1a33a9b714017b176b9d672886850ba27e356e883190a02af0e485f853add660a87eeae9772a9467d383d7cf2ee48c3c4e1d9b9d8cc9445751405894b184daa3838a654a23d5dc0f2d049b30b6383d356d86a08df9a737af57b777e45663106d4f14cf41ef118f7ba1282db9e3cc8721e95888be9e9376d8851a94f2913cfe81fda5dad828c4a7b2a2be63", "url": "https://mssdk-va.tiktokv.com/ri/report?lc_id=2142840551&platform=android&device_platform=android&sdk_ver=v05.00.03-alpha.10-ov-android&sdk_ver_code=83886880&app_ver=33.0.0&version_code=330028&aid=1233&sdkid=&subaid=&iid=1&did=1&bd_did=&client_type=inhouse®ion_type=ov&mode=2&ts=1709164612&app_type=normal" }
get_sign
This section provides information about get_sign up a device.
Endpoint
POST /get_sign
If a GET operation is performed, the ["data"] field can be empty or omitted.
The ["data"] field can accept string, hex, or JSON data.
Request Body Example
{ "url": "https://api16-normal-c-useast2a.tiktokv.com/passport/email/register/v2/?manifest_version_code=2023301020&_rticket=1709095423862¤t_region=DE&app_language=de&iid=0&channel=huaweistore&device_type=JNY-LX1&language=de&locale=de-DE&resolution=2208*1080&openudid=862354e82ba89e61&update_version_code=2023301020&ac2=wifi5g&cdid=7a5108c4-1ce7-4807-a5d1-c428ed5c895d&sys_region=DE&os_api=29&timezone_name=Europe%2FBerlin&dpi=480&carrier_region=DE&ac=wifi&device_id=1&mcc_mnc=28601&os_version=10&timezone_offset=3600&version_code=330102&app_name=musical_ly&version_name=33.1.2&device_brand=huawei&op_region=DE&ssmix=a&device_platform=android&build_number=33.1.2®ion=DE&aid=1233&ts=1709095423&passport-sdk-version=19&uoo=0&cronet_version=4.2.137.43-tiktok&ttnet_version=2fdb62f9_2023-09-06&use_store_region_cookie=1", "data": "password=6f557f31704655367142406b3735&fixed_mix_mode=1&rules_version=v2&mix_mode=1&multi_login=1&email=776a7676686c69766b64776e7c75646b456d6a7168646c692b666a68&account_sdk_source=app&birthday=1974-01-16&multi_signup=0", "headers": json.dumps({ "content-type": "application/x-www-form-urlencoded; charset=UTF-8", "cookie": "passport_csrf_token=e8be4c03718f5642343426565460d00763b; passport_csrf_token_default=e8be4c03718f5642343426565460d00763b;", "passport-sdk-version": "19", "sdk-version": "2", "user-agent": "com.zhiliaoapp.musically/2023301020 (Linux; U; Android 10; de_DE; 10; JNY-LX1; Build/OPHZ.604442.570)", "x-ss-dp": "1233", "x-ss-stub": "96441805792CE6695FB4EA6F0BC52A7F", "x-tt-local-region": "de", "x-tt-store-region": "de", "x-tt-store-region-src": "did", "x-tt-trace-id": "00-ee06b309101a704d1-ee06b309101a704d-01" }), "lc_x" : "138417152",#Include lc_x if known. "sdk_ver": "v04.04.00-alpha.10-ov-android",#You can send it randomly if you wish, but "sdk_ver": "v04.04.01-alpha.10-ov-android" should not be exceeded. "ms_token": "",#You can send it if available, usually required after "sdk_ver": "v05.00.03-alpha.10-ov-android". "p_x": "",#It is a data associated with ms_token, should not be sent together. "get_token": ""#You can send if token is obtained, otherwise send empty. }
Response Body Example
{ "X-Argus": "uHhD5s3xTEznQZjnoQxNtCp/XQs37NJ55SPoKlleZWrvEwUuxIi8ZVosf9RPK6hmLi8qNLQD6SwC1yJuh33RtA3dZwRgqp1HGoJTTRpTLT8HhdGzK70Wl2CUSP6PngFGTwBh2Bn251LHk4e/j1Q/14+pTRMxFEGGrxiNcFN+Wz0wQUYIdEPBFh0CY9FuHIoQpq2KlaabIer9gMneh7iTA0c+xi2t+QZ8cRn0bVDjBS02mEJI2CoifLSwo1TWuFqdlMHw/zgTfS/M6Pif04cBUZNv", "X-Gorgon": "0404fd1b00007a0ebae2f92b414141fa47516c0d8f5612acf1d3", "X-Khronos": "1709095423", "X-Ladon": "L0El/Gz5Pt/sVH79yBLL01CjmHBbmVML+ESxjKJzcmw0+3pV", "x-ss-dp": "1233", "x-ss-req-ticket": "1709164898120", "x-tt-trace-id": "00-f22aa748101e504d1-f22aa748101e504d-01" }
captcha
This section provides information about captcha up.
Endpoint
POST /captcha
Image data needs to be encrypted with base64 before sending for puzzle pieces.
Request Body Example
{ "puzzle": "/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDA..........Jjw1FFFMZ//Z", "piece": "iVBORw0KGgoAAAANSUhEUgAAAG4AAABuCAYAAADGWyb7AABAXElEQVR.........AElFTkSuQmCC"}
Response Body Example
{"modified_img_width": 552, "id": "24b83017d5fd8ecce92f38de964803651514f70c", "mode": "slide", "reply": [{"relative_time": 0, "x": 2, "y": 95}, {"relative_time": 86, "x": 3, "y": 95}, {"relative_time": 172, "x": 5, "y": 95}, {"relative_time": 258, "x": 7, "y": 95}, {"relative_time": 344, "x": 9, "y": 95}, {"relative_time": 430, "x": 10, "y": 95}, {"relative_time": 516, "x": 12, "y": 95}, {"relative_time": 602, "x": 14, "y": 95}, {"relative_time": 688, "x": 16, "y": 95}, {"relative_time": 774, "x": 17, "y": 95}, {"relative_time": 860, "x": 19, "y": 95}, {"relative_time": 946, "x": 21, "y": 95}, {"relative_time": 1032, "x": 23, "y": 95}, {"relative_time": 1118, "x": 24, "y": 95}, {"relative_time": 1204, "x": 26, "y": 95}, {"relative_time": 1290, "x": 28, "y": 95}, {"relative_time": 1376, "x": 30, "y": 95}, {"relative_time": 1462, "x": 31, "y": 95}, {"relative_time": 1548, "x": 33, "y": 95}, {"relative_time": 1634, "x": 35, "y": 95}, {"relative_time": 1720, "x": 37, "y": 95}, {"relative_time": 1806, "x": 38, "y": 95}, {"relative_time": 1892, "x": 40, "y": 95}, {"relative_time": 1978, "x": 42, "y": 95}, {"relative_time": 2064, "x": 44, "y": 95}, {"relative_time": 2150, "x": 45, "y": 95}, {"relative_time": 2236, "x": 47, "y": 95}, {"relative_time": 2322, "x": 49, "y": 95}, {"relative_time": 2408, "x": 51, "y": 95}, {"relative_time": 2494, "x": 52, "y": 95}, {"relative_time": 2580, "x": 54, "y": 95}, {"relative_time": 2666, "x": 56, "y": 95}, {"relative_time": 2752, "x": 58, "y": 95}, {"relative_time": 2838, "x": 59, "y": 95}, {"relative_time": 2924, "x": 61, "y": 95}, {"relative_time": 3010, "x": 63, "y": 95}, {"relative_time": 3096, "x": 65, "y": 95}, {"relative_time": 3182, "x": 66, "y": 95}, {"relative_time": 3268, "x": 68, "y": 95}, {"relative_time": 3354, "x": 70, "y": 95}, {"relative_time": 3440, "x": 72, "y": 95}, {"relative_time": 3526, "x": 73, "y": 95}, {"relative_time": 3612, "x": 75, "y": 95}, {"relative_time": 3698, "x": 77, "y": 95}, {"relative_time": 3784, "x": 78, "y": 95}, {"relative_time": 3870, "x": 80, "y": 95}, {"relative_time": 3956, "x": 82, "y": 95}, {"relative_time": 4042, "x": 84, "y": 95}, {"relative_time": 4128, "x": 85, "y": 95}, {"relative_time": 4214, "x": 87, "y": 95}, {"relative_time": 4300, "x": 89, "y": 95}, {"relative_time": 4386, "x": 91, "y": 95}, {"relative_time": 4472, "x": 92, "y": 95}, {"relative_time": 4558, "x": 94, "y": 95}, {"relative_time": 4644, "x": 96, "y": 95}, {"relative_time": 4730, "x": 98, "y": 95}, {"relative_time": 4816, "x": 99, "y": 95}, {"relative_time": 4902, "x": 101, "y": 95}, {"relative_time": 4988, "x": 103, "y": 95}, {"relative_time": 5074, "x": 105, "y": 95}, {"relative_time": 5160, "x": 106, "y": 95}, {"relative_time": 5246, "x": 108, "y": 95}, {"relative_time": 5332, "x": 110, "y": 95}, {"relative_time": 5418, "x": 112, "y": 95}, {"relative_time": 5504, "x": 113, "y": 95}, {"relative_time": 5590, "x": 115, "y": 95}, {"relative_time": 5676, "x": 117, "y": 95}, {"relative_time": 5762, "x": 119, "y": 95}, {"relative_time": 5848, "x": 120, "y": 95}, {"relative_time": 5934, "x": 122, "y": 95}, {"relative_time": 6020, "x": 124, "y": 95}, {"relative_time": 6106, "x": 126, "y": 95}, {"relative_time": 6192, "x": 127, "y": 95}, {"relative_time": 6278, "x": 129, "y": 95}, {"relative_time": 6364, "x": 131, "y": 95}, {"relative_time": 6450, "x": 133, "y": 95}, {"relative_time": 6536, "x": 134, "y": 95}, {"relative_time": 6622, "x": 136, "y": 95}, {"relative_time": 6708, "x": 138, "y": 95}, {"relative_time": 6794, "x": 140, "y": 95}, {"relative_time": 6880, "x": 141, "y": 95}, {"relative_time": 6966, "x": 143, "y": 95}, {"relative_time": 7052, "x": 145, "y": 95}, {"relative_time": 7138, "x": 147, "y": 95}, {"relative_time": 7224, "x": 148, "y": 95}, {"relative_time": 7310, "x": 150, "y": 95}]}
Python Code Example
import json import requests import base64 import time import random from urllib.parse import urlencode api_captcha = "https://tikapis.com/api/captcha" class Solver: def __init__(self, device_info, _host): self.__host = _host self.__device = device_info self.__client = requests.Session() def __params(self): params = { "lang": "en", "app_name": self.__device["app_name"], "iid": self.__device["install_id"], "did": self.__device["device_id"], "device_id": self.__device["device_id"], "aid": self.__device["aid"], "os_type": "0", "tmp": f"{int(time.time())}{random.randint(111, 999)}", "platform": "app", "webdriver": "false", "verify_host": f"https://{self.__host}/", "locale": self.__device["lang_b"], "vc": self.__device["app_version"], "app_version": self.__device["app_version"], "resolution": self.__device["resolution"], "device_brand": self.__device["device_brand"], "device_model": self.__device["device_model"], "os_name": "Android", "challenge_code": "1105", } return urlencode(params) def __headers(self): headers = { "Fastly-Client-IP": '{}.{}.{}.{}'.format(*random.sample(range(0, 255), 4)), } return headers def __get_challenge(self): for _ in range(3): try: response = self.__client.get( f"https://{self.__host}/captcha/get?{self.__params()}", headers=self.__headers() ) response.raise_for_status() data = response.json() if 'data' in data and 'question' in data['data'] and 'tip_y' in data['data']['question']: return data except Exception as e: print(f"Error retrieving captcha challenge: {e}") time.sleep(1) raise Exception( "Failed to retrieve captcha challenge after 3 attempts") def api_captcha_solver(self, puzzle, piece): puzzle_str = puzzle.decode('utf-8') if isinstance(puzzle, bytes) else puzzle piece_str = piece.decode('utf-8') if isinstance(piece, bytes) else piece body = { "puzzle": puzzle_str, "piece": piece_str, } response = self.__client.post( api_captcha, headers={ 'Content-Type': 'application/json', "api-key": API_KEY }, data=json.dumps(body) ) return response.json() def __solve_captcha(self, url_1, url_2): puzzle = base64.b64encode(self.__client.get(url_1).content) piece = base64.b64encode(self.__client.get(url_2).content) maxloc = self.api_captcha_solver(puzzle, piece) time.sleep(random.uniform(0.8, 1.3)) return maxloc def __post_captcha(self, solve): body = { "modified_img_width": 552, "id": solve["id"], "mode": "slide", "reply": list( { "relative_time": i * solve["randlenght"], "x": round( solve["maxloc"] / (solve["randlenght"] / (i + 1)) ), "y": solve["tip"], } for i in range( solve["randlenght"] ) ), } headers = self.__headers() headers.update({"content-type": "application/json"}) response = self.__client.post( f"https://{self.__host}/captcha/verify?{self.__params()}", headers=headers, json=body ) return response.json() def solve_captcha(self): captcha_challenge = self.__get_challenge() captcha_id = captcha_challenge["data"]["id"] tip_y = captcha_challenge["data"]["question"]["tip_y"] solve_info = self.__solve_captcha( captcha_challenge["data"]["question"]["url1"], captcha_challenge["data"]["question"]["url2"], ) solve_info.update({"id": captcha_id, "tip": tip_y}) return self.__post_captcha(solve_info)
Python Code Example
tikapis.py
api_captcha = "https://tikapis.com/api/captcha" API_URL = "https://tikapis.com/api/android" # or /api/ios or api/web API_KEY = ""
Python Code Example
You can edit the following api according to your request.
example_tikapis.py
import requests import json import random import traceback import time from utilities import Utils from HTTPRequester import HTTPRequester class TikApis: def __init__(self, **kwargs): API_KEY = '' self.config = kwargs self.API_URL = "https://tikapis.com/api/android" self.DOMAIN_NORMAL = random.choice(["api-va.tiktokv.com"]) self.headers = {'api-key': API_KEY, 'Content-Type': 'application/json'} self.proxy = self.config.get("proxy", "") self._setup_proxy() self.http_requester = HTTPRequester( proxies=self.proxy, app=self.config, API_URL=self.API_URL, API_HEADERS=self.headers) def _setup_proxy(self): proxy = self.proxy if proxy: proxy_type = "SOCKS5" if "socks5" in proxy.lower() else "HTTP" print(f"Using {proxy_type} proxy: {proxy}") return self.fetch_additional_data(proxy) else: print("No proxy provided. Using local network.") return self.fetch_additional_data() def fetch_additional_data(self, proxy=None): try: proxies = {'http': f'http://{proxy}', 'https': f'https://{proxy}'} if proxy else None response = requests.get( "https://ipinfo.io/json", proxies=proxies, timeout=10) response.raise_for_status() response_data = response.json() print(response_data) country_code = response_data.get("country", "US") lang_k = "en" if country_code == "us" else country_code self.set_config(**{ "tz_name": response_data.get("timezone", "America/New_York"), "lang_b": country_code, "lang_k": lang_k.lower(), }) except Exception as e: traceback.print_exc() self.set_config(**{ "tz_name": random.choice(["America/New_York", "America/Chicago", "America/Denver", "America/Los_Angeles"]), "lang_b": "US", "lang_k": "en", }) def set_config(self, **kwargs): return self.config.update(kwargs) def error_check(self, response): if isinstance(response, dict) and 'error' in response: return response return None def payload_data(self, data): if not data: return "" elif isinstance(data, bytes): payload = data.decode() if payload.startswith('b\'') and payload.endswith('\''): return data elif payload.startswith('b"') and payload.endswith('"'): return data else: return data.hex() elif isinstance(data, str): try: parsed_data = json.loads(data) return json.dumps(parsed_data) except ValueError: return data else: try: return json.dumps(data) except ValueError: return data def session_cookie(self, response): if 'headers' in dir(response) and "set-cookie" in response.headers: set_cookie_header = response.headers.get("set-cookie", "") if set_cookie_header: cookies = Utils.parse_set_cookie_headers(set_cookie_header) existing_cookies = dict() if "cookie" in self.config: existing_cookie_list = self.config["cookie"].split("; ") for cookie in existing_cookie_list: key_value = cookie.split("=") if len(key_value) == 2: existing_cookies[key_value[0].strip( )] = key_value[1].strip() for key, value in cookies.items(): if not value: continue existing_cookies[key] = value new_cookie_string = "; ".join( [f"{key}={value}" for key, value in existing_cookies.items()]) self.config["cookie"] = new_cookie_string for key, value in cookies.items(): setattr(self, key, value) else: return def get_sign(self, url, data="", extra_headers={}): payload = {**self.config, "url": url, "data": self.payload_data(data), "headers": json.dumps(extra_headers)} response = requests.post( f"{self.API_URL}/get_sign", headers=self.headers, json=payload) if response.status_code == 200: try: response_data = response.json() return response_data if 'X-Argus' in response_data else response.content except ValueError: return response.content return response.content def device_template(self): response = requests.post( f"{self.API_URL}/device_template", headers=self.headers, data=json.dumps(self.config)) if response.status_code == 200: try: response_data = response.json() if 'package_name' in response_data: return self.set_config(**response_data) else: return response.content except ValueError: return response.content return response.content def check_and_convert(self, payload): if isinstance(payload, str): try: return bytes.fromhex(payload) except ValueError: return payload else: return payload def tiktok_auto_request(self, load): try: if "method" not in load: return json.dumps(load) if (load["method"] == "POST"): response = self.http_requester.post( load["url"], headers=load["headers"], data=self.check_and_convert(load["payload"])) self.session_cookie(response) error = self.error_check(response) if error: return error return response.content elif (load["method"] == "GET"): response = self.http_requester.get( load["url"], headers=load["headers"]) error = self.error_check(response) if error: return error self.session_cookie(response) return response.content else: return json.dumps(load) except Exception as e: print({"error": str(e), "traceback": traceback.format_exc(), }) return json.dumps(load) def api_request(self, endpoint, payload={}): response = requests.post( f"{self.API_URL}/{endpoint}", headers=self.headers, data=json.dumps({**payload, **self.config})) return response.json() def extract_ids(self, data): decoded_data = data.decode('utf-8') json_data = json.loads(decoded_data) self.set_config(**{ "new_user": json_data.get("new_user"), "device_id": json_data.get("device_id_str"), "install_id": json_data.get("install_id_str"), }) return self.set_config() def device_register(self): response = requests.post( f"{self.API_URL}/device_register", headers=self.headers, data=json.dumps(self.config)) if response.status_code == 200: try: response_data = response.json() if 'method' in response_data: self.extract_ids(self.tiktok_auto_request(response_data)) else: return response.content except ValueError: return response.content return response.content def get_token(self): response = requests.post( f"{self.API_URL}/get_token", headers=self.headers, data=json.dumps(self.config)) if response.status_code == 200: try: response_data = response.json() if 'method' in response_data: token = self.tiktok_auto_request(response_data) tiktok_hex_token = {"hex": token.hex()} get_token = self.api_request( "get_token_decode", tiktok_hex_token) if all(key in get_token for key in ["get_token"]): return self.set_config(**get_token) else: return response.content except ValueError: return response.content return response.content def get_seed(self): response = requests.post( f"{self.API_URL}/get_seed", headers=self.headers, data=json.dumps(self.config)) if response.status_code == 200: try: response_data = response.json() if 'method' in response_data: a = self.tiktok_auto_request(response_data) tiktok_hex_token = {"get_hex": a.hex()} get_token = self.api_request( "get_seed_decode", tiktok_hex_token) if all(key in get_token for key in ["ms_token", "p_x"]): return self.set_config(**get_token) else: return response.content except ValueError: return response.content return response.content def app_region(self, email): try: query = Utils.generate_query(self.config, {}) payload = Utils.hashed_id(email) url = f"https://{self.DOMAIN_NORMAL}/passport/app/region/?{query}" headers = { "content-type": "application/x-www-form-urlencoded; charset=UTF-8", "sdk-version": "2", "cookie": self.config.get("cookie", ""), "x-tt-token": self.config.get("x_token", ""), "x-bd-client-key": self.config.get("x_bd_lanusk", ""), 'user-agent': Utils.userAgent(self.config) } headers.update(self.get_sign(url, payload, headers)) json_response = self.http_requester.post( url, headers=headers, data=payload) if 'data' in json_response and 'domain' in json_response: self.session_cookie(json_response) return json_response.json() else: return json_response.json() except Exception as e: traceback.print_exc() def follow(self): extra = {"user_id": "107955", "sec_user_id": "", "type": "1"} domain = self.config.get( "domain", self.DOMAIN_NORMAL).replace("c-", "") end_point = Utils.get_follow_endpoint(self.config.get("aid", -1)) domain = self.DOMAIN_NORMAL url = f"https://{domain}/{end_point}?{Utils.generate_query(self.config, extra)}" headers = ({ "sdk-version": "2", "cookie": self.config["cookie"] if "cookie" in self.config else "", "x-tt-token": self.config["x_token"] if "x_token" in self.config else "", "x-bd-client-key": self.config["x_bd_lanusk"] if "x_bd_lanusk" in self.config else "", 'user-agent': Utils.userAgent(self.config) }) headers.update(self.get_sign(url, "", headers)) response = self.http_requester.get(url, headers) error = self.error_check(response) if error: return error return response.content def digg(self): extra = {"aweme_id": "107955", "type": "1"} domain = self.config.get( "domain", self.DOMAIN_NORMAL).replace("c-", "") end_point = Utils.get_like_endpoint(self.config.get("aid", -1)) domain = self.DOMAIN_NORMAL url = f"https://{domain}/{end_point}?{Utils.generate_query(self.config, extra)}" headers = ({ "sdk-version": "2", "cookie": self.config["cookie"] if "cookie" in self.config else "", "x-tt-token": self.config["x_token"] if "x_token" in self.config else "", "x-bd-client-key": self.config["x_bd_lanusk"] if "x_bd_lanusk" in self.config else "", 'user-agent': Utils.userAgent(self.config) }) headers.update(self.get_sign(url, "", headers)) response = self.http_requester.get(url, headers) error = self.error_check(response) if error: return error return response.content def account_register(self, email, password): app_region = self.app_region(email) print("app_region", app_region) if isinstance(app_region, bytes): app_region = app_region.decode('utf-8') if app_region and "data" in app_region and "domain" in app_region["data"]: domain_info = app_region["data"] else: domain_info = Utils.domain_chose(self.config.get("cookie", "")) self.captcha_domain = domain_info["captcha_domain"] self.DOMAIN_NORMAL = domain_info["domain"] extra = { "passport-sdk-version": self.config.get("passport_sdk_version", "19"), "uoo": "0", "cronet_version": self.config.get("cronet_version", ""), "ttnet_version": self.config.get("okhttp_version", ""), "use_store_region_cookie": "1" } query = Utils.generate_query(self.config, extra) payload = f"password={Utils._xor_tiktok(password)}&fixed_mix_mode=1&rules_version=v2&mix_mode=1&multi_login=1&email={Utils._xor_tiktok(email)}&account_sdk_source=app&birthday={Utils.generate_random_birthdate()}&multi_signup=0" url = f"https://{self.DOMAIN_NORMAL}/passport/email/register/v2/?{query}" headers = { "content-type": "application/x-www-form-urlencoded; charset=UTF-8", "sdk-version": "2", "cookie": self.config["cookie"] if "cookie" in self.config else "", "x-tt-token": self.config["x_token"] if "x_token" in self.config else "", "x-bd-client-key": self.config["x_bd_lanusk"] if "x_bd_lanusk" in self.config else "", 'user-agent': Utils.userAgent(self.config) } headers.update(self.get_sign(url, payload, headers)) r = self.http_requester.post(url, headers=headers, data=payload) error = self.error_check(r) if error: return error if hasattr(r, 'headers') and "x-tt-token" in r.headers and len(r.headers.get("x-tt-token", "")) > 0: response_json = r.json() set_cookie_headers = r.headers.get("x-tt-token") if set_cookie_headers: self.session_cookie(r) self.set_config(**{ "email": email, "password": password, "user": json.dumps(response_json.get("data")), "x_token": r.headers.get("x-tt-token"), "x_bd_lanusk": r.headers.get("x-bd-lanusk", ""), "device_platform": "android", "is_bot": 1, **self.config, "domain": self.DOMAIN_NORMAL, }) time.sleep(2) print(self.follow()) print(self.digg()) else: return r.content device = { "aid": "1233", "app_version": "33.7.3", "version_code": "330703", "manifest_version_code": "2023307030", "update_version_code": "2023307030", "sdk_ver": "v05.00.06-alpha.10-ov-android", # "proxy": "username:pass@host:port", } tik_api = TikApis(**device) tik_api.device_template() tik_api.device_register() # tik_api.get_token() print(json.dumps(tik_api.config)) # print("\n") active_device = { "1": 'app_alert_check', # "2": 'log_settings', # "3": 'log_settings_2', # "4": 'report_mode_change_2', # "5": 'app_log', # "6": 'app_log_2', # "7": 'app_log_3', # "9": 'monitor_collect1', # "10": 'get_appmonitor_settings', # "3": 'monitor_collect', # "12": 'get_common', # "13": 'request_combine', # "14": 'check_in', # "15": 'store_region', # "16": 'trust_users', # "17": 'monitor_appmonitor', # "18": 'unificationprivacysettings', # "19": 'unificationsettingsrestriction', # "20": 'compliance_settings', # "21": 'policy_notice', # "22": 'cmpl_settings', # "23": "user_login_report", # "24": "user_login_logged", "25": "report_did_iid_update", # "26": "dyn_task", # "27": "get_dctoken", # "28": "report_image", } for key, value in active_device.items(): api = tik_api.api_request(value) tiktok_auto_request = tik_api.tiktok_auto_request(api) print(f"Response: {value} -> value", {tiktok_auto_request}) print("\n") print("\n") time.sleep(5) account_register = tik_api.account_register( f"abcf{random.randint(5,999)}321313{random.randint(5,999)}[email protected]", Utils.generate_random_password()) print("account_register", account_register) print("\n") print(json.dumps(tik_api.config))
Python Code Example
import random import time import hashlib from datetime import datetime as dt from urllib.parse import urlencode class Utils: @staticmethod def parse_set_cookie_headers(set_cookie_headers): cookies = {} if set_cookie_headers: cookie_headers = set_cookie_headers.split(", ") for cookie_header in cookie_headers: parts = cookie_header.split(";") if parts: cookie = parts[0] cookie_key_value = cookie.split("=") if len(cookie_key_value) == 2: key = cookie_key_value[0].strip() value = cookie_key_value[1].strip() if value: cookies[key] = value return cookies @staticmethod def get_follow_endpoint(aid): if int(aid) == 1340: return "lite/v2/relation/follow/" else: return "aweme/v1/commit/follow/user/" @staticmethod def get_like_endpoint(aid): if int(aid) == 1340: return "lite/v2/item/digg/" else: return "aweme/v1/commit/item/digg/" @staticmethod def generate_random_password(): length = random.randint(10, 16) special_chars = "@+" uppercase_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" lowercase_chars = "abcdefghijklmnopqrstuvwxyz" digits = "0123456789" password_chars = [random.choice(special_chars)] password_chars += [random.choice(uppercase_chars) for _ in range(random.randint(1, 3))] remaining_length = length - len(password_chars) password_chars += [random.choice(lowercase_chars + digits) for _ in range(remaining_length)] random.shuffle(password_chars) password = ''.join(password_chars) return password @staticmethod def domain_chose(cookie: str = None): domains = { "maliva": [ "api16-normal-c-alisg.tiktokv.com", "api19-normal-c-alisg.tiktokv.com", "api21-normal-c-alisg.tiktokv.com", "api22-normal-c-alisg.tiktokv.com", ], "useast1a": [ "api16-normal-c-useast1a.tiktokv.com", "api19-normal-c-useast1a.tiktokv.com", "api22-normal-c-useast1a.tiktokv.com" ], "useast2a": [ "api16-normal-c-useast2a.tiktokv.com", "api19-normal-c-useast2a.tiktokv.com", "api21-normal-c-useast2a.tiktokv.com", "api22-normal-c-useast2a.tiktokv.com" ], "us": [ "api16-normal-useast5.us.tiktokv.com", "api19-normal-useast5.us.tiktokv.com" ] } captcha_urls = [ "verify-sg.tiktokv.com", "verification-va.byteoversea.com" ] if cookie: cookie_dict = Utils.parse_cookies(cookie) tt_target_idc = cookie_dict.get('tt-target-idc', None) if tt_target_idc and tt_target_idc in domains: domain_choices = domains[tt_target_idc] else: domain_choices = [domain for sublist in domains.values() for domain in sublist] else: domain_choices = [domain for sublist in domains.values() for domain in sublist] login_url = random.choice(domain_choices) captcha_url = random.choice(captcha_urls) return {"domain": login_url, "captcha_domain": captcha_url} @staticmethod def parse_cookies(cookie_str): cookie_dict = {} items = cookie_str.split(';') for item in items: parts = item.strip().split('=') if len(parts) == 2: key, value = parts key = key.strip() value = value.strip() if key in cookie_dict: if isinstance(cookie_dict[key], list): cookie_dict[key].append(value) else: cookie_dict[key] = [cookie_dict[key], value] else: cookie_dict[key] = value cookie_dict = {k: v for k, v in cookie_dict.items() if v is not None and v != ''} return cookie_dict @staticmethod def _xor_tiktok(string): encrypted = [hex(ord(c) ^ 5)[2:] for c in string] return "".join(encrypted) @staticmethod def hashed_id(value): hashed_id = value + "aDy0TUhtql92P7hScCs97YWMT-jub2q9" type = "2" if "@" in value else "3" hashed_value = hashlib.sha256(hashed_id.encode()).hexdigest() return f"hashed_id={hashed_value}&type={type}" @staticmethod def strip_strings(item): if isinstance(item, str): return item.strip() elif isinstance(item, list): return [Utils.strip_strings(sub_item) for sub_item in item] elif isinstance(item, dict): return {key: Utils.strip_strings(value) for key, value in item.items()} else: return item @staticmethod def userAgent(dev_info): device_model_or_type = dev_info['device_model'] if 'device_model' in dev_info else dev_info.get('device_type', 'Unknown') build_id_part = f"; Build/{dev_info['build_id']}" if 'build_id' in dev_info and dev_info['build_id'] else "" return f"{dev_info['package_name']}/{dev_info['update_version_code']} (Linux; U; Android {dev_info['os_version']}; {dev_info['lang_k']}_{dev_info['lang_b']}; {dev_info['os_version']}; {device_model_or_type}{build_id_part})" @staticmethod def generate_query(dev_info, extra=None): if extra is None: extra = {} app_type = "ttn" if int(dev_info.get("aid", -1)) == 385522 else "normal" dev_info["app_type"] = app_type manifest_version_code = update_version_code = "-1" if app_type == "ttn" else dev_info.get("manifest_version_code", "-1") update_version_code = dev_info.get("update_version_code", "-1") time_ts = int(time.time()) url_params = { "manifest_version_code": manifest_version_code, "_rticket": str(int(round(time_ts * 1000))), "current_region": dev_info.get("lang_b", ""), "app_language": dev_info.get("lang_k", ""), "app_type": dev_info.get("app_type", ""), "iid": dev_info.get("install_id", ""), "channel": "googleplay", "device_type": dev_info.get("device_model", ""), "language": dev_info.get("lang_k", ""), "locale": f'{dev_info.get("lang_k", "")}-{dev_info.get("lang_b", "")}', "resolution": dev_info.get("resolution", "").replace("x", "*"), "openudid": dev_info.get("openudid", ""), "update_version_code": update_version_code, "ac2": "wifi5g", "cdid": dev_info.get("cdid", ""), "sys_region": dev_info.get("lang_b", ""), "os_api": dev_info.get("os_api", ""), "timezone_name": dev_info.get("tz_name", "").replace("/", "%2F"), "dpi": dev_info.get("dpi", ""), "carrier_region": dev_info.get("lang_b", ""), "ac": "wifi", "device_id": dev_info.get("device_id", ""), "mcc_mnc": dev_info.get("mcc_mnc", ""), "os_version": str(dev_info.get("os_version", "")), "timezone_offset": dev_info.get("tz_offset", ""), "version_code": dev_info.get("version_code", ""), "app_name": dev_info.get("app_name", ""), "version_name": dev_info.get("app_version", ""), "device_brand": dev_info.get("device_brand", ""), "op_region": dev_info.get("lang_b", ""), "ssmix": "a", "device_platform": "android", "build_number": dev_info.get("app_version", ""), "region": dev_info.get("lang_b", ""), "aid": dev_info.get("aid", ""), "ts": str(time_ts), } if not url_params["iid"]: del url_params["iid"], url_params["device_id"] url_params.update(extra) query = urlencode(url_params, safe="%2F") return query.replace("/", "%2F").replace("+", "%20").replace("+", "%20").replace("+", "%20").replace("+", "%20") @staticmethod def generate_random_birthdate(): current_year = dt.now().year birth_year = random.randint(current_year - 50, current_year - 18) birth_month = random.randint(1, 12) if birth_month == 2: if (birth_year % 4 == 0 and birth_year % 100 != 0) or (birth_year % 400 == 0): max_day = 29 else: max_day = 28 elif birth_month in [4, 6, 9, 11]: max_day = 30 else: max_day = 31 birth_day = random.randint(1, max_day) return f"{birth_year}-{birth_month:02d}-{birth_day:02d}"
Python Code Example
import requests import json url = "https://tikapis.com/api/android/get_sign" payload = json.dumps({ "url": "https://api16-normal-c-useast2a.tiktokv.com/aweme/v1/commit/follow/user/?user_id=2342342&type=1manifest_version_code=2023301020&_rticket=1709095423862¤t_region=DE&app_language=de&iid=0&channel=huaweistore&device_type=JNY-LX1&language=de&locale=de-DE&resolution=2208*1080&openudid=862354e82ba89e61&update_version_code=2023301020&ac2=wifi5g&cdid=7a5108c4-1ce7-4807-a5d1-c428ed5c895d&sys_region=DE&os_api=29&timezone_name=Europe%2FBerlin&dpi=480&carrier_region=DE&ac=wifi&device_id=1&mcc_mnc=28601&os_version=10&timezone_offset=3600&version_code=330102&app_name=musical_ly&version_name=33.1.2&device_brand=huawei&op_region=DE&ssmix=a&device_platform=android&build_number=33.1.2®ion=DE&aid=1233&ts=1709095423&passport-sdk-version=19&uoo=0&cronet_version=4.2.137.43-tiktok&ttnet_version=2fdb62f9_2023-09-06&use_store_region_cookie=1", "headers": { "content-type": "application/x-www-form-urlencoded; charset=UTF-8", "cookie": "passport_csrf_token=e8b45654654656548f5642343426565460d00763b; passport_csrf_token_default=e8b45654654656548f5642343426565460d00763b;", "passport-sdk-version": "19", "sdk-version": "2", "user-agent": "com.zhiliaoapp.musically/2023301020 (Linux; U; Android 10; de_DE; 10; JNY-LX1; Build/OPHZ.604442.570)", "x-ss-dp": "1233", "x-tt-local-region": "de", "x-tt-store-region": "de", "x-tt-store-region-src": "did", "x-tt-trace-id": "00-ee06b309101a704d1-ee06b309101a704d-01" }, "data": "", "lc_x" : "208700416", #Include lc_x if known. "sdk_ver": "v05.00.06-alpha.10-ov-android",#You can send it randomly if you wish, but "sdk_ver": "v04.04.01-alpha.10-ov-android" should not be exceeded. "get_token": ""#You can send if token is obtained, otherwise send empty. }) headers = { 'api-key': 'API-KEY', 'Content-Type': 'application/json' } response = requests.request("POST", url, headers=headers, data=payload) print(response.text)
Python Code Example
import ssl import requests from requests.adapters import HTTPAdapter from requests.exceptions import HTTPError, ProxyError, ConnectionError, Timeout, RequestException import traceback from urllib.parse import urlparse, urljoin import json class SSLAdapter(HTTPAdapter): def __init__(self, ssl_context, **kwargs): self.ssl_context = ssl_context super().__init__(**kwargs) def init_poolmanager(self, *args, **kwargs): kwargs['ssl_context'] = self.ssl_context super().init_poolmanager(*args, **kwargs) class HTTPRequester: def __init__(self, API_URL, API_HEADERS, proxies=None, app=None): self.app = app self.proxies = proxies self.API_URL = API_URL self.API_HEADERS = API_HEADERS self.ctx = self._create_ssl_context() self.session = self._create_client() @staticmethod def _create_ssl_context() -> ssl.SSLContext: ctx = ssl.create_default_context() ciphers = ( 'ECDHE+AESGCM:ECDHE+CHACHA20:DHE+AESGCM:DHE+CHACHA20:' 'ECDHE+AES256:ECDHE+AES128:DHE+AES256:DHE+AES128:' 'RSA+AESGCM:RSA+AES:!aNULL:!eNULL:!MD5:!DSS:!RC4' ) ctx.set_ciphers(ciphers) return ctx def _create_client(self): session = requests.Session() ssl_adapter = SSLAdapter(self.ctx) session.mount('https://', ssl_adapter) if self.proxies: session.proxies.update({ 'http': f'http://{self.proxies}', 'https': f'http://{self.proxies}', }) return session def complete_url(self, partial_url, base_url="https://"): parsed_url = urlparse(partial_url) if not parsed_url.scheme: return urljoin(base_url, partial_url) else: return partial_url def payload_data(self, data): if not data: return "" elif isinstance(data, bytes): return data.hex() elif isinstance(data, str): try: parsed_data = json.loads(data) return json.dumps(parsed_data) except ValueError: return data else: try: return json.dumps(data) except ValueError: return data def argus_redirect(self, url, data, headers): try: payload = json.dumps({ "url": url, "data": self.payload_data(data), "headers": json.dumps(headers) }) response = requests.post(f"{self.API_URL}/get_sign", headers=self.API_HEADERS, data=payload) return response.json() except Exception as e: traceback.print_exc() def _send_request(self, method, url, headers=None, data=None, allow_redirects=False, **kwargs): try: history = [] response = self.session.request( method, url, headers=headers, data=data, allow_redirects=allow_redirects, **kwargs) history.extend(response.history) while response.is_redirect: url = self.complete_url(response.headers['Location']) print("Redirecting to:", url) history.append(url) updated_headers = headers.copy() if headers else {} generated_headers = self.argus_redirect(url, data if method == 'POST' and data else "", updated_headers) generated_headers.pop('Content-Type', None) updated_headers.update(generated_headers) if method == 'POST' and data: response = self.session.request( method, url, headers=updated_headers, data=data, allow_redirects=False, **kwargs) else: response = self.session.request( 'GET', url, headers=updated_headers, allow_redirects=False, **kwargs) response.raise_for_status() return response except HTTPError as e: return {"error": "HTTP Error", "status_code": e.response.status_code, "reason": e.response.reason} except ProxyError as e: return {"error": "Proxy Error", "details": str(e)} except ConnectionError as e: return {"error": "Connection Error", "details": str(e)} except Timeout as e: return {"error": "Timeout Error", "details": str(e)} except RequestException as e: return {"error": "Request Exception", "details": str(e)} except Exception as e: return {"error": "General Error", "details": str(e), "traceback": traceback.format_exc()} def get(self, url, headers=None, **kwargs): return self._send_request('GET', url, headers=headers, **kwargs) def post(self, url, headers=None, data=None, **kwargs): return self._send_request('POST', url, headers=headers, data=data, **kwargs)