├── LICENSE
├── README.md
├── dark.css
├── dark.html
├── google3d913672b444e790.html
├── index.html
├── javascript.js
├── logo.png
├── manifest.webmanifest
├── style.css
├── sw.js
└── updates.md
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 Vijay Kumar
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6 |
7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8 |
9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
10 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
VKrDownloader
2 |
3 | Video Downloader by Vijay Kumar
4 | @TheOfficialVKr
5 |
6 | Telegram : join telegram @vkrdownloader
7 |
8 | Demo
9 | Light theme https://theofficialvkr.github.io/VKrDownloader/
10 |
11 | Dark Theme https://theofficialvkr.github.io/VKrDownloader/dark.html
12 |
13 |
14 |
15 |
Download videos from:
16 |
17 | YouTube
18 | Facebook
19 | Twitter
20 | Instagram (Reels)
21 | TikTok
22 | 1000+ other websites in all audio/video quality options
23 |
24 |
25 |
26 |
27 | Support Me
28 |
29 | ### Notice: Support Needed to Keep VKrDownloader Alive
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 | API Documentation
45 |
46 | With the VKrDownloader API, you can programmatically download videos from supported sites.
47 |
48 | API Endpoint
49 | GET https://vkrdownloader.xyz/server/?api_key=API-KEY&vkr=VIDEO_URL
50 |
51 | Request Parameters
52 |
53 | vkr (string) - Required . The URL of the video you want to download.
54 | api_key (string) - Required . The API KEY which is vkrdownloader . use this key to fetch video data.
55 |
56 |
57 | Authentication
58 | You must pass an API key to authenticate your requests. The API key can be passed in two ways:
59 |
60 |
61 | Query string : Append api_key=YOUR_API_KEY
to the URL.
62 | HTTP Header : Include the API key using the x-api-key
header in your request.
63 |
64 |
65 | Example Request (Query String)
66 | curl "https://vkrdownloader.xyz/server/?api_key=vkrdownloader&vkr=https://youtu.be/3VxnPQWvg5w"
67 |
68 |
69 | Example Request (Header)
70 | curl -X POST https://vkrdownloader.xyz/server/ \
71 | -H "x-api-key: YOUR_API_KEY" \
72 | -d "vkr=https://youtu.be/3VxnPQWvg5w"
73 |
74 |
75 | Example Response
76 | {
77 | "title": "Sample Video",
78 | "source": "https://video-download-link.com",
79 | "thumbnail": "https://img.youtube.com/sample_thumbnail.jpg",
80 | "formats": [
81 | {
82 | "url": "https://video-download-link.com",
83 | "format_id": "360p",
84 | "ext": "mp4",
85 | "size": "10 MB"
86 | },
87 | {
88 | "url": "https://video-download-link.com/1080p.mp4",
89 | "format_id": "1080p",
90 | "ext": "mp4",
91 | "size": "25 MB"
92 | }
93 | ]
94 | }
95 |
96 |
97 | Error Handling
98 |
99 | 401 Unauthorized - Returned if the API key is missing or invalid.
100 | 400 Bad Request - If the video URL is invalid or missing.
101 | 500 Internal Server Error - If an unexpected error occurs while processing the request.
102 |
103 |
104 | API Key
105 | To access the VKrDownloader API, you need an API key. You can pass it in the query string or the request header as x-api-key
.
106 |
107 | Example (Query String)
108 | https://vkrdownloader.xyz/server/?api_key=vkrdownloader&vkr=https://youtu.be/3VxnPQWvg5w
109 |
110 | Example (Header)
111 | curl -X POST https://vkrdownloader.xyx/server/ \
112 | -H "x-api-key: YOUR_API_KEY" \
113 | -d "vkr=https://youtu.be/3VxnPQWvg5w"
114 |
115 |
116 | For more information about obtaining an API key, please
117 | contact us .
118 |
119 |
120 |
121 | How To Install
122 |
123 | Upload zip files to your server or hosting platform.
124 | Unzip the file in your file manager.
125 | This project works on almost all free/paid hosting, so don't worry about specific requirements.
126 | That's it! Open your site, and VKrDownloader will start working immediately.
127 |
128 |
129 |
130 |
131 | Demo
132 | https://theofficialvkr.github.io/VKRdownloader/
133 |
134 |
135 |
136 | Updates
137 | Check all updates here:
138 | Updates Page
139 |
140 |
141 |
142 | Need Help?
143 | Contact me for any kind of help:
144 |
152 |
153 |
154 |
155 |
156 |
157 | At Last, Remember
158 | I am not the Developer 👍
159 |
160 |
--------------------------------------------------------------------------------
/dark.css:
--------------------------------------------------------------------------------
1 | #loading {
2 | text-align: center;
3 | display: none;
4 | margin-top: 20px;
5 | }
6 |
7 | #loading p {
8 | font-weight: bold;
9 | font-size: 38px;
10 | color: #333;
11 | }
12 |
13 | #container {
14 | display: none;
15 | text-align: center;
16 | margin: 20px;
17 | box-shadow: 0 0 20px rgba(0, 0, 0, 0.1);
18 | padding: 20px;
19 | background-color: #0c1013;
20 | border-radius: 10px;
21 | }
22 |
23 | #inputUrl {
24 | outline: none !important;
25 | }
26 |
27 | #thumb img {
28 | width: 100%;
29 | height: 300px;
30 | }
31 |
32 | .dlbtns {
33 | display: inline-block;
34 | padding: 10px 20px;
35 | margin: 5px;
36 | text-align: center;
37 | border-radius: 5px;
38 | font-size: 14px;
39 | font-weight: bold;
40 | color: white;
41 | cursor: pointer;
42 | width: auto;
43 | /* Fixed width */
44 | transition: background-color 0.3s;
45 | }
46 |
47 | .centerV {
48 | height: auto;
49 | display: flex;
50 | justify-content: center;
51 | align-items: center;
52 | background: transparent;
53 | }
54 |
55 | .wave {
56 | width: 5px;
57 | height: 100px;
58 | background: linear-gradient(45deg, red, #fff);
59 | margin: 10px;
60 | animation: wave 1s linear infinite;
61 | border-radius: 20px;
62 | }
63 |
64 | .wave:nth-child(2) {
65 | animation-delay: 0.1s;
66 | }
67 |
68 | .wave:nth-child(3) {
69 | animation-delay: 0.2s;
70 | }
71 |
72 | .wave:nth-child(4) {
73 | animation-delay: 0.3s;
74 | }
75 |
76 | .wave:nth-child(5) {
77 | animation-delay: 0.4s;
78 | }
79 |
80 | .wave:nth-child(6) {
81 | animation-delay: 0.5s;
82 | }
83 |
84 | .wave:nth-child(7) {
85 | animation-delay: 0.6s;
86 | }
87 |
88 | .wave:nth-child(8) {
89 | animation-delay: 0.7s;
90 | }
91 |
92 | .wave:nth-child(9) {
93 | animation-delay: 0.8s;
94 | }
95 |
96 | .wave:nth-child(10) {
97 | animation-delay: 0.9s;
98 | }
99 |
100 | @keyframes wave {
101 | 0% {
102 | transform: scale(0);
103 | }
104 |
105 | 50% {
106 | transform: scale(1);
107 | }
108 |
109 | 100% {
110 | transform: scale(0);
111 | }
112 | }
113 |
114 |
115 |
116 |
117 |
118 | .mt-5,
119 | .my-5 {
120 | margin-top: 0.5rem !important;
121 | }
122 |
123 |
124 |
125 | .custom-shape-divider-bottom-1610026357 {
126 | position: absolute;
127 | bottom: 0;
128 | left: 0;
129 | width: 100%;
130 | overflow: hidden;
131 | line-height: 0;
132 | transform: rotate(0deg);
133 | }
134 |
135 | .custom-shape-divider-bottom-1610026357 svg {
136 | position: relative;
137 | display: block;
138 | width: calc(100% + 15.3px);
139 | height: 0px;
140 | }
141 |
142 | .custom-shape-divider-bottom-1610026357 .shape-fill {
143 | fill: #ffff00;
144 | }
145 |
146 | .herosec {
147 | min-height: calc(100vh - 0px);
148 | display: flex;
149 | justify-content: center;
150 | align-items: center;
151 | flex-flow: column;
152 | }
153 |
154 | .download-video iframe {
155 | border-radius: 10px;
156 | position: relative;
157 | }
158 |
159 | .download-video {
160 | position: relative;
161 | }
162 |
163 | .download-video iframe::after {
164 | content: "";
165 | height: 100%;
166 | width: 100%;
167 | position: absolute;
168 | top: 0;
169 | left: 0;
170 | background: red;
171 | z-index: 5;
172 | }
173 |
174 |
175 | .myselect {
176 | display: flex;
177 | width: 100%;
178 | justify-content: end;
179 | }
180 |
181 | .searchsec {
182 | background: white;
183 | }
184 |
185 | @media(max-width:500px) {
186 | .searchsec {
187 | flex-wrap: wrap;
188 | display: flex;
189 | }
190 |
191 |
192 | .searchsec {
193 | border: none;
194 | background: transparent;
195 | }
196 |
197 | .searchsec input {
198 | border: 1px solid black;
199 | border-radius: 10px;
200 | margin-bottom: 10px;
201 | }
202 |
203 | .myselect {
204 | display: flex;
205 | width: 100%;
206 | justify-content: center;
207 | }
208 |
209 | }
210 |
--------------------------------------------------------------------------------
/dark.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | VKrDownloader : Online Video Downloader Tool
9 |
10 |
11 |
12 |
13 |
14 |
15 |
18 |
19 |
23 |
24 |
25 |
26 |
27 |
28 |
VKrDL
29 |
30 |
31 | Get started
32 |
33 |
34 |
35 | Open main menu
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 | All Format YouTube HD
68 | Video
69 | Downloader.
70 |
71 |
72 | Our YouTube Downloader tool offers fast and easy video downloads in multiple formats. Built with Express, VKrDownloader and Tailwind CSS for a seamless experience.
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 | Download
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 | About VKrDownloader
137 |
138 |
139 | Welcome to VKrDownloader! Our mission is to provide a fast, user-friendly tool for downloading online videos from platforms like YouTube, Instagram, and more. Developed by Vijay Kumar, VKrDownloader is designed to offer a seamless experience that respects user privacy and prioritizes efficiency.
140 |
141 |
142 | Our Vision
143 |
144 | To make video content more accessible by offering a reliable downloader that meets the highest standards for speed and ease of use.
145 |
146 |
147 | Why Choose Us?
148 |
149 |
150 | Ease of Use: Our interface is simple, allowing users to download videos without complex steps. Privacy Focus: We value your privacy and only collect minimal information necessary for site performance. Constant Improvement: We regularly update VKrDownloader with the latest features and improvements to maintain a smooth experience.
151 |
152 |
153 | Contact Information
154 |
155 | For any inquiries, suggestions, or feedback, please reach out to us at telegram as @vkrdownloader
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 | Made with ♥️ by
164 | Vijay Kumar
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
--------------------------------------------------------------------------------
/google3d913672b444e790.html:
--------------------------------------------------------------------------------
1 | google-site-verification: google3d913672b444e790.html
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 | VkrDownloader: Download Videos / Audio Online From Any Site
29 |
30 |
34 |
35 |
39 |
40 |
41 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
Download
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
VKRDownloader - Download Videos Seamlessly
148 |
149 | VKRDownloader by Vijay Kumar is your ultimate tool for downloading online videos, thumbnails, and music. It's fast, free, and hassle-free!
150 |
151 |
152 |
Download from Your Favorite Platforms:
153 |
154 | 🎥 YouTube
155 | 📘 Facebook
156 | 🐦 Twitter
157 | 📸 Instagram (Reels)
158 | 🎵 TikTok
159 | 🌐 1000+ other websites
160 |
161 |
162 | Supports all audio and video qualities for the best experience.
163 |
164 |
165 |
166 |
167 |
168 | Powered By Vijay Kumar
169 |
170 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
--------------------------------------------------------------------------------
/javascript.js:
--------------------------------------------------------------------------------
1 | /*******************************
2 | * Configuration for Colors
3 | *******************************/
4 | const formatColors = {
5 | greenFormats: ["17", "18", "22"],
6 | blueFormats: ["139", "140", "141", "249", "250", "251", "599", "600"],
7 | defaultColor: "#9e0cf2"
8 | };
9 |
10 | /*******************************
11 | * Utility Functions
12 | *******************************/
13 |
14 | /**
15 | * Get the background color based on the format itag.
16 | * @param {string} downloadUrlItag - The itag parameter from the download URL.
17 | * @returns {string} - The corresponding background color.
18 | */
19 | function getBackgroundColor(downloadUrlItag) {
20 | if (formatColors.greenFormats.includes(downloadUrlItag)) {
21 | return "green";
22 | } else if (formatColors.blueFormats.includes(downloadUrlItag)) {
23 | return "#3800ff";
24 | } else {
25 | return formatColors.defaultColor;
26 | }
27 | }
28 |
29 | /**
30 | * Debounce function to limit the rate at which a function can fire.
31 | * @param {Function} func - The function to debounce.
32 | * @param {number} wait - The delay in milliseconds.
33 | * @returns {Function} - The debounced function.
34 | */
35 | function debounce(func, wait) {
36 | let timeout;
37 | return function(...args) {
38 | clearTimeout(timeout);
39 | timeout = setTimeout(() => func.apply(this, args), wait);
40 | };
41 | }
42 |
43 | /**
44 | * Extract YouTube video ID from a given URL.
45 | * @param {string} url - The YouTube URL.
46 | * @returns {string|null} - The video ID or null if not found.
47 | */
48 | // Function to get YouTube video IDs from a URL, including Shorts URLs
49 | function getYouTubeVideoIds(url) {
50 | // Validate the input
51 | if (!url || typeof url !== 'string') {
52 | console.error('Invalid URL provided to getYouTubeVideoId:', url);
53 | return null;
54 | }
55 |
56 | try {
57 | // Create a URL object to parse the URL
58 | const urlObj = new URL(url);
59 |
60 | // Check if the hostname belongs to YouTube or YouTube short links
61 | const validHosts = ['www.youtube.com', 'youtube.com', 'youtu.be'];
62 | if (!validHosts.includes(urlObj.hostname)) {
63 | console.warn('URL does not belong to YouTube:', url);
64 | return null;
65 | }
66 |
67 | // For youtu.be (short link), the video ID is in the pathname
68 | if (urlObj.hostname === 'youtu.be') {
69 | const videoId = urlObj.pathname.slice(1); // Remove the leading '/'
70 | return videoId.length === 11 ? videoId : null;
71 | }
72 |
73 | // For youtube.com URLs, look for 'v' or 'shorts' in query or pathname
74 | if (urlObj.hostname.includes('youtube.com')) {
75 | if (urlObj.pathname.startsWith('/shorts/')) {
76 | // Shorts video ID is in the pathname after "/shorts/"
77 | return urlObj.pathname.split('/')[2];
78 | }
79 |
80 | // Regular video URLs have 'v' as a query parameter
81 | const videoId = urlObj.searchParams.get('v');
82 | return videoId && videoId.length === 11 ? videoId : null;
83 | }
84 |
85 | console.warn('Unrecognized YouTube URL format:', url);
86 | return null;
87 | } catch (error) {
88 | console.error('Error parsing URL in getYouTubeVideoId:', error);
89 | return null;
90 | }
91 | }
92 |
93 |
94 |
95 | /**
96 | * Sanitize HTML content using DOMPurify.
97 | * @param {string} content - The HTML content to sanitize.
98 | * @returns {string} - The sanitized HTML.
99 | */
100 | function sanitizeContent(content) {
101 | return DOMPurify.sanitize(content);
102 | }
103 |
104 | /**
105 | * Update the inner HTML of a specified element with sanitized content.
106 | * @param {string} elementId - The ID of the HTML element.
107 | * @param {string} content - The content to inject.
108 | */
109 | function updateElement(elementId, content) {
110 | const element = document.getElementById(elementId);
111 | if (element) {
112 | element.innerHTML = content;
113 | } else {
114 | console.warn(`Element with ID "${elementId}" not found.`);
115 | }
116 | }
117 |
118 | /**
119 | * Retrieve a query parameter value by name from a URL.
120 | * @param {string} name - The name of the parameter.
121 | * @param {string} url - The URL to extract the parameter from.
122 | * @returns {string} - The parameter value or an empty string if not found.
123 | */
124 | function getParameterByName(name, url) {
125 | // Properly escape regex special characters
126 | name = name.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
127 | const regex = new RegExp(`[?&]${name}(=([^]*)|&|#|$)`);
128 | const results = regex.exec(url);
129 |
130 | if (!results) return '';
131 | if (!results[2]) return '';
132 |
133 | return decodeURIComponent(results[2].replace(/\+/g, ' '));
134 | }
135 |
136 | /*******************************
137 | * AJAX Request with Retry Logic
138 | *******************************/
139 |
140 | /**
141 | * Make an AJAX GET request with retry capability.
142 | * @param {string} inputUrl - The input URL for the request.
143 | * @param {number} retries - Number of retry attempts remaining.
144 | */
145 | function makeRequest(inputUrl, retries = 4) {
146 | const requestUrl = `https://vkrdownloader.xyz/server?api_key=vkrdownloader&vkr=${encodeURIComponent(inputUrl)}`;
147 | const retryDelay = 2000; // Initial retry delay in milliseconds
148 | const maxRetries = retries;
149 |
150 | $.ajax({
151 | url: requestUrl,
152 | type: "GET",
153 | cache: true,
154 | async: true,
155 | crossDomain: true,
156 | dataType: 'json',
157 | timeout: 15000, // Extended timeout for slower networks
158 | success: function (data) {
159 | handleSuccessResponse(data, inputUrl);
160 | },
161 | error: function (xhr, status, error) {
162 | if (retries > 0) {
163 | let delay = retryDelay * Math.pow(2, maxRetries - retries); // Exponential backoff
164 | console.log(`Retrying in ${delay / 1000} seconds... (${retries} attempts left)`);
165 | setTimeout(() => makeRequest(inputUrl, retries - 1), delay);
166 | } else {
167 | const errorMessage = getErrorMessage(xhr, status, error);
168 | console.error(`Error Details: ${errorMessage}`);
169 | displayError("Unable to fetch the download link after several attempts. Please check the URL or try again later.");
170 | document.getElementById("loading").style.display = "none";
171 | }
172 | },
173 | complete: function () {
174 | document.getElementById("downloadBtn").disabled = false; // Re-enable the button
175 | }
176 | });
177 | }
178 |
179 | function getErrorMessage(xhr, status, error) {
180 | const statusCode = xhr.status;
181 | let message = `Status: ${status}, Error: ${error}`;
182 |
183 | if (xhr.responseText) {
184 | try {
185 | const response = JSON.parse(xhr.responseText);
186 | if (response && response.error) {
187 | message += `, Server Error: ${response.error}`;
188 | }
189 | } catch (e) {
190 | message += `, Unable to parse server response.`;
191 | }
192 | }
193 |
194 | switch (statusCode) {
195 | case 0: return "Network Error: The server is unreachable.";
196 | case 400: return "Bad Request: The input URL might be incorrect.";
197 | case 401: return "Unauthorized: Please check the API key.";
198 | case 429: return "Too Many Requests: You are being rate-limited.";
199 | case 503: return "Service Unavailable: The server is temporarily overloaded.";
200 | default: return `${message}, HTTP ${statusCode}: ${xhr.statusText || error}`;
201 | }
202 | }
203 |
204 |
205 | function displayError(message) {
206 | // Assuming there's a placeholder element for error messages
207 | const errorElement = document.getElementById("errorMessage");
208 | if (errorElement) {
209 | errorElement.innerText = message;
210 | errorElement.style.display = "block";
211 | }
212 | }
213 |
214 | /**
215 | * Generate a detailed error message based on the XHR response.
216 | * @param {Object} xhr - The XMLHttpRequest object.
217 | * @param {string} status - The status string.
218 | * @param {string} error - The error message.
219 | * @returns {string} - The formatted error message.
220 | */
221 |
222 | /*******************************
223 | * Event Handlers
224 | *******************************/
225 |
226 | /**
227 | * Handle the "Download" button click event.
228 | */
229 | document.getElementById("downloadBtn").addEventListener("click", debounce(function () {
230 | document.getElementById("loading").style.display = "initial";
231 | document.getElementById("downloadBtn").disabled = true; // Disable the button
232 |
233 | const inputUrl = document.getElementById("inputUrl").value.trim();
234 | if (!inputUrl) {
235 | displayError("Please enter a valid YouTube URL.");
236 | document.getElementById("loading").style.display = "none";
237 | document.getElementById("downloadBtn").disabled = false;
238 | return;
239 | }
240 |
241 | makeRequest(inputUrl); // Make the AJAX request with retry logic
242 | }, 300)); // Adjust the delay as needed
243 |
244 | /**
245 | * Display an error message within the page instead of using alert.
246 | * @param {string} message - The error message to display.
247 | */
248 | function displayError(message) {
249 | const errorContainer = document.getElementById("error");
250 | if (errorContainer) {
251 | errorContainer.innerHTML = sanitizeContent(message);
252 | errorContainer.style.display = "block";
253 | } else {
254 | // Fallback to alert if error container is not available
255 | alert(message);
256 | }
257 | }
258 |
259 | /*******************************
260 | * Response Handlers
261 | *******************************/
262 |
263 | /**
264 | * Handle successful AJAX responses.
265 | * @param {Object} data - The response data from the server.
266 | * @param {string} inputUrl - The original input URL.
267 | */
268 | function handleSuccessResponse(data, inputUrl) {
269 | document.getElementById("container").style.display = "block";
270 | document.getElementById("loading").style.display = "none";
271 |
272 | if (data.data) {
273 | const videoData = data.data;
274 |
275 | // Extract necessary data
276 | //const thumbnailUrl = videoData.thumbnail;
277 | const downloadUrls = videoData.downloads.map(download => download.url);
278 | const videoSource = videoData.source;
279 | const videoId = getYouTubeVideoIds(videoSource);
280 | const thumbnailUrl = videoId
281 | ? `https://i.ytimg.com/vi/${videoId}/hqdefault.jpg`
282 | : videoData.thumbnail;
283 | // Construct video HTML
284 | const videoHtml = `
285 |
287 |
288 | ${Array.isArray(downloadUrls) ? downloadUrls.map(url => ``).join('') : ''}
289 |
290 | `;
291 | const YTvideoHtml = `
292 |
294 |
295 |
296 | ${downloadUrls.map(url => ``).join('')}
297 | `;
298 | const titleHtml = videoData.title ? `${sanitizeContent(videoData.title)} ` : "";
299 | const descriptionHtml = videoData.description ? `View Description ${sanitizeContent(videoData.description)} ` : "";
300 | const durationHtml = videoData.size ? `${sanitizeContent(videoData.size)} ` : "";
301 |
302 | // Update DOM elements
303 | if (videoId) {
304 | updateElement("thumb", YTvideoHtml);
305 | } else {
306 | updateElement("thumb", videoHtml);
307 | }
308 | updateElement("title", titleHtml);
309 | updateElement("description", descriptionHtml);
310 | updateElement("duration", durationHtml);
311 |
312 | // Generate download buttons
313 | generateDownloadButtons(data, inputUrl);
314 | } else {
315 | displayError("Issue: Unable to retrieve the download link. Please check the URL and contact us on Social Media @TheOfficialVKr.");
316 | document.getElementById("loading").style.display = "none";
317 | }
318 | }
319 |
320 | /**
321 | * Generate download buttons with dynamic colors and labels.
322 | * @param {Object} videoData - The video data from the server.
323 | * @param {string} inputUrl - The original input URL.
324 | */
325 | function generateDownloadButtons(videoData, inputUrl) {
326 | const downloadContainer = document.getElementById("download");
327 | downloadContainer.innerHTML = "";
328 |
329 | if (videoData.data) {
330 | const downloads = videoData.data.downloads;
331 | const videoSource = videoData.data.source;
332 |
333 | // Add YouTube specific button if applicable
334 | const videoId = getYouTubeVideoIds(videoSource);
335 | if (videoId) {
336 | // downloadContainer.innerHTML += `
337 | //
338 | // Download Video (YouTube)
339 | // `;
340 | const qualities = ["mp3", "360", "720", "1080"];
341 | qualities.forEach(quality => {
342 | downloadContainer.innerHTML += `
343 | `;
346 | });
347 | }
348 | // Generate download buttons for available formats
349 | downloads.forEach(download => {
350 | if (download && download.url) {
351 | const downloadUrl = download.url;
352 | const itag = getParameterByName("itag", downloadUrl);
353 | const bgColor = getBackgroundColor(itag);
354 | const videoExt = download.format_id;
355 | const videoSize = download.size;
356 |
357 | downloadContainer.innerHTML += `
358 |
359 |
360 | ${sanitizeContent(videoExt)} - ${sanitizeContent(videoSize)}
361 |
362 | `;
363 | }
364 | });
365 |
366 | } else {
367 | displayError("No download links found or data structure is incorrect.");
368 | document.getElementById("loading").style.display = "none";
369 | }
370 |
371 | // If no download buttons or iframes were added, notify the user
372 | if (downloadContainer.innerHTML.trim() === "") {
373 | displayError("Server Down due to Too Many Requests. Please contact us on Social Media @TheOfficialVKr.");
374 | document.getElementById("container").style.display = "none";
375 | // Redirecting the user to an alternative download page
376 | // window.location.href = `https://vkrdownloader.xyz/download.php?vkr=${encodeURIComponent(inputUrl)}`;
377 | }
378 | }
379 |
--------------------------------------------------------------------------------
/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theofficialvkr/VKrDownloader/282d04b4a6bc7761d14bec36a2fabe01bdc56eb6/logo.png
--------------------------------------------------------------------------------
/manifest.webmanifest:
--------------------------------------------------------------------------------
1 | {
2 | "name": "VKrDownloader",
3 | "short_name": "VKrDownloader",
4 | "description": "All in one Video Downloader - Download videos from Facebook, Twitter, YouTube, TikTok, and 1000+ other sites. Made by Vijay Kumar.",
5 | "start_url": "/",
6 | "display": "standalone",
7 | "background_color": "#ffffff",
8 | "theme_color": "#007bff",
9 | "icons": [
10 | {
11 | "src": "https://raw.githubusercontent.com/theofficialvkr/VKrDownloader/refs/heads/main/logo.png",
12 | "sizes": "192x192",
13 | "type": "image/png"
14 | },
15 | {
16 | "src": "https://raw.githubusercontent.com/theofficialvkr/VKrDownloader/refs/heads/main/logo.png",
17 | "sizes": "512x512",
18 | "type": "image/png"
19 | }
20 | ],
21 | "screenshots": [
22 | {
23 | "src": "https://raw.githubusercontent.com/theofficialvkr/VKrDownloader/refs/heads/main/logo.png",
24 | "sizes": "192x192",
25 | "type": "image/png"
26 | },
27 | {
28 | "src": "https://raw.githubusercontent.com/theofficialvkr/VKrDownloader/refs/heads/main/logo.png",
29 | "sizes": "512x512",
30 | "type": "image/png"
31 | }
32 | ]
33 | }
34 |
--------------------------------------------------------------------------------
/style.css:
--------------------------------------------------------------------------------
1 | body {
2 | font-family: 'Arial', sans-serif;
3 | margin: 0;
4 | padding: 0;
5 | background-color: #f5f5f5;
6 | text-wrap: break-word;
7 | overflow-wrap: break-word;
8 | }
9 |
10 | header {
11 | background-color: #333;
12 | color: #fff;
13 | padding: 15px;
14 | text-align: center;
15 | }
16 |
17 | nav ul {
18 | list-style: none;
19 | margin: 0;
20 | padding: 0;
21 | display:flex;
22 | width:100%;
23 | flex-direction: row-reverse !important;
24 | }
25 |
26 | nav li {
27 | display: inline;
28 | margin-right: 20px;
29 | }
30 |
31 | nav a {
32 | text-decoration: none;
33 | color: #fff;
34 | font-weight: bold;
35 | font-size: 16px;
36 | }
37 |
38 | #form {
39 | text-align: center;
40 | margin: 10px 0;
41 | }
42 |
43 | #inputUrl {
44 | padding: 10px;
45 | min-width:100%; /* Full width input */
46 | border: none;
47 | border-radius: 5px;
48 | box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
49 | }
50 |
51 | #downloadBtn {
52 | padding: 10px;
53 | cursor: pointer;
54 | background-color: #007bff;
55 | color: #fff;
56 | border: none;
57 | width:100%;
58 | border-radius: 5px;
59 | box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
60 | transition: background-color 0.3s;
61 | }
62 |
63 | #downloadBtn:hover {
64 | background-color: #0056b3;
65 | }
66 | #download{
67 | display:flex;
68 | justify-content: center;
69 | align-items: center;
70 | width:100%;
71 | flex-wrap:wrap;
72 | }
73 | #loading {
74 | text-align: center;
75 | display: none;
76 | margin-top: 20px;
77 | }
78 |
79 | #loading p {
80 | font-weight: bold;
81 | font-size: 38px;
82 | color: #333;
83 | }
84 |
85 | #container {
86 | display: none;
87 | text-align: center;
88 | margin: 20px;
89 | box-shadow: 0 0 20px rgba(0, 0, 0, 0.1);
90 | padding: 20px;
91 | background-color: #fff;
92 | border-radius: 10px;
93 | }
94 |
95 | #thumb img{
96 | width: 100%;
97 | height: 300px;
98 | }
99 | .dlbtns{
100 | display: inline-block;
101 | padding: 10px 20px;
102 | margin: 5px;
103 | text-align: center;
104 | border-radius: 5px;
105 | font-size: 14px;
106 | font-weight: bold;
107 | color: white;
108 | cursor: pointer;
109 | width:auto;
110 | min-width: 150px; /* Fixed width */
111 | transition: background-color 0.3s;
112 | }
113 | .centerV {
114 | height: auto;
115 | display: flex;
116 | justify-content: center;
117 | align-items: center;
118 | background: transparent;
119 | }
120 | #content{
121 | background: #000000a8;
122 | color: white;
123 | font-weight:bold;
124 | margin-bottom:80px;
125 | }
126 | .wave {
127 | width: 5px;
128 | height: 100px;
129 | background: linear-gradient(45deg, red, #fff);
130 | margin: 10px;
131 | animation: wave 1s linear infinite;
132 | border-radius: 20px;
133 | }
134 | .wave:nth-child(2) {
135 | animation-delay: 0.1s;
136 | }
137 | .wave:nth-child(3) {
138 | animation-delay: 0.2s;
139 | }
140 | .wave:nth-child(4) {
141 | animation-delay: 0.3s;
142 | }
143 | .wave:nth-child(5) {
144 | animation-delay: 0.4s;
145 | }
146 | .wave:nth-child(6) {
147 | animation-delay: 0.5s;
148 | }
149 | .wave:nth-child(7) {
150 | animation-delay: 0.6s;
151 | }
152 | .wave:nth-child(8) {
153 | animation-delay: 0.7s;
154 | }
155 | .wave:nth-child(9) {
156 | animation-delay: 0.8s;
157 | }
158 | .wave:nth-child(10) {
159 | animation-delay: 0.9s;
160 | }
161 |
162 | @keyframes wave {
163 | 0% {
164 | transform: scale(0);
165 | }
166 | 50% {
167 | transform: scale(1);
168 | }
169 | 100% {
170 | transform: scale(0);
171 | }
172 | }
173 |
174 |
175 |
176 | /* Add more styling as needed */
177 |
178 | /* Responsive styles for smaller screens */
179 | @media only screen and (max-width: 990px) {
180 | #inputUrl {
181 | width: 100%;
182 | }
183 |
184 | nav {
185 | display: block;
186 | text-align: center;
187 | }
188 | nav ul{
189 | flex-direction: column !important;
190 | }
191 | nav li {
192 | display: block;
193 | margin: 10px 0;
194 | }
195 | }
196 | footer{
197 | position: fixed;
198 | bottom: 0;
199 | width: 100vw;
200 | }
201 |
--------------------------------------------------------------------------------
/sw.js:
--------------------------------------------------------------------------------
1 | self.addEventListener('install', (event) => {
2 | event.waitUntil(
3 | caches.open('vkrdownloader-cache').then((cache) => {
4 | return cache.addAll([
5 | '/VKrDownloader',
6 | '/VKrDownloader/index.html',
7 | '/VKrDownloader/manifest.webmanifest',
8 | '/VKrDownloader/logo.png'
9 | ]);
10 | })
11 | );
12 | });
13 |
14 | self.addEventListener('fetch', (event) => {
15 | event.respondWith(
16 | caches.match(event.request).then((response) => {
17 | return response || fetch(event.request);
18 | })
19 | );
20 | });
21 |
22 | self.addEventListener('activate', (event) => {
23 | event.waitUntil(
24 | caches.keys().then((cacheNames) => {
25 | return Promise.all(
26 | cacheNames.map((cacheName) => {
27 | if (cacheName !== 'vkrdownloader-cache') {
28 | return caches.delete(cacheName);
29 | }
30 | })
31 | );
32 | })
33 | );
34 | });
35 |
--------------------------------------------------------------------------------
/updates.md:
--------------------------------------------------------------------------------
1 | # VKrDownloader Updates
2 | Fixed Instagram and tiktok downloading
3 | Fixed YouTube downloading
4 | Added MP3 converting Button
5 | Added More button to download videos in different format
6 | Fix API error by retires
7 | Fix Thumbnail error
8 | Add Video instead of thumbnail image
9 |
10 | List Of All Supported Sites
11 |
12 | Add API key to protect server
13 |
14 | ## Notice: Support Needed to Keep VKrDownloader Alive
15 |
16 | ### Dear VKrDownloader Users,
17 |
18 | I'm reaching out to let you know that VKrDownloader has hit the free-tier limit on Vercel, which means they've temporarily suspended my account and the server. Since VKrDownloader is a free tool, covering the costs for premium hosting has become challenging. I want to keep VKrDownloader available to everyone, but without support, it’s difficult to continue.
19 |
20 | I’m actively working to find a solution, and I’ll keep you updated. If you appreciate VKrDownloader and find it useful, please consider supporting the project. With your help, I can ensure VKrDownloader stays up and running for everyone to use.
21 |
22 | Thank you for your understanding and support!
23 |
24 | Best,
25 | Vijay Kumar
26 |
27 |
28 |
29 | Fixed URL detection logic
30 | Update API logic
31 | Move server to premium hosting
32 |
33 | Download VKrDownloader APP
34 |
35 | VKrDownloader is a powerful and user-friendly web app designed to make video downloading easier than ever. With VKrDownloader, you can directly share videos from apps like YouTube and instantly access all available download links, allowing you to save videos for offline viewing with just a few taps.
36 |
37 | Key Features:
38 |
39 | One-Tap Sharing: While watching a video on YouTube or other compatible platforms, simply tap the share button, select VKrDownloader from your share list, and instantly receive a list of download links.
40 |
41 | Copy & Paste URL Option: Alternatively, copy the video URL and paste it directly into VKrDownloader , which will retrieve all download options for you.
42 |
43 | Fast & Convenient: No need to switch between apps or copy links repeatedly; VKrDownloader streamlines the download process, saving you time and effort.
44 |
45 | Flexible Format & Quality Options: Get download links in various resolutions and formats to suit your storage and quality preferences.
46 |
47 |
48 | VKrDownloader is a hassle-free solution for anyone looking to download videos with ease, perfect for enjoying content offline anytime, anywhere.
49 |
50 |
51 |
52 | Click here to Download VKrDownloader App
53 |
54 |
55 |
56 | Updated whole Server
57 | Speed it up
58 | Fix converting Button
59 | Fix Video Player
60 |
61 |
--------------------------------------------------------------------------------