├── .gitignore
├── public
├── img
│ ├── icon.png
│ └── spinning-circles.svg
├── js
│ ├── disabledButton.js
│ ├── getUrl.js
│ └── app.js
├── index.html
└── css
│ └── style.css
├── package.json
├── README.md
├── index.js
└── src
└── tiktokDL.js
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
--------------------------------------------------------------------------------
/public/img/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zalazarc20/tiktokDL/HEAD/public/img/icon.png
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "tiktokdl",
3 | "version": "1.1.0",
4 | "description": "",
5 | "main": "index.js",
6 | "type": "module",
7 | "scripts": {
8 | "dev": "nodemon ./index.js",
9 | "start": "node index",
10 | "test": "echo \"Error: no test specified\" && exit 1"
11 | },
12 | "keywords": [],
13 | "author": "",
14 | "license": "ISC",
15 | "dependencies": {
16 | "axios": "^0.27.2",
17 | "body-parser": "^1.20.0",
18 | "express": "^4.18.1"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/public/js/disabledButton.js:
--------------------------------------------------------------------------------
1 | export const disabledButton = () => {
2 | let input = document.getElementById('url');
3 | let submit = document.getElementById('submit');
4 |
5 | document.addEventListener('DOMContentLoaded', e => {
6 | submit.disabled = true;
7 | });
8 |
9 | input.addEventListener('input', e => {
10 | if(e.target.value !== ''){
11 | submit.disabled = false;
12 | }
13 | if(e.target.value === '') {
14 | submit.disabled = true;
15 | }
16 | })
17 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ✅ Tiktok DL (Download videos of tiktok, No Watermark) ✌️
2 |
3 | > ### ⚠️ **Warning!!** this project is not compatible with safari browser. ⚠️
4 |
5 | a very simple web version, to download the video in the best quality.
6 |
7 | ### how to use the app locally?
8 | - `git clone https://github.com/zalazarc20/tiktokDL.git`
9 | - `npm install`
10 | - once the modules are installed, start the server with `npm run dev` (you need nodemon).
11 | - `npm install nodemon -g`
12 |
13 | ### This is my first application, but very soon I will bring new projects 😉👌
14 |
--------------------------------------------------------------------------------
/public/js/getUrl.js:
--------------------------------------------------------------------------------
1 | export const getUrl = async (url) => {
2 | let content = document.getElementById('content');
3 | let res = await fetch('/url', {
4 | method: 'POST',
5 | headers: {
6 | 'Accept': 'application/json',
7 | 'Content-Type': 'application/json'
8 | },
9 | body: JSON.stringify({ videoUrl: url})
10 | })
11 |
12 | let {nowm, wm, music} = await res.json();
13 |
14 | // agregamos la etiqueta video...
15 | let buttons = `
16 | download audio
17 | `;
18 | let video = `
19 |
22 | `;
23 | content.innerHTML = `${buttons} ${video}`;
24 | }
--------------------------------------------------------------------------------
/public/js/app.js:
--------------------------------------------------------------------------------
1 | import { disabledButton } from "./disabledButton.js";
2 | import { getUrl } from "./getUrl.js";
3 |
4 | let app = document.getElementById('app');
5 | let form = document.getElementById('form');
6 | let content = document.getElementById('content');
7 |
8 | disabledButton(); // disable button at the beginning and with empty input
9 |
10 | form.addEventListener('submit', e => {
11 | e.preventDefault();
12 |
13 | content.innerHTML = '
';
14 |
15 | let url = e.target.url.value; // get value of input
16 | let domain = url.split('/')[2]; // get domain
17 |
18 | if(domain === 'www.tiktok.com' || domain === 'vm.tiktok.com'){
19 | getUrl(url); // get data video
20 | }else{
21 | content.innerHTML = '
Error, The url is not a tiktok link!
'
22 | }
23 | e.target.reset();
24 | })
25 |
26 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | import express from 'express';
2 | import bodyParser from 'body-parser';
3 | import { tiktokDL } from './src/tiktokDL.js';
4 | import { fileURLToPath } from 'url';
5 | import { dirname } from 'path';
6 |
7 | const __filename = fileURLToPath(import.meta.url);
8 | const __dirname = dirname(__filename);
9 |
10 | const app = express();
11 | const port = process.env.PORT || 3000;
12 |
13 | app.use(express.static(__dirname + '/public'));
14 | app.use(bodyParser.json());
15 |
16 | app.post('/url', async (req, res) => {
17 | let { videoUrl } = req.body;
18 |
19 | // get url video
20 | let {nowm, wm, music} = await tiktokDL(videoUrl);
21 | res.send(JSON.stringify({nowm, wm, music}))
22 | })
23 |
24 | app.listen(port, () => {
25 | console.log(`servidor activado - http://localhost:${port}`)
26 | console.log(`${process.env.RAILWAY_STATIC_URL}`)
27 | console.log(`server actived - port: ${port}`);
28 | })
--------------------------------------------------------------------------------
/src/tiktokDL.js:
--------------------------------------------------------------------------------
1 | import axios from "axios";
2 |
3 | export const tiktokDL = async url => {
4 | let domain = 'https://www.tikwm.com/';
5 | let res = await axios.post(domain+'api/', {}, {
6 | headers: {
7 | 'accept': 'application/json, text/javascript, */*; q=0.01',
8 | 'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
9 | // 'cookie': 'current_language=en; _ga=GA1.1.115940210.1660795490; _gcl_au=1.1.669324151.1660795490; _ga_5370HT04Z3=GS1.1.1660795489.1.1.1660795513.0.0.0',
10 | 'sec-ch-ua': '"Chromium";v="104", " Not A;Brand";v="99", "Google Chrome";v="104"',
11 | 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36'
12 | },
13 | params: {
14 | url: url,
15 | count: 12,
16 | cursor: 0,
17 | web: 1,
18 | hd: 1
19 | }
20 | })
21 |
22 | return {
23 | nowm: domain+res.data.data.play,
24 | wm: domain+res.data.data.wmplay,
25 | music: domain+res.data.data.music,
26 | }
27 | }
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | TIKTOK DL - download tiktok videos without watermark
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
Insert a valid link of tiktok
20 |
25 |
26 |
27 | - Copy link of some tiktok video
28 | - Paste link in text box
29 | - Click the GENERATE button
30 | - Watch and Download the video without watermark
31 |
32 |
33 |
34 |
35 |
36 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/public/img/spinning-circles.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/public/css/style.css:
--------------------------------------------------------------------------------
1 | @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@200;300;400;500;700&display=swap');
2 |
3 | :root{
4 | --color-text: #525252;
5 | --color-primary: #7241FF;
6 | --color-primary-light: #7241FF70;
7 | --color-danger: #ff4141;
8 | --color-bg: #F5F1FF;
9 | --white: #ffffff;
10 | }
11 |
12 | *{
13 | box-sizing: border-box;
14 | }
15 |
16 | body{
17 | margin: 0;
18 | background-color: var(--color-bg);
19 | font-family: 'Poppins', sans-serif;
20 | }
21 |
22 | .container{
23 | max-width: 80%;
24 | min-height: 90vh;
25 | width: 100%;
26 | margin: 0 auto;
27 | display: grid;
28 | place-content: center;
29 | }
30 |
31 | .card{
32 | margin-top: 2rem;
33 | background-color: var(--white);
34 | padding: 1rem;
35 | border-radius: 10px;
36 | }
37 |
38 | .card h2{
39 | color: var(--color-text);
40 | font-weight: 500;
41 | }
42 | .card h2 b{
43 | color: var(--color-primary);
44 | }
45 |
46 | form{
47 | display: flex;
48 | justify-content: space-between;
49 | }
50 |
51 | form input{
52 | margin-right: 5px;
53 | }
54 |
55 | form input:nth-child(1){
56 | width: 80%;
57 | padding: .7rem;
58 | border-radius: 10px;
59 | border: 2px solid var(--color-primary-light);
60 | background-color: var(--color-bg);
61 | color: var(--color-text);
62 | outline: none;
63 | font-weight: 500;
64 | transition: .3s ease-in-out;
65 | }
66 |
67 | form input:nth-child(1):focus, form input:nth-child(1):hover{
68 | border: 2px solid var(--color-primary);
69 | }
70 |
71 | .btn-submit{
72 | background-color: var(--color-primary);
73 | border: none;
74 | border-radius: 10px;
75 | font-weight: 500;
76 | color: var(--white);
77 | cursor: pointer;
78 | }
79 |
80 | .btn{
81 | margin-bottom: 1rem;
82 | padding: 0.4rem;
83 | background-color: var(--color-primary);
84 | color: var(--white);
85 | border-radius: 10px;
86 | text-decoration: none;
87 | text-align: center;
88 | }
89 |
90 | .btn-submit:disabled{
91 | background-color: var(--color-primary-light);
92 | }
93 |
94 | .content{
95 | min-width: 300px;
96 | border-radius: 10px;
97 | margin-top: 1rem;
98 | min-height: 300px;
99 | background-color: var(--color-bg);
100 | display: grid;
101 | place-content: center;
102 | padding: 1rem;
103 | }
104 |
105 | .content video{
106 | justify-self: center;
107 | width: 300px;
108 | border-radius: 10px;
109 | }
110 |
111 | @media screen and (min-width: 720px) {
112 | .content{
113 | width: 400px;
114 | }
115 | .content ol{
116 | font-size: 12px;
117 | }
118 |
119 | .content video{
120 | width: 200px;
121 | }
122 | }
123 |
124 | footer{
125 | margin-top: 1rem;
126 | width: 100%;
127 | display: flex;
128 | justify-content: center;
129 | align-items: center;
130 | }
131 |
132 | footer h3{
133 | color: var(--color-text);
134 | font-weight: 300;
135 | font-size: 14px;
136 | margin: 0;
137 | }
138 | footer b{
139 | font-weight: 500;
140 | color: var(--color-primary);
141 | }
142 |
143 | footer p{
144 | margin: 0;
145 | font-size: 12px;
146 | text-align: center;
147 | color: var(--color-text);
148 | }
149 |
150 | .btn-instagram{
151 | text-decoration: none;
152 | }
153 |
154 | .messageError{
155 | color: var(--color-danger);
156 | }
--------------------------------------------------------------------------------