├── 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 | 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 | 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 | 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 | 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 |
    1. Upload zip files to your server or hosting platform.
    2. 124 |
    3. Unzip the file in your file manager.
    4. 125 |
    5. This project works on almost all free/paid hosting, so don't worry about specific requirements.
    6. 126 |
    7. That's it! Open your site, and VKrDownloader will start working immediately.
    8. 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 | 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 | 85 |
    86 |
    87 | 88 | 89 |
    90 | 91 | 92 | 114 | 115 | 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 | 100 |
    101 | 102 |
    103 |
    104 |
    105 |
    106 | 107 |
    108 | 109 |
    110 |
    111 | 112 | 134 | 135 | 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 | 161 |

    162 | Supports all audio and video qualities for the best experience. 163 |

    164 |
    165 |
    166 |
    167 | 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 | `; 291 | const YTvideoHtml = ` 292 | `; 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 | // 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 | 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 | 53 | 54 |
    55 | 56 |
  • Updated whole Server
  • 57 |
  • Speed it up
  • 58 |
  • Fix converting Button
  • 59 |
  • Fix Video Player
  • 60 | 61 | --------------------------------------------------------------------------------