| from flask import Flask, render_template_string, request, send_file, after_this_request |
| import yt_dlp |
| import os |
| import uuid |
|
|
| app = Flask(__name__) |
|
|
| HTML_CODE = """ |
| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>UniLoader β Made by Deepu</title> |
| <link rel="preconnect" href="https://fonts.googleapis.com"> |
| <link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@700;900&family=Sora:wght@300;400;500;600;700&display=swap" rel="stylesheet"> |
| <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css" rel="stylesheet"> |
| <style> |
| *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } |
| |
| :root { |
| --bg: #04060f; |
| --card: rgba(8, 12, 26, 0.92); |
| --text: #e2e8f0; |
| --muted:#4a5568; |
| } |
| |
| html, body { |
| min-height: 100vh; |
| background: var(--bg); |
| font-family: 'Sora', sans-serif; |
| color: var(--text); |
| overflow-x: hidden; |
| } |
| |
| /* ββ RGB Animations ββ */ |
| @keyframes rgb-glow { |
| 0% { color:#ff0080; text-shadow:0 0 14px #ff0080,0 0 30px #ff0080; } |
| 16% { color:#ff8c00; text-shadow:0 0 14px #ff8c00,0 0 30px #ff8c00; } |
| 33% { color:#ffe600; text-shadow:0 0 14px #ffe600,0 0 30px #ffe600; } |
| 50% { color:#00ff88; text-shadow:0 0 14px #00ff88,0 0 30px #00ff88; } |
| 66% { color:#00c8ff; text-shadow:0 0 14px #00c8ff,0 0 30px #00c8ff; } |
| 83% { color:#a855f7; text-shadow:0 0 14px #a855f7,0 0 30px #a855f7; } |
| 100% { color:#ff0080; text-shadow:0 0 14px #ff0080,0 0 30px #ff0080; } |
| } |
| @keyframes rgb-border { |
| 0% { border-color:#ff0080; box-shadow:0 0 14px #ff0080,inset 0 0 8px rgba(255,0,128,.07); } |
| 16% { border-color:#ff8c00; box-shadow:0 0 14px #ff8c00,inset 0 0 8px rgba(255,140,0,.07); } |
| 33% { border-color:#ffe600; box-shadow:0 0 14px #ffe600,inset 0 0 8px rgba(255,230,0,.07); } |
| 50% { border-color:#00ff88; box-shadow:0 0 14px #00ff88,inset 0 0 8px rgba(0,255,136,.07); } |
| 66% { border-color:#00c8ff; box-shadow:0 0 14px #00c8ff,inset 0 0 8px rgba(0,200,255,.07); } |
| 83% { border-color:#a855f7; box-shadow:0 0 14px #a855f7,inset 0 0 8px rgba(168,85,247,.07); } |
| 100% { border-color:#ff0080; box-shadow:0 0 14px #ff0080,inset 0 0 8px rgba(255,0,128,.07); } |
| } |
| @keyframes shimmer { |
| 0% { background-position:0% center; } |
| 100% { background-position:200% center; } |
| } |
| @keyframes line-move { |
| 0% { background-position:0% 50%; } |
| 50% { background-position:100% 50%; } |
| 100% { background-position:0% 50%; } |
| } |
| @keyframes drift { |
| 0% { transform:translate(0,0) scale(1); } |
| 50% { transform:translate(28px,-38px) scale(1.07); } |
| 100% { transform:translate(-18px,28px) scale(.95); } |
| } |
| @keyframes fadeDown { |
| from { opacity:0; transform:translateY(-20px); } |
| to { opacity:1; transform:translateY(0); } |
| } |
| @keyframes fadeUp { |
| from { opacity:0; transform:translateY(18px); } |
| to { opacity:1; transform:translateY(0); } |
| } |
| @keyframes spin { to { transform:rotate(360deg); } } |
| @keyframes pulse-badge { |
| 0%,100% { transform:scale(1); box-shadow:0 0 18px rgba(0,200,255,.35); } |
| 50% { transform:scale(1.03); box-shadow:0 0 36px rgba(168,85,247,.55); } |
| } |
| |
| /* ββ Background ββ */ |
| .bg-scene { position:fixed; inset:0; z-index:0; overflow:hidden; pointer-events:none; } |
| .orb { position:absolute; border-radius:50%; filter:blur(90px); opacity:.28; animation:drift 20s ease-in-out infinite alternate; } |
| .orb1 { width:520px;height:520px; background:radial-gradient(circle,#1a0050,transparent 70%); top:-200px;left:-150px; animation-duration:24s; } |
| .orb2 { width:360px;height:360px; background:radial-gradient(circle,#003060,transparent 70%); bottom:-120px;right:-100px; animation-duration:18s;animation-delay:-9s; } |
| .orb3 { width:260px;height:260px; background:radial-gradient(circle,#004030,transparent 70%); top:50%;left:50%; opacity:.15; animation-duration:28s;animation-delay:-14s; } |
| |
| .bg-grid { |
| position:fixed; inset:0; z-index:0; |
| background-image: |
| linear-gradient(rgba(0,200,255,.025) 1px, transparent 1px), |
| linear-gradient(90deg, rgba(0,200,255,.025) 1px, transparent 1px); |
| background-size:56px 56px; |
| } |
| |
| /* ββ Layout ββ */ |
| .page-wrap { |
| position:relative; z-index:1; |
| min-height:100vh; |
| display:flex; flex-direction:column; |
| align-items:center; justify-content:center; |
| padding:2.5rem 1rem; |
| } |
| |
| /* ββ Brand ββ */ |
| .brand { text-align:center; margin-bottom:2.4rem; animation:fadeDown .7s ease both; } |
| |
| .brand-eyebrow { |
| font-size:.63rem; font-weight:600; |
| letter-spacing:.22em; text-transform:uppercase; |
| color:#64748b; margin-bottom:.9rem; |
| } |
| |
| .brand-title { |
| font-family:'Orbitron', sans-serif; |
| font-size:clamp(2.4rem,7vw,3.8rem); |
| font-weight:900; letter-spacing:.04em; line-height:1; |
| animation:rgb-glow 3s linear infinite; |
| margin-bottom:.7rem; |
| } |
| |
| .brand-sub { |
| font-size:.82rem; font-weight:300; |
| letter-spacing:.06em; color:var(--muted); |
| margin-bottom:1.1rem; |
| } |
| |
| .made-badge { |
| display:inline-block; |
| font-family:'Orbitron', sans-serif; |
| font-size:.68rem; font-weight:700; |
| letter-spacing:.3em; text-transform:uppercase; |
| padding:7px 26px; border:2px solid #00c8ff; border-radius:50px; |
| animation:rgb-glow 3s linear infinite, |
| rgb-border 3s linear infinite, |
| pulse-badge 3s ease-in-out infinite; |
| background:rgba(0,0,0,.15); cursor:default; |
| } |
| |
| /* ββ Card ββ */ |
| .card { |
| width:100%; max-width:460px; |
| background:var(--card); |
| border:1px solid rgba(255,255,255,.07); |
| border-radius:22px; padding:2.2rem 2rem; |
| position:relative; backdrop-filter:blur(28px); |
| box-shadow:0 40px 80px rgba(0,0,0,.65), |
| 0 0 0 1px rgba(255,255,255,.04) inset; |
| animation:fadeUp .7s ease .15s both; overflow:hidden; |
| } |
| |
| /* Rainbow top bar on card */ |
| .card::before { |
| content:''; position:absolute; top:0;left:0;right:0; height:2px; |
| background:linear-gradient(90deg,#ff0080,#ff8c00,#ffe600,#00ff88,#00c8ff,#a855f7,#ff0080); |
| background-size:200% auto; animation:shimmer 4s linear infinite; |
| } |
| |
| /* ββ RGB divider ββ */ |
| .rgb-line { |
| height:1px; margin:1.4rem 0; opacity:.45; |
| background:linear-gradient(90deg,transparent,#00c8ff,#a855f7,#ff0080,transparent); |
| background-size:200% 200%; animation:line-move 4s ease infinite; border-radius:2px; |
| } |
| |
| /* ββ Platform Pills ββ */ |
| .platforms { display:flex;gap:7px;justify-content:center;flex-wrap:wrap;margin-bottom:1.3rem; } |
| .pill { |
| display:inline-flex;align-items:center;gap:5px; |
| font-size:.68rem;font-weight:600;letter-spacing:.04em; |
| padding:4px 12px;border-radius:100px; |
| background:rgba(255,255,255,.04);border:1px solid rgba(255,255,255,.08); |
| color:#64748b;transition:color .2s,border-color .2s,background .2s;cursor:default; |
| } |
| .pill.ok { color:#00ff88;border-color:rgba(0,255,136,.25); } |
| .pill.warn { color:#fbbf24;border-color:rgba(251,191,36,.25); } |
| |
| /* ββ Quality Tags ββ */ |
| .quality-row { display:flex;gap:8px;margin-bottom:1.3rem; } |
| .q-tag { |
| flex:1;text-align:center;padding:8px 6px; |
| background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.06); |
| border-radius:10px;font-size:.66rem;font-weight:500; |
| letter-spacing:.06em;color:var(--muted);text-transform:uppercase; |
| } |
| .q-tag strong { |
| display:block;font-family:'Orbitron',sans-serif; |
| font-size:.72rem;color:#00c8ff;margin-bottom:2px;font-weight:700; |
| } |
| |
| /* ββ Input ββ */ |
| .input-wrap { position:relative;margin-bottom:1.1rem; } |
| .input-icon { |
| position:absolute;left:16px;top:50%;transform:translateY(-50%); |
| color:#00c8ff;font-size:.82rem;opacity:.6;pointer-events:none;transition:opacity .2s; |
| } |
| .url-input { |
| width:100%;background:rgba(255,255,255,.04); |
| border:1px solid rgba(255,255,255,.09);border-radius:12px; |
| padding:14px 16px 14px 42px;font-family:'Sora',sans-serif; |
| font-size:.9rem;color:var(--text);outline:none; |
| transition:border-color .25s,box-shadow .25s,background .25s; |
| } |
| .url-input::placeholder { color:var(--muted); } |
| .url-input:focus { |
| border-color:#00c8ff;background:rgba(0,200,255,.05); |
| box-shadow:0 0 0 3px rgba(0,200,255,.12); |
| } |
| |
| /* ββ Button ββ */ |
| .dl-btn { |
| width:100%;padding:15px;font-family:'Sora',sans-serif; |
| font-size:.92rem;font-weight:700;letter-spacing:.05em;color:#fff; |
| background:linear-gradient(135deg,#0ea5e9,#2563eb,#7c3aed); |
| background-size:200% auto;border:none;border-radius:12px;cursor:pointer; |
| display:flex;align-items:center;justify-content:center;gap:10px; |
| transition:background-position .4s,transform .15s,box-shadow .2s; |
| box-shadow:0 4px 24px rgba(14,165,233,.3);position:relative;overflow:hidden; |
| } |
| .dl-btn:hover { background-position:right center;box-shadow:0 6px 32px rgba(14,165,233,.5);transform:translateY(-1px); } |
| .dl-btn:active { transform:translateY(1px); } |
| .dl-btn:disabled { opacity:.65;cursor:wait; } |
| |
| .spinner { |
| width:16px;height:16px;border:2px solid rgba(255,255,255,.2); |
| border-top-color:#fff;border-radius:50%;display:none; |
| animation:spin .7s linear infinite; |
| } |
| |
| /* ββ Error ββ */ |
| .error-box { |
| margin-top:1.2rem;background:rgba(180,50,50,.1); |
| border:1px solid rgba(220,60,60,.25);border-radius:10px; |
| padding:12px 16px;font-size:.82rem;color:#f87171; |
| display:flex;align-items:flex-start;gap:10px;animation:fadeUp .3s ease both; |
| } |
| |
| /* ββ Footer ββ */ |
| .footer-note { |
| margin-top:1.8rem;text-align:center; |
| font-size:.7rem;color:var(--muted);opacity:.65;letter-spacing:.03em; |
| } |
| .footer-name { animation:rgb-glow 3s linear infinite; } |
| </style> |
| </head> |
| <body> |
| <div class="bg-scene"> |
| <div class="orb orb1"></div> |
| <div class="orb orb2"></div> |
| <div class="orb orb3"></div> |
| </div> |
| <div class="bg-grid"></div> |
| |
| <div class="page-wrap"> |
| |
| <div class="brand"> |
| <div class="brand-eyebrow">β‘ Universal Video Downloader</div> |
| <div class="brand-title">UniLoader</div> |
| <div class="brand-sub">Download anything. Instantly.</div> |
| <div class="made-badge">β¦ Made by Deepu β¦</div> |
| </div> |
| |
| <div class="card"> |
| |
| <div class="platforms"> |
| <span class="pill ok"><i class="fab fa-youtube"></i> YouTube</span> |
| <span class="pill ok"><i class="fab fa-tiktok"></i> TikTok</span> |
| <span class="pill warn"><i class="fab fa-instagram"></i> Instagram</span> |
| <span class="pill ok"><i class="fab fa-facebook"></i> Facebook</span> |
| <span class="pill ok"><i class="fas fa-video"></i> 1000+ Sites</span> |
| </div> |
| |
| <div class="quality-row"> |
| <div class="q-tag"><strong>720p</strong>Max Quality</div> |
| <div class="q-tag"><strong>MP4</strong>Format</div> |
| <div class="q-tag"><strong>Fast</strong>Direct</div> |
| </div> |
| |
| <div class="rgb-line"></div> |
| |
| <form method="POST" action="/download" onsubmit="handleSubmit()"> |
| <div class="input-wrap"> |
| <input type="url" name="url" required class="url-input" |
| placeholder="Paste video link hereβ¦" autocomplete="off"> |
| <i class="fas fa-link input-icon"></i> |
| </div> |
| <button type="submit" class="dl-btn" id="dlBtn"> |
| <i class="fas fa-download" id="btnIcon"></i> |
| <span id="btnText">Download Best Quality</span> |
| <div class="spinner" id="spinner"></div> |
| </button> |
| </form> |
| |
| {% if error %} |
| <div class="error-box"> |
| <i class="fas fa-circle-exclamation"></i> |
| <span>{{ error }}</span> |
| </div> |
| {% endif %} |
| |
| </div> |
| |
| <p class="footer-note"> |
| For personal use only | <span class="footer-name">β¦ Made by Deepu β¦</span> |
| </p> |
| </div> |
| |
| <script> |
| function handleSubmit() { |
| const btn = document.getElementById('dlBtn'); |
| const icon = document.getElementById('btnIcon'); |
| const text = document.getElementById('btnText'); |
| const spin = document.getElementById('spinner'); |
| btn.disabled = true; |
| icon.style.display = 'none'; |
| text.textContent = 'Preparing downloadβ¦'; |
| spin.style.display = 'block'; |
| } |
| </script> |
| </body> |
| </html> |
| """ |
|
|
| |
| |
| |
| @app.route("/", methods=["GET"]) |
| def index(): |
| return render_template_string(HTML_CODE) |
|
|
|
|
| @app.route("/download", methods=["POST"]) |
| def download(): |
| url = request.form.get("url", "").strip() |
| filename = f"video_{uuid.uuid4().hex[:8]}.mp4" |
|
|
| is_youtube = any(x in url for x in ["youtube.com", "youtu.be"]) |
| is_instagram = "instagram.com" in url |
| is_tiktok = "tiktok.com" in url |
|
|
| ydl_opts = { |
| "format": ( |
| "bv*[ext=mp4][height<=720]/" |
| "bv*[height<=720]/" |
| "best[height<=720]/best" |
| ), |
| "outtmpl" : filename, |
| "merge_output_format": "mp4", |
| "quiet" : True, |
| "no_warnings" : True, |
| "nocheckcertificate" : True, |
| "retries" : 5, |
| "fragment_retries" : 5, |
| "http_headers": { |
| "User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/120.0.0.0 Safari/537.36", |
| "Accept-Language": "en-US,en;q=0.9", |
| }, |
| } |
|
|
| |
| if is_youtube: |
| ydl_opts["extractor_args"] = { |
| "youtube": { |
| "player_client": ["android", "ios", "web"], |
| "player_skip" : ["webpage"], |
| } |
| } |
| ydl_opts["http_headers"]["User-Agent"] = ( |
| "com.google.android.youtube/17.36.4 (Linux; U; Android 12; GB) gzip" |
| ) |
|
|
| |
| if is_instagram: |
| ydl_opts["http_headers"] = { |
| "User-Agent" : "Instagram 219.0.0.12.117 Android (31/12; 420dpi; 1080x2400; samsung; SM-G991B; o1s; exynos2100; en_US; 346877738)", |
| "Accept" : "*/*", |
| "Accept-Language" : "en-US", |
| "X-IG-App-ID" : "936619743392459", |
| } |
|
|
| |
| if is_tiktok: |
| ydl_opts["http_headers"]["User-Agent"] = ( |
| "TikTok 26.2.0 rv:262018 (iPhone; iOS 14.4.2; en_US) Cronet" |
| ) |
|
|
| try: |
| with yt_dlp.YoutubeDL(ydl_opts) as ydl: |
| ydl.download([url]) |
|
|
| if not os.path.exists(filename): |
| raise FileNotFoundError("Download completed but output file not found.") |
|
|
| @after_this_request |
| def cleanup(resp): |
| try: |
| if os.path.exists(filename): |
| os.remove(filename) |
| except Exception: |
| pass |
| return resp |
|
|
| return send_file(filename, as_attachment=True) |
|
|
| except Exception as e: |
| if os.path.exists(filename): |
| os.remove(filename) |
|
|
| err = str(e).lower() |
| if "sign in" in err or "login" in err or "private" in err: |
| msg = "This video is private or requires login." |
| elif "429" in err or "too many" in err: |
| msg = "Rate limited. Please wait a few minutes and try again." |
| elif "instagram" in err: |
| msg = "Instagram blocked this download. Try uploading/downloading the video manually." |
| elif "copyright" in err or "blocked" in err: |
| msg = "This video is blocked or restricted." |
| else: |
| msg = str(e) |
|
|
| return render_template_string(HTML_CODE, error=msg) |
|
|
|
|
| |
| |
| |
| if __name__ == "__main__": |
| app.run(host="0.0.0.0", port=7860) |
|
|