Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save nis267/74c6315f6dbd24a0b8889acdd08789e6 to your computer and use it in GitHub Desktop.
Save nis267/74c6315f6dbd24a0b8889acdd08789e6 to your computer and use it in GitHub Desktop.
### BY: MUNFAQQIHA ####################################################################################################################################
######################### A BASH SHELL SCRIPT FOR LINUX AND WINDOWS TO AUTOMATICALLY NON-STOP UPLOAD FILES TO WWW.TERABOX.COM #########################
#######################################################################################################################################################
### ----------------------------------------------------------------------------------------------------------------------------------------------- ###
### | sample of successful upload: on linux: https://s.id/teraupnix || on windows: https://s.id/teraupwin | ###
### ----------------------------------------------------------------------------------------------------------------------------------------------- ###
### it is possible to upload multiple different types of files recursively, except 0-byte file size, in a folder where you run it. The maximum size ###
### of a single uploaded file allowed by terabox is 2147483648 Bytes (2.00 GiB). if a file exceeds that, this script will split it into pieces, and ###
### 120MiB is the upper limit of a single segment size allowed for multipart upload. however, terabox limits the maximum size of a single file that ###
### can be stored on their server. the total size of a single file for premium user is limited to 21474836479 Bytes (20.00 GiB), & 4294967296 Bytes ###
### (4.00 GiB) for a free member - https://s.id/1IMx2. ###
### ----------------------------------------------------------------------------------------------------------------------------------------------- ###
### ###
### catch the following steps to make it successful (run it on VPS / RDP for faster speed): ###
### ###
### 1. install jq: ###
### ###
### a. on linux do as usual. ###
### b. on windows: choose one of the following: ###
### (1). install linux with WSL: ubuntu or debian (highly recommended). ###
### (2). install gitforwindows (gitforwindows.org). ###
### (*). choose all of its default options. ###
### (*). run this on its shell: curl -Lo /usr/bin/jq.exe https://github.com/stedolan/jq/releases/latest/download/jq-win64.exe && jq -V ###
### ###
### 2. set the value for each of the following variables: ###
### ###
### it is all those little steps to get the value of the following 3 variables jt (jsToken), bt (bdstoken), and co (cookie): ###
### ###
### a. login to terabox account via chrome on desktop. ###
### b. press CTRL + R, then F12, next type "getinfo" in the "Filter" column ###
### c. so click "Networks" tab, right-click the url that says "getinfo" ###
### d. select copy >> Copy as cURL (bash), and don't event miss to paste it into your text editor. its usage is below: ###
### ###
### (1). for "jt" value, copy from "jsToken" section after "=" sign and before "&". ###
### (2). for "bt" value, copy from "bdstoken" section after as "jt" above. ###
### (3). for "co" value, copy from "cookie" section as usually. ###
### ###
### jt="" ###
### bt="" ###
### co="" ###
### ###
### e. the next let you go to fill out all variables (pay attention to text case): ###
### ###
### (1). full location path of a folder containing the files to be uploaded to terabox. ###
### ###
### # sample output of pwd command on linux shell. ###
### fl="/home/munfaqqiha/Pilem/Jadul" ###
### ###
### # sample output of pwd command on gitforwindows shell. ###
### fl="/c/Pilem/Jadul" ###
### ###
### (2). full path of your terabox folder where you'd like to store your files. ###
### ###
### rf="/Pilem/Jadul" ###
### ###
### (3). do you wanna move your files to another place after they're uploaded?: <yes/no>. ###
### ###
### mv="no" ###
### ###
### (4). if you decide that, please specify a full path of a backup folder to move them. ###
### ###
### # sample output of pwd command on linux shell. ###
### bu="/home/munfaqqiha/Pilem/Backup" ###
### ###
### # sample output of pwd command on gitforwindows shell. ###
### bu="/c/Pilem/Backup" ###
### ###
### (5). would you like to get a shared & download link of each uploaded file?: <yes/no>. all will be saved into a text file named "link.id". ###
### ###
### ds="yes" ###
### ###
### (6). while you'd agree to the points above, set its expiration date either 7, 30 (days), or 0 (forever). ###
### ###
### on="0" ###
### ###
### (7). please decide whether files may be deleted from the folder after they're uploaded: <yes/no>. ###
### ###
### rm="no" ###
### (9). amount of files to upload simultaneously (default 1) ###
### ###
### max_files_uploading="1" ###
### ###
#######################################################################################################################################################
### ALERT: ###
### .... After you've obtained your credentials, DO NOT press the "Sign Out" on the terabox.com when leaving it. It is enough to clear your cookies ###
### .... via the browser's built-in feature. If you do, then you'll not be able to upload files. You'll get an error something like: "need verify". ###
### ###
### NOTES: ###
### (*). it is also possible to run the code with the command: "bash yours.sh". if you picking on this, please include all variables in your file. ###
### (*). don't forget to watch a sample of successful upload on linux & windows at here: https://cuty.io/teraput. ###
### (*). for the multiple lines bash command code get it at here: https://cuty.io/linuxwintera. ###
#######################################################################################################################################################
### THE CODE STARTS FROM HERE #########################################################################################################################
set +H
jt="your stuffing"
bt="............."
co="............."
fl="............."
rf="............."
mv="............."
bu="............."
ds="............."
on="............."
rm="............."
max_files_uploading="1"
# Define a function to process a batch of files
process_file_upload() {
yu="$1"
nfo=$(curl -sL "${bo}" -A "${ua}" -b "${co}" -e "${bo}/" | perl -pe 's/\%(\w\w)/chr hex $1/ge' | sed "s#\"#\\n#g;s|:||g;s|,||g" | awk 'NF') &&
jt=$(echo "$nfo" | grep -i 'jstok.*' -A1 | tail -1) &&
bt=$(echo "$nfo" | grep -i 'bdsto.*' -A1 | tail -1) &&
sz=$(du -b "${yu}" 2>&- | awk '{print $1}') && fn="${yu}" &&
qt=$(curl -s "${bo}/api/quota?checkexpire=1&checkfree=1&app_id=250528&jsToken=${jt}" -A "${ua}" -b "${co}" -e "${bo}/") &&
to=$(echo "$qt" | jq -r '.total') && us=$(echo "$qt" | jq -r '.used') &&
if [[ ! ($(grep -s '[[:digit:]]' <<<${to})) || ! ($(grep -s '[[:digit:]]' <<<${on})) ||
(-z ${rf} || -z ${mv} || -z ${bu} || -z ${ds} || -z ${on} || -z ${rm} || -z ${max_files_uploading}) ]]; then
echo -e "\n$(echo "# recheck: the value of your variables, and don't forget to paste all on the shell." |
sed 's/# re.*ck:/\o033[1;41m&\o033[0m/I')" && exit 1
elif [[ $((to - us)) -lt ${sz} ]]; then
echo -e "\n$(echo "# quota: is smaller than the size of the current file ($(numfmt --to=iec-i --suffix=B --format='%.2f' ${sz} |
sed 's/[0-9]\+/& /2')). your remaining space is $(numfmt --to=iec-i --suffix=B --format='%.2f' $((to - us)) |
sed 's/[0-9]\+/& /2')." | sed 's/# quota:/\o033[1;41m&\o033[0m/I')" && exit 1
elif [[ -z "${sz/[ ]*\n/}" ]]; then
echo -e "\n$(echo '# notice: please double-check whether your file exists or not!.' |
sed 's/# notice:/\o033[1;41m&\o033[0m/I')" && return
else
echo -e "\n$(echo '### TERABOX: preparing..! ||' "$(echo "QUOTA:" $(numfmt --to=iec-i --suffix=B --format='%.2f' "$us" |
sed 's/[0-9]\+/& /2') / $(numfmt --to=iec-i --suffix=B --format='%.2f' "$to" | sed 's/[0-9]\+/& /2'))" \
$(printf "%$(tput cols)s" | tr " " "#") | cut -c -$COLUMNS |
sed -E 's/t.*x:|q.*:/\o033[1;41m&\o033[0m/Ig')\n" &&
if [[ (${vi} -eq 1 && ${sz} -le 21474836479) || (${vi} -eq 0 && ${sz} -le 4294967296) ]]; then
[[ ${sz} -ge 2147483648 ]] &&
echo -e "$(echo "# info: your file is larger than 2147483648 bytes (2.00 GiB). please wait it will be splitted into pieces!." |
sed 's/# info:/\o033[1;41m&\o033[0m/I')\n" &&
(split --verbose -b 120M "${yu}" --suffix-length=3 --numeric-suffixes=0 piece"${yu}" &&
echo -e $(ls -1 *piece"${yu}"[[:digit:]]* > "piece${yu}0a")) || echo "${yu}" > "piece${yu}0a"
else
echo -e "$(echo "# info: size limit exceeded!. the total size of a single file for a VIP user is limited to 21474836479 bytes, \
and 4294967296 bytes for a non." | sed 's/# info:/\o033[1;41m&\o033[0m/I')\n" && return
fi &&
cat "piece${yu}0a" | while read md; do
md5sum <<<"${md}" | md5sum | cut -d ' ' -f1 >>"piece${yu}0b"
done &&
md5=$(cat "piece${yu}0b" | sed -n 's/^/"/;s/$/"/;H;${x;s/\n/,/g;s/^,//;p}' | awk '{print "["$0"]"}') &&
fp=$(echo "${rf}/${yu}" | jq -Rr @uri) &&
tp=$(echo "${rf}/" | sed 's#/*$##;${s|$|/|}') &&
pc=$(curl -s "${bo}/api/precreate?app_id=250528&jsToken=${jt}" -A "${ua}" -b "${co}" -H "Origin: ${bo}" -e "${bo}/" \
--data-raw "path=${fp}&size=${sz}&autoinit=1&rtype=3&target_path=${tp}&block_list=${md5}") &&
echo "$pc" | jq -C --arg fs "$(numfmt --to=iec-i --suffix=B --format='%.2f' <<<${sz} | sed 's/[0-9]\+/& /2') (${sz} Bytes)" \
'.filesize = $fs | .block_list |= tostring' 2>&- || true &&
if grep -Eiq 'uploadid.*' <<<${pc}; then
echo -e "\n$(echo '### TERABOX: uploading..!' $(printf "%$(tput cols)s" | tr " " "#") | cut -c -$COLUMNS |
sed "s,t.*:,\o033[1;41m&\o033[0m,I")" &&
ui=$(echo $pc | jq -r '.uploadid') &&
bl=$(cat "piece${yu}0a" | wc -l) &&
pr=0 || pr=1 && ps=0 &&
while read mi; do
ls -1 *piece"${yu}"[[:digit:]]* &>/dev/null &&
echo -e "\n$(echo "# uploading: piece #${pr} of #${bl} left | file: ${mi} | md5: $(cat "piece${yu}0b" | head -1 &&
sed -i '1d' "piece${yu}0b")" | sed -e 's/# up.*ng:/\o033[1;41m&\o033[0m/Ig' -Ee 's/piece\s|left|file:|md5:/\x1b[32m&\x1b[0m/Ig')\n" ||
echo -e "$(true)" &&
up=$(curl -iF "file=@${mi}" "$(echo $bo | sed 's/www/c-jp/')/rest/2.0/pcs/superfile2?method=upload&type=tmpfile&app_id=250528&path=${fp}&uploadid=${ui}&partseq=${ps}" -A "${ua}" -b "${co}" -H "Origin: ${bo}" -e "${bo}/") &&
echo -e "\n$(echo "${up}" | tail -1 | jq -C 2>&-)" &&
echo "${up}" | sed '$!d' | jq -r '.md5' >>"piece${yu}0c" &&
((bl--)) && pr=$((pr + 1)) && ps=$(expr $ps + 1)
done < "piece${yu}0a" &&
md5=$(cat "piece${yu}0c" | sed -n 's/^/"/;s/$/"/;H;${x;s/\n/,/g;s/^,//;p}' | awk '{print "["$0"]"}') &&
if grep -Eiq 'md5.*' <<<${up}; then
echo -e "\n$(echo '### TERABOX: finishing..!' $(printf "%$(tput cols)s" | tr " " "#") | cut -c -$COLUMNS |
sed "s,t.*:,\o033[1;41m&\o033[0m,I")\n" &&
if [[ "${mv}" == *"yes"* ]]; then
mkdir -p "${bu}" && mv -f "${yu}" "${bu}"
elif [[ "${rm}" == *"yes"* ]]; then
rm -rf "${yu}"
fi &&
create=$(curl -s "${bo}/api/create?isdir=0&rtype=1&bdstoken=${bt}&app_id=250528&jsToken=${jt}" -A "${ua}" -b "${co}" -H "Origin: ${bo}" -e "${bo}/" \
--data-raw "path=${fp}&size=${sz}&uploadid=${ui}&target_path=${tp}&block_list=${md5}") &&
fi=$(echo -e "$(echo ${create} | jq --arg fs "$(numfmt --to=iec-i --suffix=B --format='%.2f' <<<${sz} | sed 's/[0-9]\+/& /2') (${sz} Bytes)" \
'.size = $fs | {"uploaded": "Glory to God for His great work!"} + .')") &&
grep -Eiq 'yes' <<<${ds} &&
pl=$(echo ${create} | jq '.path' | jq -Rr @uri) &&
pl=$(echo $pl | sed -n 'H;${x;s/\n/,/g;s/^,//;p}' | awk '{print "["$0"]"}') &&
sl=$(curl -s "${bo}/share/pset?app_id=250528&bdstoken=${bt}" -A "${ua}" -b "${co}" -e "${bo}/" \
--data-raw "schannel=0&channel_list=[0]&period=${on}&path_list=${pl}&public=1" | jq -r '.link') &&
ma=$(echo $sl | awk -F 's/1' '{print $2}') &&
dl=$(curl -s "${bo}/share/list?shorturl=${ma}&root=1&app_id=250528&jsToken=${jt}" -A "${ua}" -b "${co}" -e "${bo}/" | jq -r '.list[].dlink') &&
echo "$fi" | jq -C '.sharedlink="'"${sl}"'" | .downloadlink="'"${dl}"'"' &&
echo -e "Storedname: ${yu}\nSharedlink: ${sl}\nD/loadlink: ${dl}\n" >>link.id ||
echo "$fi" | jq -C && rm -rf *piece"${yu}"[[:digit:]]*
else
echo -e "\n$(echo '# notice: look at the uploading log above..!' $(echo "${up}" | grep -oi 'http.*' |
head -1 | sed 's/\s$//') | sed -e 's/# notice:/\o033[1;41m&\o033[0m/I' -e 's/http.*/\x1b[91m&\x1b[0m/Ig')"
fi
else
echo -e "\n$(echo '# notice: please, look at the precreate section..!' |
sed 's/# notice:/\o033[1;41m&\o033[0m/I')\n"
fi
fi
}
[[ -n ${fl} && -d ${fl} ]] && cd "${fl}" && ua='okhttp/7.4' && bo='https://www.terabox.com' && set +H &&
find . -name "*piece*[[:digit:]]*" ! -regex ".*\.\(sh\|id\)" -delete &&
echo -e "\n$(ls 2>&- --color -Ss1pq --block-size=1 "${PWD}/"*)" &&
readarray -t mi <<<"$(find . -type f ! -regex ".*\.\(sh\|id\)" -size +0 -printf "%f\n")" &&
[ $(echo "${mi[@]}" | wc -w) -gt 0 ] &&
vi=$(curl -s "${bo}/rest/2.0/membership/proxy/user?method=query" -A "${ua}" -b "${co}" -e "${bo}/" | jq -r '.data.member_info.is_vip') &&
# Process files
for yu in "${mi[@]}"; do
process_file_upload "${yu}" &
# Wait until the number of background jobs is less than the maximum allowed
while [ "$(jobs -r | wc -l)" -ge "$max_files_uploading" ]; do
sleep 1
done
done &&
wait &&
echo -e "\n$(ls 2>&- --color -Ss1pq --block-size=1 *)" ||
echo -e "\n$(echo "# notice: check the variable values of your file source directory and its existence or not!." |
sed 's/# notice:/\o033[1;41m&\o033[0m/I')\n"
### CODE ENDS HERE ####################################################################################################################################
@nis267
Copy link
Author

nis267 commented Feb 11, 2024

When uploading multiples files concurrently the output is mixed up because each file is uploaded in background. Maybe that is misleading but I think it's correctly uploading multiple files. I will also try again when I have time.

@Banaune
Copy link

Banaune commented Feb 17, 2024

@nis267 Is there some way to upload the files and folders recursively keeping the original folder structure?

@nis267
Copy link
Author

nis267 commented Feb 19, 2024

@nis267 Is there some way to upload the files and folders recursively keeping the original folder structure?

@Banaune with the actual script no for that I need to implement this feature.

@Banaune
Copy link

Banaune commented Feb 28, 2024

@nis267 That would be very helpful when uploading from headless machines.

@arnelap
Copy link

arnelap commented Mar 3, 2024

This is awesome, thanks to both developers!

Any chance more file management features will be added i the future, especially deleting files?
That way I could upload a backup and then delete the older version of that backup.

@Namlee123
Copy link

Namlee123 commented Mar 4, 2024

Hello @nis267 , thank you for what you do.
I run your code on bash.sh.

  1. Error: I get an error with the filename being too long and containing a comma:
  • Comma: curl: (26) Failed to open/read local data from file/application.
    --> I fixed it by inserting: "file=@\"${mi}\"" and it worked.
  • The name is too long: it will report that the file/folder does not exist and delete the file, regardless of "rm=no".
    --> Hope you can fix this error.
    File name: (Guzheng, Instrumental, Chinese) [CD] VA - High Mountains, Flowing Water (高山流水) (Selection of Masterpieces by Chinese Masters of Guzheng) - 2011, FLAC (image+.cue), lossless.zip
  1. Improvements:
  • If a file (F1) is larger than 2G, it will be split into 120M size files: F1.Chunk1, F1.Chunk2, F1.Chunk3... It uploads each file in turn. Do not upload simultaneously.
    --> I want the split files F1.Chunk1, F1.Chunk2, F1.Chunk3 to be uploaded simultaneously in the background, just like uploading files F1, F2, F3... As this will be extremely economical meantime.
  • With a Free account, the size of a file does not exceed 4G. But I have a 5G file.
    --> So you can create an additional subroutine, combined with zip or rar to separate the 5G file into 4G and 1G and then upload it.
    For example:
    File: xyz.zip (9G)
    linux zip: zip -s=4G -0 "xyz.zip.zip" "xyz.zip"
    result: xyz.zip.z01(4G), xyz.zip.z02 (4G), xyz.zip.zip (1G)
    ->start uploading those 3 files

Thanks.

@binhna
Copy link

binhna commented Dec 22, 2024

Hi, thank you for sharing your code! However, it seems that the bdstoken parameter is no longer present in the cURL. Additionally, I believe the website detects when the browser’s inspect mode is open, causing it to redirect to about:blank. To capture the getInfo request, you need to act quickly and copy it before the redirection happens

@VigramK
Copy link

VigramK commented Dec 23, 2024

Hi, thank you for sharing your code! However, it seems that the bdstoken parameter is no longer present in the cURL. Additionally, I believe the website detects when the browser’s inspect mode is open, causing it to redirect to about:blank. To capture the getInfo request, you need to act quickly and copy it before the redirection happens

What browser are you using? I am using Firefox and i can still open developer tools and access the network tab. The getInfo request found there still includes the bdstoken along with jsToken & cookie parameters.

@miju12
Copy link

miju12 commented Feb 16, 2025

Hi, thank you for sharing your code! However, it seems that the bdstoken parameter is no longer present in the cURL. Additionally, I believe the website detects when the browser’s inspect mode is open, causing it to redirect to about:blank. To capture the getInfo request, you need to act quickly and copy it before the redirection happens

i have made a tapermonkey script to capture it without any redirects

// ==UserScript==
// @name         Capture Terabox GetInfo Request with Cookies
// @namespace    http://tampermonkey.net/
// @version      1.2
// @description  Capture Terabox getinfo API request and copy as cURL with full headers and cookies
// @author       You
// @match        *://*.terabox.com/*
// @grant        GM_setClipboard
// ==/UserScript==

(function () {
    'use strict';

    console.log("[Tampermonkey] Script loaded for Terabox!");

    // Function to get all cookies as a string
    function getCookies() {
        return document.cookie.split("; ").map(cookie => `-H "Cookie: ${cookie}"`).join(" ");
    }

    // Hook into fetch API
    const originalFetch = window.fetch;
    window.fetch = async function (...args) {
        const response = await originalFetch(...args);

        if (args[0].includes("/api/user/getinfo")) {
            console.log("[Tampermonkey] Intercepted fetch getinfo request:", args);

            let headers = "";
            if (args[1] && args[1].headers) {
                for (const [key, value] of Object.entries(args[1].headers)) {
                    headers += `-H "${key}: ${value}" `;
                }
            }

            // Get cookies and add them to the headers
            const cookieHeader = getCookies();
            headers += ` ${cookieHeader}`;

            const curlCommand = `curl -X GET "${args[0]}" ${headers}`;
            console.log("[Tampermonkey] Generated cURL Command:", curlCommand);

            GM_setClipboard(curlCommand);
            alert("✅ cURL command copied to clipboard!\n\nIncludes authentication cookies.");
        }

        return response.clone();
    };

    // Hook into XHR API (for older requests)
    const originalOpen = XMLHttpRequest.prototype.open;
    XMLHttpRequest.prototype.open = function (method, url) {
        if (url.includes("/api/user/getinfo")) {
            console.log("[Tampermonkey] Intercepted XHR getinfo request:", method, url);

            const cookieHeader = getCookies();
            const curlCommand = `curl -X GET "https://www.terabox.com${url}" ${cookieHeader}`;
            console.log("[Tampermonkey] Generated XHR cURL Command:", curlCommand);

            GM_setClipboard(curlCommand);
            alert("✅ cURL command copied to clipboard!\n\nIncludes authentication cookies.");
        }
        return originalOpen.apply(this, arguments);
    };
})();

@KaemmeA
Copy link

KaemmeA commented Mar 10, 2025

@miju12 thanks for posting your script, it works like a charm. However, it seems like there is no cookie token in the copied cURL command. It only contains jsToken, pcftoken & bdstoken as url parameters and csrfToken inside a Cookie:

 -H "Cookie: csrfToken=..." 

What exactly do i have to assign as "co" value?

@eijkboy
Copy link

eijkboy commented Mar 19, 2025

@miju12 thanks for posting your script, it works like a charm. However, it seems like there is no cookie token in the copied cURL command. It only contains jsToken, pcftoken & bdstoken as url parameters and csrfToken inside a Cookie. What exactly do i have to assign as "co" value?

  1. Install Mozilla Firefox and Fiddler Classic.
  2. Open your Firefox then Fiddler Classic (make sure the File > Capture Traffic is checked).
  3. Sign in to your terabox.com account on Firefox.
  4. Back to Fiddler Classic, press CTR + F then paste and search getinfo.
  5. Right click on one of yellow highlighted text and select Copy > Headers only.
  6. Paste the copied text into text editor like notepad.
  7. Find and copy only the ndus part (it has 45 characters), i.e. ndus=SftCdCQeWuHQ6aSRDUliAGd8etw2cj076wXtYe6p.
  8. You can then assign it as co value, i.e. co="ndus=SftCdCQeWuHQ6aSRDUliAGd8etw2cj076wXtYe6p".

Hope this helps. Thank you.

@megateksis
Copy link

@miju12 thanks for posting your script, it works like a charm. However, it seems like there is no cookie token in the copied cURL command. It only contains jsToken, pcftoken & bdstoken as url parameters and csrfToken inside a Cookie. What exactly do i have to assign as "co" value?

1. Install [Mozilla Firefox](https://www.mozilla.org/en-US/firefox) and [Fiddler Classic](https://api.getfiddler.com/fc/latest).

2. Open your Firefox then Fiddler Classic (make sure the `File > Capture Traffic` is checked).

3. Sign in to your terabox.com account on Firefox.

4. Back to Fiddler Classic, press `CTR + F` then paste and search `getinfo`.

5. Right click on one of yellow highlighted text and select `Copy > Headers only`.

6. Paste the copied text into text editor like notepad.

7. Find and copy only the `ndus` part (it has 45 characters), i.e. `ndus=SftCdCQeWuHQ6aSRDUliAGd8etw2cj076wXtYe6p`.

8. You can then assign it as `co` value, i.e. `co="ndus=SftCdCQeWuHQ6aSRDUliAGd8etw2cj076wXtYe6p"`.

Hope this helps. Thank you.

Para conseguir obter os dados do site do terabox, que está em HTTPs, sigao tutorial abaixo:

https://docs.telerik.com/fiddler/configure-fiddler/tasks/firefoxhttps

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment